实战Containerd系列之1 Docker、Containerd、Kubernetes之间的关系

153次阅读

共计 2015 个字符,预计需要花费 6 分钟才能阅读完成。

话说Kubernetes都要弃用 Dockershim 了,因此是时候学习 Containerd 了。 本文先简单整理一下 Kubernetes、Docker、Containerd 之间的渊源和纠葛。

1 Docker,OCI 和 Containerd

这里略过早期 Docker 的发展历史,大概就是在 docker 如日中天的时候,社区要搞容器化标准,成立了 OCI(Open Container Initiaiv),OCI主要包含两个规范,一个是容器运行时规范(runtime-spec),一个是容器镜像规范(image-spec)。 docker 的公司也在 OCI 中,这里略过在推动标准化过程中各大厂各自心里的"小算盘"和"利益考虑",docker在这个过程中由一个庞然大物逐渐拆分出了containerdrunc等项目, docker公司将runc捐赠给了OCI,后来将 containerd 捐赠给了 CNCF。

  • runc是什么? runc是一个轻量级的命令行工具,可以用它来运行容器。runc遵循OCI标准来创建和运行容器,它算是第一个OCI Runtime标准的参考实现。

  • containerd 是什么?containerd 的自我介绍中说它是一个开放、可靠的容器运行时,实际上它包含了单机运行一个容器运行时的功能。 containerd 为了支持多种 OCI Runtime 实现,内部使用containerd-shim,shim英文翻译过来是"垫片"的意思,见名知义了,例如为了支持runc,就提供了containerd-shim-runc

经过上面的发展,docker 启动一个容器的过程大致是下图所示的流程:

实战Containerd系列之1 Docker、Containerd、Kubernetes之间的关系

从上图可以看出,每启动一个容器,实际上是 containerd 启动了一个containerd-shim-runc进程,即使containerd 的挂掉也不会影响到已经启动的容器。

2 Kubernetes,Docker 和 Containerd

Kubernetes 的出现是为了解决容器编排的问题,在早期为了支持多个容器引擎,是在Kubernetes内部对多个容器引擎做兼容,例如 kubelet 启动一个docker-manager的进程直接调用docker的api进行容器的创建。

实战Containerd系列之1 Docker、Containerd、Kubernetes之间的关系

后来 k8s 为了隔离各个容器引擎之间的差异,在 docker 分出 containerd 后,k8s 也搞出了自己的容器运行时接口(CRI),CRI 的出现是为了统一k8s与不同容器引擎之间交互的接口,与 OCI 的容器运行时规范不同,CRI 更加适合k8s,不仅包含对容器的管理,还引入了 k8s 中 Pod 的概念及对 Pod 生命周期的管理。 k8s 开始把 containerd 接入CRI标准。kubelet 通过 CRI 接口调用docker-shim,进一步调用 docker api。此时在每个 k8s 节点上 kubelet 大致按下图流程启动容器:

实战Containerd系列之1 Docker、Containerd、Kubernetes之间的关系

为了更好的将 containerd 接入到 CRI 标准中,k8s 又搞出了cri-containerd项目,cri-containerd是一个守护进程用来实现 kubelet 和 containerd 之间的交互,此时 k8s 节点上 kubelet 大致按下图流程启动容器:

实战Containerd系列之1 Docker、Containerd、Kubernetes之间的关系

在上图中 cri-containerd 和 containerd 还是两个独立的进程,他们之间通过 gRPC 通信,后来在 Containerd 1.1 时,将 cri-containerd 改成了 Containerd 的 CRI 插件,CRI 插件位于 containerd 内部,这让 k8s 启动 Pod 时的通信更加高效,此时 k8s 节点上 kubelet 大致按下图流程启动容器:

实战Containerd系列之1 Docker、Containerd、Kubernetes之间的关系

为了更贴近 OCI,k8s 又搞了一个轻量级的容器运行时cri-o,所以在 k8s "抛弃" dockershim 后,可供我们选择的容器运行时有 containerd 和 cri-o。

小结一下 kubelet 启动容器的发展历程:

早期: kubelet --> docker-manager --> docker
中期: kubelet -CRI-> docker-shim --> docker --> containerd --> runc
中期: kubelet -CRI-> cri-containerd --> containerd --> runc
当前: kubelet -CRI-> containerd(CRI plugin) --> runc
当前: kubelet -CRI-> cri-o --> runc

3.总结

Docker 是一个伟大的项目,在理清 Kubernetes、Containerd 和 Docker 之间的关系后,可以看出 docker 为 OCI 贡献了runtime spec的标准参考实现 runc,另外 OCI 的 image spec 镜像规范也是以 Docker 镜像规范V2为基础制定的,docker 还为 k8s 贡献了一个稳定可靠的容器运行时 containerd。 虽然 k8s 后续将不再支持 dockershim,但 Docker本身仍然可以作为本地开发、测试和单机容器部署的利器。

正文完
 
mervinwang
版权声明:本站原创文章,由 mervinwang 2023-01-13发表,共计2015字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
文章搜索