Docker核心技术预览
本文简单介绍docker使用到的部分核心技术,但不做深入探究,因为每一个技术都是一个独立的项目,有机会再分别详细介绍。
Linux Namespace (实例隔离)
The purpose of each namespace is to wrap a particular global system resource in an abstraction that makes it appear to the processes within the namespace that they have their own isolated instance of the global resource.
每个用户实例之间相互隔离,互不影响。一般的硬件虚拟化方法给出的方法是VM,而LXC给出的方法是container,更细一点讲就是 kernel namespace。其中pid、net、ipc、mnt、uts、user等namespace将container的进程、网络、消息、文件系统、 UTS(“UNIX Time-sharing System”)和用户空间隔离开。
pid namespace
不同用户的进程就是通过pid namespace隔离开的,且不同 namespace 中可以有相同pid。所有的LXC进程在docker中的父进程为docker进程,每个lxc进程具有不同的namespace。同时由于允许嵌套,因 此可以很方便的实现 Docker in Docker。
net namespace
有了 pid namespace, 每个namespace中的pid能够相互隔离,但是网络端口还是共享host的端口。网络隔离是通过net namespace实现的, 每个net namespace有独立的 network devices, IP addresses, IP routing tables, /proc/net 目录。这样每个container的网络就能隔离开来。LXC在此基础上有5种网络类型,docker默认采用veth的方式将container中的虚 拟网卡同host上的一个docker bridge—docker0连接在一起。
ipc namespace
container中进程交互还是采用linux常见的进程间交互方法(interprocess communication – IPC), 包括常见的信号量、消息队列和共享内存。然而与VM不同,container 的进程间交互实际上还是host上具有相同pid namespace中的进程间交互,因此需要在IPC资源申请时加入namespace信息 – 每个IPC资源有一个唯一的 32bit ID。
mnt namespace
类似chroot,将一个进程放到一个特定的目录执行。mnt namespace允许不同namespace的进程看到的文件结构不同,这样每个 namespace 中的进程所看到的文件目录就被隔离开了。同chroot不同,每个namespace中的container在/proc/mounts`的信息只包含所 在namespace的mount point。
uts namespace
UTS(“UNIX Time-sharing System”) namespace允许每个container拥有独立的hostname和domain name, 使其在网络上可以被视作一个独立的节点而非Host上的一个进程。
user namespace
每个container可以有不同的 user 和 group id, 也就是说可以以container内部的用户在container内部执行程序而非Host上的用户。
有了以上6种namespace从进程、网络、IPC、文件系统、UTS和用户角度的隔离,一个container就可以对外展现出一个独立计算机 的能力,并且不同container从OS层面实现了隔离。 然而不同namespace之间资源还是相互竞争的,仍然需要类似ulimit来管理每个container所能使用的资源——LXC 采用的是cgroup。
参考
cgroup (资源配额)
cgroups 实现了对资源的配额和度量。cgroups 的使用非常简单,提供类似文件的接口,在/cgroup目录下新建一个文件夹即可新建一个group,在此文件夹中新建task文件,并将pid写入该文 件,即可实现对该进程的资源控制。具体的资源配置选项可以在该文件夹中新建子subsystem,{子系统前缀}.{资源项}是典型的配置方法, 如memory.usage_in_bytes就定义了该group 在subsystem memory中的一个内存限制选项。
我们主要关心cgroups可以限制哪些资源,即有哪些subsystem是我们关心。
cpu
在cgroup中,并不能像硬件虚拟化方案一样能够定义CPU能力,但是能够定义CPU轮转的优先级,因此具有较高CPU优先级的进程会更可能得到CPU 运算。 通过将参数写入cpu.shares,即可定义改cgroup的CPU优先级 – 这里是一个相对权重,而非绝对值。当然在cpu这个subsystem中还有其他可配置项,手册中有详细说明。
cpuacct
产生cgroup任务的cpu资源报告
cpuset
cpusets 定义了有几个CPU可以被这个group使用,或者哪几个CPU可以供这个group使用。在某些场景下,单CPU绑定可以防止多核间缓存切换,从而提高效率
memory
设置每个cgroup的内存限制以及产生内存资源报告
blkio
block IO相关的统计和限制,byte/operation统计和限制(IOPS等),读写速度限制等,但是这里主要统计的都是同步IO
net_cls
标记每个网络包以供cgroup方便使用
devices
允许或拒绝cgroup任务对设备的访问
freezer
暂停和恢复cgroup任务
参考
- PaaS Under the Hood, Episode 2: cgroups
- https://www.kernel.org/doc/Documentation/cgroups/
-
Control groups (cgroups)
LXC 旨在提供一个共享kernel的 OS 级虚拟化方法,在执行时不用重复加载Kernel,且container的kernel与host共享,因此可以大大加快container的 启动过程,并显著减少内存消耗。