作者:小姐姐养的狗 来源:高效运维
一位同学曾给我打比方:宿主机就好比一间大房子,docker 把它变成了N个小隔断。在这些小隔断之间,有独立的卫生间、小床、电视…
麻雀虽小,五脏俱全,这个比喻非常的贴切。Linux 提供了非常全面的隔离机制,使得每个小隔间互不影响。即使隔壁小间满室春光,我的小房间一样的冷清,对我毫无影响。
Docker 能实现这些功能,依赖于 chroot、namespace、cgroup 等三种老技术。我们本篇文章,就先聊一下 namespace 方面的东西。毕竟隔离是容器的第一要素。
Linux 的内核,提供了多达8种类型的 Namespace。在这些独立的 Namespace 中,资源互不影响,隔离措施做得非常好。
1. 8种类型
我们先来看一下,Linux都支持哪些Namespace。可以通过 unshare 命令来观察到这些细节。在终端执行 man unshare,将会出现这些 Namespace 的介绍。
Mount(mnt) 隔离挂载点
Process ID (pid) 隔离进程 ID
Network (net) 隔离网络设备,端口号等
Interprocess Communication (ipc) 隔离 System V IPC 和 POSIX message queues
UTS Namespace(uts) 隔离主机名和域名
User Namespace (user) 隔离用户和用户组
另外,Linux 在 4.6 版本,5.6 版本,分别加入了 cgroups 和 Time 两种隔离类型,加起来就有8种。
Control group (cgroup) Namespace 隔离 Cgroups 根目录 (4.6版本加入)
Time Namespace 隔离系统时间 (5.6版本加入)
2. 1个例子
通过unshare命令,可以快速建立一些隔离的例子,我们拿最简单直观的pid namespace来看一下它的效果。
众所周知,Linux 进程号为1的,叫做systemd进程。但在 Docker 中,我们通过执行ps命令,却只能看到非常少的进程列表。
执行下面的命令,进入隔离环境,并将 bash 作为根进程:
unshare --pid --fork --mount-proc /bin/bash
效果如图所示。可以看到,我们的 bash,已经成为了1号进程,而宿主机和其他隔离环境的进程信息,在这里是不可见的。
先在隔离环境中,执行sleep 1000。再开一个终端,在宿主机上执行pstree,我们将会看到这个隔离环境的进行信息。
接下来,在宿主机上,把 sleep 对应进程的命名空间信息,和宿主机的命名空间信息作一下对比。可以看到,它们的pid namespace,对应的数值是不同的。
下面给出其他 namespace 的实验性命令,你可以实际操作一下。
3. 试验一下
unshare --mount --fork /bin/bash
创建mount namespace,并在每个不同的环境中,使用不同的挂载目录。
unshare --uts --fork /bin/bash
uts 可以用来隔离主机名称,允许每个 namespace 拥有一个独立的主机名,你可以通过hostname命令进行修改。
unshare --ipc --fork /bin/bash
IPC Namespace 主要是用来隔离进程间通信的。Linux 的进程间通信,有管道、信号、报文、共享内存、信号量、套接口等方式。使用了 IPC 命名空间,意味着跨 Namespace 的这些通信方式将全部失效!不过,这也正是我们所希望得到的。
unshare --user -r /bin/bash
用户命名空间,就非常好理解了。我们可以在一个 Namespace 中建立 xjjdog 账号,也可以在另外一个 Namespace 中建立 xjjdog 账号,而且它们是相互不影响的。
unshare --net --fork /bin/bash
net namespace,这个就非常有用了。它可以用来隔离网络设备、IP 地址和端口等信息。
End
可以看到,通过各种 Namespace,Linux 能够对各种资源进行精细化的隔离。Docker本身也是一个新瓶装旧酒的玩具。Docker 的创新之处,在于它加入了一个中央仓库,并封装了很多易用的命令。
你可能会发现,到目前为止,我们并没有对 Cpu和内存的资源使用进行隔离,也没有对应的 Namespace 来解决这些问题。
资源限制的功能,是使用Cgroups进行限额配置来完成的,和Namespace没什么关系。我们将在后面的文章,介绍 Cgroups 这项技术。
最后,附上 Docker 的一张生命周期图。来源(http://docker-saigon.github.io/post/Docker-Internals/ )。
Docker 发展到现在,应用工具链已经非常成熟了,很多同学已经驾轻就熟,如果你对容器技术非常感兴趣,不如多看一下最底层的原理。这样,不管是谷歌推自己的容器,还是继续使用 docker,都能快速把它掌握。