容器的底层实现技术

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;

容器内部密码是什么 容器的设备代号_Network

 查看容器的 ID:

容器内部密码是什么 容器的设备代号_Network_02

 在 /sys/fs/cgroup/cpu/docker 目录中,Linux 会为每个容器创建一个 cgroup 目录,以容器长ID 命名

容器内部密码是什么 容器的设备代号_docker_03

 目录中包含所有与 cpu 相关的 cgroup 配置,文件 cpu.shares 保存的就是 --cpu-shares 的配置,值为 512

容器内部密码是什么 容器的设备代号_Network_04

 同样的,/sys/fs/cgroup/memory/docker 和 /sys/fs/cgroup/blkio/docker 中保存的是内存以及 Block IO 的 cgroup 配置;

namespace

在每个容器中,我们都可以看到文件系统,网卡等资源,这些资源看上去是容器自己的。拿网卡来说,每个容器都会认为自己有一块独立的网卡,即使 host 上只有一块物理网卡。这种方式非常好,它使得容器更像一个独立的计算机

Linux 实现这种方式的技术是 namespace。namespace 管理着 host 中全局唯一的资源,并可以让每个容器都觉得只有自己在使用它。换句话说,namespace 实现了容器间资源的隔离;

Linux 使用了六种 namespace,分别对应六种资源:Mount、UTS、IPC、PID、Network 和 User,下面我们分别讨论;

Mount namespace

让容器有自己的 / 目录,可以执行 mount 和 umount 命令;

UTS namespace

让容器有自己的 hostname。 默认情况下,容器的 hostname 是它的短ID,可以通过 -h 或 --hostname 参数设置;

容器内部密码是什么 容器的设备代号_User_05

IPC namespace

让容器拥有自己的共享内存和信号量(semaphore)来实现进程间通信,而不会与 host 和其他容器的 IPC 混在一起

PID namespace

容器拥有自己独立的一套 PID,这就是 PID namespace 提供的功能

Network namespace 让容器拥有自己独立的网卡、IP、路由等资源

User namespace 让容器能够管理自己的用户,host 不能看到容器中创建的用户

最后的最后,总结一下,容器的常用操作命令

create      创建容器  
run         运行容器  
pause       暂停容器  
unpause     取消暂停继续运行容器  
stop        发送 SIGTERM 停止容器  
kill        发送 SIGKILL 快速停止容器  
start       启动容器  
restart     重启容器  
attach      attach 到容器启动进程的终端  
exec        在容器中启动新进程,通常使用 "-it" 参数  
logs        显示容器启动进程的控制台输出,用 "-f" 持续打印  
rm          从磁盘中删除容器