掌握这些 Docker 原理知识,出去吹牛逼不再担忧了

在现代的开发流程中随处可见 Docker 的身影,Docker 提供了环境隔离、应用打包等功能让服务部署变得特别简单,本文将会浅析 Docker 背后所使用的技术,阅读完后,你能够搞清楚以下问题:linux

  • 1. 容器与虚拟机之间的差异
  • 2.Docker 资源隔离的原理
  • 3.Docker 资源限制的原理
  • 4.Docker 分层结构的原理

容器 vs 虚拟机

虚拟机(VM)是计算机系统的仿真器,经过软件模拟具备完整硬件系统功能的、运行在一个彻底隔离环境中的完整计算机系统,能提供物理计算机的功能。网络

虚拟机经过在当前的真实操做系统上经过 Hypervisor 技术进行虚拟机运行环境与体系的创建并经过该技术进行资源控制,一个性能较好的物理机一般能够承载多个虚拟机,每一个虚拟机都会有本身操做系统,如图 1.1 所示。app

图1.1
图 1.1

从图中能够看出,虚拟机提供了物理机硬件级别的操做系统隔离,这让不一样虚拟机之间的隔离很完全,但也须要消耗更多资源,而有时不须要这么完全的隔离,而更但愿不消耗那么多资源,此时就可使用容器技术。负载均衡

容器能够提供操做系统级别的进程隔离,以 Docker 为例,当咱们运行 Docker 容器时,此时容器自己只是操做系统中的一个进程,只是利用操做系统提供的各类功能实现了进程间网络、空间、权限等隔离,让多个 Docker 容器进程相互不知道彼此的存在,如图 1.2 所示。运维

图1.2
图 1.2

虚拟机技术与容器技术的最大区别在于:多个虚拟机使用多个操做系统内核,而多个容器共享宿主机操做系统内核ssh

Docker 资源隔离:Linux Namespace

Linux Namespace(Linux 命名空间)是 Linux 内核(Kernel)提供的功能,它能够隔离一系列的系统资源,如 PID(进程 ID,Process ID)、User ID、Network、文件系统等。编辑器

若是你熟悉 Linux,你可能会联想到 linux 中的 chroot 命令,该命令容许将当前目录修改为根目录(即根目录 / 的挂载点切换了),至关于文件系统被隔离了,Namespace 也具备类似的功能,但更增强大。工具

目前 Linux 主要提供 6 中不一样类型的 Namespace,以下表所示。性能

Namespace 类型 描述 系统调用 flags(标记)
Mount Namespace 隔离文件系统挂载点 CLONE_NEWS
UTS Namespace 隔离 HostName 与 DomianName CLONE_NEWUTS
IPC Namespace 隔离进程间通讯 CLONE_NEWIPC
PID Namespace 隔离进程 ID CLONE_NEWPID
Network Namespace 隔离网络 CLONE_NEWNET
User Namespace 隔离用户和用户组 CLONE_NEWUSER

以一个具体的例子来解释 Namespace 的做用,假设你有一台性能很是好的计算机,你向用户出售本身的计算机的资源,每一个用户买到一个 ssh 实例,为了不不一样客户之间相互干扰,你可能会对不一样用户进行权限限制,让用户只能访问本身 ssh 实例下的资源。spa

但有些操做须要 root 权限,而咱们不能将 root 权限提供给用户,此时就可使用 Namespae 了,经过 User Namespace 对 UID 进行隔离,具体而言,UID 为 x 的用户在该 Namespace 中具备 root 权限,但在真实物理机中,他依旧是 UID 为 x 的用户,这就解决了用户间隔离的问题。

此外还能够经过 PID Namespace 对 PID 进行隔离,从该 Namespace 中的用户角度看,Namespace 中就像一台新的 Linux,有本身的 init 进程(初始进程,PID 为 1),其余进程的 PID 在 init 进程 PID 上递增,如图 1.3 所示。

图1.3
图 1.3

图中,进程 3 在父命名空就中 PID 为 3,而在子命名空间中,其 PID 为 1,用户在该子命名空间中内看进程 3 就像 init 进程同样。

Linux 提供了 3 个系统 API 方便咱们使用 Namespace:

  • clone () 建立新进程,根据系统调用 flags 来决定哪一种类型 Namespace 将会被建立,而该进程的子进程也会包含这些 Namespace。
  • setns () 将进程加入到已存在的 Namespace 中。
  • unshare () 将进程移出某个 Namespace

Docker 利用 Linux Namespace 功能实现多个 Docker 容器相互隔离,具备独立环境的功能,Go 语言对 Namespce API 进行了相应的封装,从 Docker 源码中能够看到相关的实现。

Docker 资源限制:Linux Cgroups

Docker 经过 Linux Namespace 帮进程隔离出本身单独的空间 / 资源,那 Docker 如何限制进程对这些资源的使用呢?

Docker 容器本质依旧是一个进程,多个 Docker 容器运行时,若是其中一个 Docker 进程占用大量 CPU 和内存就会致使其余 Docker 进程响应缓慢,为了不这种状况,能够经过 Linux Cgroups 技术对资源进行限制。

Linux Cgroups(Linux Contorl Groups,简称 Cgroups)能够对一组进程及这些进程的子进程进行资源限制、控制和统计的能力,其中包括 CPU、内存、存储、网络、设备访问权限等,经过 Cgroups 能够很轻松的限制某个进程的资源占用而且统计该进程的实时使用状况。

Cgroups 由 3 个组件构成,分别是 cgroup(控制组)、subsystem(子系统)以及 hierarchy(层级树),3 者相互协同做用。

  • cgroup 是对进程分组管理的一种机制,一个 cgroup 一般包含一组(多个)进程,Cgroups 中的资源控制都以 cgroup 为单位实现。
  • subsystem 是一组(多个)资源控制的模块,每一个 subsystem 会管理到某个 cgroup 上,对该 cgroup 中的进程作出相应的限制和控制。
  • hierarchy 会将一组(多个)cgroup 构建成一个树状结构,Cgropus 能够利用该结构实现继承等功能

3 者具体如何相互协同做用?

Cgroups 会将系统进程分组(cgroup)而后经过 hierachy 构建成独立的树,树的节点就是 cgroup(进程组),每颗树均可以与一个或多个 subsystem 关联,subsystem 会对树中对应的组进行操做。

有个几个规则须要注意。

1. 一个 subsystem 只能附加到一个 hierarchy,而一个 hierarchy 能够附加多个 subsystem 2. 一个进程能够做为多个 cgroup 的成员,但这些 cgroup 只能在不一样的 hierarchy 中 3. 一个进程 fork 出子进程,此时子进程与父进程默认是在同一个 cgroup 中,能够根据须要移动到其余 cgroup

Docker 分层结构:Union File System

咱们都知道 Docker 镜像是一种分层结构,每一层构建在其余层之上,从而实现增量增长内容的功能,这是如何实现的?

要理解这个问题,首先须要理解 Union File System(简称,UnionFS),它是为 Linux 系统设计的将其余文件系统联合到一个联合挂载点的文件系统服务。UnionFS 使用 branch(分支)将不一样文件系统的文件和目录透明地叠加覆盖,造成一个单一一致的文件系统,此外 UnionFS 使用写时复制(Copy on Write,简称,CoW)技术来提升合并后文件系统的资源利用。(后续的文章会介绍 CoW 技术)

Docker 使用的第一种存储驱动为 AUFS(Advanced Multi-layered unification filesytem),AUFS 彻底重写了早期的 UnionFS,目的是提升其性能与可靠性,此外还引入了如 branch 负载均衡等新功能。

与 UnionFS 相似,AUFS 能够在基础的文件系统上增量的增长新的文件系统,经过叠加覆盖的形式最终造成一个文件系统。一般 AUFS 最上层是可读可写层,而其余层只是只读层,每一层都只是一个普通的文件系统。

Docker 镜像分层、增量增长等功能正是经过利用 AUFS 的分层文件系统结构、增量增长等功能实现,这也致使了运行 Docker 容器若是没有指定 volume(数据卷)或 bind mount,则 Docker 容器结束后,运行时产生的数据便丢失了。

Docker 存储驱动除了 AUFS 外,还有 OverlayFS、Devicemapper、Btrfs、ZFS 等,本文很少讨论。

总结

至此,咱们知道了 Docker 核心功能的基本原理,Docker 利用 Linux Namespace 进行网络、用户、进程等不一样资源的隔离,使用 Linux Cgroups 技术对资源的使用进行限制与监控,经过 AUFS 等存储驱动实现分层结构与增量更新等功能。

现实世界中的 Docker 还使用了不少其余技术,但最核心且最基本的就是 Linux Namespace、Linux Cgrpus 与 AUFS。

Docker 在当前的开发流程中已成必备工具,容器带来的优点解放了运维人员也避免了开发人员遇到开发环境与线上环境不一致时致使问题的状况。目前容器编排技术(K8s)快速发展,Docker 容器技术在将来也将会进一步发展,它值得咱们花时间与精力去了解其本质。

相关文章
相关标签/搜索