底层实现原理

docker 虚拟化技术由这些技术支撑:namespace、Cgroups、union filesystem

一、Namespace

命名空间(namespace)是 linux 提供的用于隔离进程、网络、挂载点、进程间通信等资源的方法。docker 就是通过 linux 的 namespace 对不同的容器实现了隔离。

Linux 的命名空间机制提供了七种不同的命名空间,包括:clone_newcgroup、clone_newipc、clone_newnet、clone_newns、clone_newpid、clone_newuser、clone_newuts。通过这 7 个选项我们能在创建新的进程时,设置新进程应该在那些资源上与宿主机器进行隔离。

1. 进程隔离

进程 pid 隔离的实现,在使用 clone 系统调用创建一个新进程时,在参数中指定 CLONE_NEWPID 参数。新创建的这个进程将会 “看到” 一个全新的进程空间,在这个进程空间中,他的 pid 为 1。也就实现了针对进程 PID 的命名空间。在此命名空间中,看不到宿主机中真正的进程空间,也看不到其他命名空间的情况。

2. 网络隔离

3. 挂载点隔离

在新的进程中创建隔离的挂载点需要在 clone 系统调用中传入 CLONE_NEWNS

二、Cgroups

全称为 Linux Control Group。他最主要的作用就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等。

三、Union Filesystem

为了解决镜像的使用问题。

UnionFS 其实是一种为 Linux 操作系统设计的用于把多个文件系统联合到同一个挂载点的文件系统服务。

联合文件系统,能够将不同文件夹中的层联合到同一个文件夹中。整个联合的过程称为 “联合挂载”。

其中每一个镜像层或者容器层都是 /var/lib/docker 目录下的一个子文件夹;在 docker 中,所有镜像层和容器层的内容都存储在 /var/lib/docker/aufs/diff/ 目录中。而 /var/lib/docker/aufs/layers/ 中存储着镜像层的元数据,每一个文件都保存着镜像层的元数据,最后的 /var/lib/docker/aufs/mnt/ 包含镜像或者容器层的挂载点,最终会被 Docker 通过联合的方式进行组装。

上面的这张图片非常好的展示了组装的过程,每一个镜像层都是建立在另一个镜像层之上的,同时所有的镜像层都是只读的,只有每个容器最顶层的容器层才可以被用户直接读写,所有的容器都建立在一些底层服务(Kernel)上,包括命名空间、控制组、rootfs 等等,这种容器的组装方式提供了非常大的灵活性,只读的镜像层通过共享也能够减少磁盘的占用。