容器基础
容器技术的核心功能,就是通过约束和修改进程的动态表现,从而为其创造出一个“边界”。
对于Docker等大多数Linux容器来说,Cgroups技术是用来制造约束的主要手段,而Namespace技术则是用来修改进程视图的主要方法。
隔离:Linux Namespace机制
Linux操作系统提供了PID、Mount、UTS、IPC、Network和User这些Namespace,用来对各种不同的进程上下文进行“障眼法”操作
-
PID Namespace
在Linux系统中创建线程的系统调用是clone(),比如:
int pid = clone(main_function, stack_size, SIGCHLD, NULL);
这个系统调用就会为我们创建一个新的进程,并且返回它的进程号pid。
而当我们用clone()系统调用创建一个新进程时,就可以在参数中指定CLONE_NEWPID参数,比如:
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
这时,新创建的这个进程将会“看到”一个全新的进程空间,在这个进程空间里,它的PID是1。
-
Mount Namespace
- Linux容器文件系统: rootfs
- rootfs只是一个操作系统所包含的文件、配置和目录,并不包括操作系统内核
- 保证一致性
- 切换进程的根目录(Change Root)
- 优先使用pivot_root系统调用,如果系统不支持,才会使用chroot
$ chroot $HOME/test /bin/bash
- Linux容器文件系统: rootfs
-
Network Namespace
限制:Linux Cgroups
Linux Cgroups的全称是Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等等。
简单来说,就是一个子系统目录加上一组资源限制文件的组合。
/sys/fs/cgroup
$ mount -t cgroup
cpuset on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cpu on /sys/fs/cgroup/cpu type cgroup (rw,nosuid,nodev,noexec,relatime,cpu)
cpuacct on /sys/fs/cgroup/cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct)
blkio on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
memory on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
...
# 限制进程在长度为cfs_period的一段时间内,只能被分配到总量为cfs_quota的CPU时间。
$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_period_us
100000
$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_quota_us
20000
# 把被限制的进程的PID写入container组里的tasks文件
$ echo 226 > /sys/fs/cgroup/cpu/container/tasks
#意味着这个Docker容器,只能使用到20%的CPU带宽。
分层镜像设计
-
可读写层
- 挂载方式为:rw
-
init层
- Init层是Docker项目单独生成的一个内部层,专门用来存放/etc/hosts、/etc/resolv.conf等信息
- 用户执行docker commit只会提交可读写层,所以是不包含这些内容的
-
只读层
-
挂载方式为:ro+wh,即readonly+whiteout
-
修改时,在可读写层创建一个whiteout文件,把只读层里的文件“遮挡”起来
比如,你要删除只读层里一个名叫foo的文件,那么这个删除操作实际上是在可读写层创建了一个名叫.wh.foo的文件。这样,当这两个层被联合挂载之后,foo文件就会被.wh.foo文件“遮挡”起来,“消失”了
-