Swarm 的最大特点,是完全使用 Docker 项目原本的容器管理 API 来完成集群管理。在部署了 Swarm 的多机
环境下,用户只需要使用原先的 Docker 指令创建一个容器,这个请求就会被 Swarm 拦截下来处理,然后通过
具体的调度算法找到一个合适的 Docker Daemon 运行起来。
2014年,docker 并购 Fig 项目,将其发展为现在的 Compose,使得容器的部署更加的便利 —— 可以使用配
置文件就可以完成较为复杂的容器的编排参数的配置。同年6月,Google 公司发布了 Kubernetes。
2015 年 6 月 22 日,由 Docker 公司牵头,CoreOS、Google、RedHat 等公司共同宣布,Docker 公司将
Libcontainer 捐出,并改名为 RunC 项目,交由一个完全中立的基金会管理,然后以 RunC 为依据,大家共同
制定一套容器和镜像的标准和规范。这套标准和规范,就是 OCI( Open Container Initiative )。OCI 的提
出,意在将容器运行时和镜像的实现从 Docker 项目中完全剥离出来。从 API 到容器运行时的每一层,
Kubernetes 项目都为开发者暴露出了可以扩展的插件机制,鼓励用户通过代码的方式介入到 Kubernetes 项目
的每一个阶段。Kubernetes 项目的这个变革的效果立竿见影,很快在整个容器社区中催生出了大量的、基于
Kubernetes API 和扩展接口的二次创新工作,比如:
微服务治理项目 Istio;
有状态应用部署框架 Operator;
还有像 Rook 这样的开源创业项目,它通过 Kubernetes 的可扩展接口,把 Ceph 这样的重量级产品封装成
了简单易用的容器存储插件。
二. Docker 容器的技术基础
1. 进程与 Linux Namespaces
为了达到在容器中排除其他进程,docker 利用了 Linux 的 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。除去 PID Namespace,
Linux 系统还提供了 Mount、UTS、IPC、Newwork 和 User 等 Namespace。这就是为什么容器中只能「看
到」自身容器内的进程的原因了。
2. 资源限制与Linux Cgroups
虽然在容器中 PID 为1的进程只能看到容器里的情况。但是从宿主机角度来看,它作为一个普通进程与其他进程
依然是平等关系,也就说它能够使用的资源(CPU、内存等),仍旧可以被宿主机上的其他进程占用。这种情
况导致了容器内的进程「隔离了但没有完全隔离」的尴尬,是不符合容器作为一个「沙盒」的特性的。
Linux Cgroups 的全称是 Linux Control Groups。它的最主要作用,就是限制一个进程组能够使用的资源上
限,包括 CPU、内存、磁盘、网络带宽等。比如:
blkio,为块设备设定 I/O 限制,一般用于磁盘等设备;
cpuset,为进程分配单独的 CPU 核和对应的内存节点;
memory,为进程设定内存使用的限制。等等
评论