0%

docker 实现原理

Linux Namespace资源隔离

Linux命名空间是全局资源的一种抽象,将资源发到不同的命名空间中,各个命名空间中的资源时相互隔离的。命名空间有以下几种类别

分类 系统调用参数 相关内核版本
Mount Namespace CLONE_NEWNS Linux 2.4.19
UTS Namespace CLONE_NEWUTS Linux 2.6.19
IPC Namespace CLONE_NEWIPC Linux 2.6.19
PID Namespace CLONE_NEWPID Linux 2.6.24
Network Namespace CLONE_NEWNET 始于Linux 2.6.24 完成于2.6.29
User Namespace CLONE_NEWUSER 始于Linux2.6.23 完成于3.8

查看进程的namespace

1
2
3
4
5
6
7
8
9
10
ls -l /proc/<pid>/ns

lrwxrwxrwx 1 xiangwei.flower xiangwei.flower 0 Apr 3 12:27 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 xiangwei.flower xiangwei.flower 0 Apr 3 12:27 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 xiangwei.flower xiangwei.flower 0 Apr 3 12:27 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 xiangwei.flower xiangwei.flower 0 Apr 3 12:27 net -> net:[4026532057]
lrwxrwxrwx 1 xiangwei.flower xiangwei.flower 0 Apr 3 12:27 pid -> pid:[4026531836]
lrwxrwxrwx 1 xiangwei.flower xiangwei.flower 0 Apr 3 12:27 pid_for_children -> pid:[4026531836]
lrwxrwxrwx 1 xiangwei.flower xiangwei.flower 0 Apr 3 12:27 user -> user:[4026531837]
lrwxrwxrwx 1 xiangwei.flower xiangwei.flower 0 Apr 3 12:27 uts -> uts:[4026531838]

CGroup资源限制

通过Namespace可以保证容器之间的隔离,但是无法控制容器可以占用多少资源,如果其中的某一个容器正在执行CPU计算密集型任务,那么就会影响其他容器任务的性能与执行效率,导致多个容器相互影响并且抢占资源。

CGroup(Control Group)就是能够隔离宿主机上的物理资源,例如CPU、内存、磁盘I/O和网络带宽。而我们需要做的就是把容器进程加入到指定的CGroup中。

UnionFS 联合文件系统

Linux Namespace和cgroup分别解决了容器的资源隔离与资源限制,那么容器是很轻量的,通常每台机器中可以运行几十上百个容器,这些容器可能会公用一个image。所以容器在启动的时候,不可能各自将这个image复制一份。Docker在内部使用镜像分层存储以及UnionFS来实现多个容器共用一个镜像。

  • 镜像分层存储:docker镜像是由一系列的层组成的,每层代表Dockerfile中的一条指令,比如下面的Dockerfile文件:

    1
    2
    3
    4
    FROM ubuntu:15.04
    COPY . /app
    RUN make /app
    CMD python /app/app.py

    这个dockerfile文件最终生成镜像的时候会生成四层,这四层是不可写的,而通过镜像实例化容器的过程,其实就是在就是在这四层之上添加了一个可写层,也就是我们通常说的容器层。而对容器层的操作,主要是利用了写时复制(CoW,copy on write)的技术。例如,如果当前操作会改变下面四层的某一层,docker会先将该层拷贝到容器层,然后再在容器层中进行操作。

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