容器相关规范

Catalogue
  1. 1. 容器引擎
  2. 2. OCI
  3. 3. CRI
  4. 4. CNI
  5. 5. 参考资料

容器无疑是近年来云计算中最火热的关键词。随着docker的大热,docker、oci、runc、containerd等等名词也逐渐传播开来。这么多的名词,也容易让人混淆。本文对相关名词和其之间的联系进行一下梳理和总结,方便大家更好地理解。

容器引擎

容器引擎,或者说容器平台,不仅包含对于容器的生命周期的管理,还包括了对于容器生态的管理,比如对于镜像等。现在的docker、rkt以及阿里推出的pouch均可属于此范畴。

Docker可以分为两个阶段来理解。docker版本为1.2时,当时的docker的主要作用是容器的生命周期管理和镜像管理,当时的docker在功能上更趋近于现在的container
runtime。而后来,随着docker的发展,docker就不再局限于容器的管理,还囊括了存储(volume)、网络(net)等的管理,因此后来的docker更多的是一个容器及容器生态的管理平台。

OCI

OCI全称Open Container Initiative,开放容器联盟。Linux基金会于2015年6月成立OCI组织,旨在围绕容器格式和运行时制定一个开放的工业化标准,目前主要有两个标准文档:容器运行时标准 (runtime spec)和 容器镜像标准(image spec)

容器运行时标准中对于容器的状态描述,以及对于容器的创建、删除、查看等操作进行了定义。runc是对于OCI标准的一个参考实现,是一个可以用于创建和运行容器的CLI(command-line interface)工具。runc直接与容器所依赖的cgroup/linux kernel等进行交互,负责为容器配置cgroup/namespace等启动容器所需的环境,创建启动容器的相关进程。

为了兼容OCI标准,docker也做了架构调整。将容器运行时相关的程序从docker daemon剥离出来,形成了containerd。containerd向docker提供运行容器的API,二者通过grpc进行交互。containerd最后会通过runc来实际运行容器。

CRI

CRI全称Container Runtime Interface,容器运行时接口,是 Kubernetes 提供的 API,用于同容器运行时进行通信以创建/删除容器化应用程序。

kubernetes在初期版本里,就对多个容器引擎做了兼容,因此可以使用docker、rkt等容器引擎对容器进行管理。以docker为例,kubelet中会启动一个docker manager,通过直接调用docker的api进行容器的创建等操作。

在kubernetes 1.5版本之后,kubernetes推出了自己的运行时接口api–CRI(container runtime interface)。cri接口的推出,隔离了各个容器引擎之间的差异,而通过统一的接口与各个容器引擎之间进行互动。

在cri开始之初,主要是支持docker和rkt两种。其中kubelet是通过cri接口,调用docker-shim,并进一步调用docker api实现的。后来为了要直接支持containerd和runC,kubernetes分别又孵化了cri-containerdcri-o。他们关系如下:

2020年12月更新:

在2013年,Docker以提供镜像打包的创新技术实现了“一次构建、处处运行”的软件交付方式,开启了一个全新的容器时代。面对平台化的竞争,Docker 推出了调度引擎 Swarm,但 Swarm 从未真正流行起来,因为整个行业更倾向于采用 Kubernetes,这是 Docker 第一次死亡:它失去了平台之战。2016 年 9 月,Google 和 RedHat 联合宣布了“fork Docker”,也就是后来的 CRI-O 项目,这就是这次弃用事件的起始,同时也宣告了竞争的结束。

Kubernetes 要弃用 Docker,因为kubelet只需要用CRI实现对容器的生命周期管理,而Docker包含网络、存储卷等不需要的功能,而这些用不到的功能本身就可能带来安全隐患。事实上,您拥有的功能越少,攻击面也就越小。

CRI 运行时的实现方案主要有两种:

  • containerd:如果大家只是想从 Docker 迁移出来,那么 containerd 就是最好的选择,可以完成所有“运行时”工作,如上图所示。containerd 还属于全开源软件,因此您可以在 GitHub 上查看说明文档甚至参与项目贡献。https://github.com/containerd/containerd/
  • CRI-O: 是主要由 Red Hat 员工开发的 CRI 运行时。它的最大区别在于并不依赖于 Docker,而且目前已经在 Red Hat OpenShift 中得到使用。CRI-O 的优势在于其采用极简风格,或者说它的设计本身就是作为“纯 CRI”运行时存在。不同于作为 Docker 组成部分的 containerd,CRI-O 在本质上属于纯 CRI 运行时、因此不包含除 CRI 之外的任何其他内容。https://github.com/cri-o/cri-o

CNI

全称:Container Network Interface,容器网络接口

CNI(Container Network Interface) 是 google 和 CoreOS 主导制定的容器网络标准,它本身并不是实现或者代码,可以理解成一个协议。这个标准是在 rkt 网络提议的基础上发展起来的,综合考虑了灵活性、扩展性、ip 分配、多网卡等因素.

这个协议连接了两个组件:容器管理系统和网络插件。它们之间通过 JSON 格式的文件进行通信,实现容器的网络功能。具体的事情都是插件来实现的,包括:创建容器网络空间(network namespace)、把网络接口(interface)放到对应的网络空间、给网络接口分配 IP 等等

参考资料