前戏
为了更好地理解容器的特性,可以刨析容器的底层实现技术。cgroup
和namespace
是最重要的两种技术。cgroup实现资源限额,namespace实现资源隔离。
cgroup
cgroup全称Control Group。Linux操作系统通过cgroup可以设置进程使用CPU、内存和IO资源的限额,例如: --cpu-shares、-m、--device-write-bps实际上就是在配置cgroup
cgroup是什么样的?我们可以在 /sys/fs/cgroup中找到它。还是用例子来说明,启动一个容器,设置 --cpu-shares=512
查看容器的ID
在 /sys/fs/cgroup/cpu/docker目录中,Linux会为每个容器创建一个cgroup目录,以容器长ID命名
注:
目录中包含所有与cpu相关的cgroup配置,文件cpu.shares保存的就是 --cpu-shares的配置,值为512。同样的,/sys/fs/cgroup/memory/docker和 /sys/fs/cgroup/blkio/docker中保存的是内存以及Block IO的cgroup配置。
namespace
简介:
在每个容器中,我们都可以看到文件系统、网卡等资源,这些资源看上去是容器自己的。拿网卡来说,每个容器都会认为自己有一块独立的网卡,即使宿主机上只有一块物理网卡。这种方式非常好,它使得容器更像一个独立的计算机。
Linux实现这种方式的技术是namespace。namespace管理着host中全局唯一的资源,并可以让每个容器都觉得只有自己在使用它。换句话说,namespace实现了容器间资源的隔离。
inux使用了6种namespace,分别对应6种资源:Mount、UTS、IPC、PID、Network和User
Mount namespace
Mount namespace让容器看上去拥有整个文件系统(用来隔离文件系统的挂载点)。容器有自己的/目录,可以执行mount和umount命令。当然我们知道这些操作只在当前容器中生效,不会影响到host和其他容器。
UTS namespace
UTS namespace让容器有自己的hostname(主机名)。默认情况下,容器的hostname是它的短ID,可以通过 -h或 --hostname参数设置
IPC namespace
IPC namespace让容器拥有自己的共享内存和信号量(semaphore)来实现进程间通信,而不会与host和其他容器的IPC混在一起。
PID namespace
容器在宿主机中以进程的形式运行
注:所有容器的进程都挂在dockerd进程下,同时也可以看到容器自己的子进程。
进程的PID不同于host中对应进程的PID,容器中PID=1的进程当然也不是host的init进程。也就是说:容器拥有自己独立的一套PID,这就是PID namespace提供的功能。
Network namespace
Network namespace让容器拥有自己独立的网卡、IP、路由等资
User namespace
User namespace让容器能够管理自己的用户,宿主机不能看到容器中创建的用户
注:在容器中创建了用户cjk,但宿主机t中并不会创建相应的用户