初识 Containerd
Containerd 与 Docker
在之前的工作中,containerd 始终都是薛定谔的存在,只闻其名但没啥用武之地,直到前一段时间 K8s 官网发表要废除 Docker 时,才把这家伙又拉回到公众视线里。在技术层面上,我在之前的文章中也探讨过 CRI、containerd 以及 Docker 这些容器运行时之间的关系。有趣味的小伙伴能够去看一下这几篇文章:
了解容器运行时
K8s、CRI 与 container
当初只是单纯好奇在非技术层面上 CNCF 为啥要这么做呢,所以还是去八卦一下 Containerd 和 Docker 的前世今生以及爱恨情仇。
在几年之前,Docker 公司在容器技术畛域强势崛起,一家独大,Google、RedHat 这样的巨头们都产生了很大的危机感,因而他们想与 Docker 公司一起联结研发推动一个开源的容器运行时作为 Docker 技术的外围依赖。然鹅 Docker 公司很高冷的示意:我不干!巨头们听到这个反馈就很不爽啊,因而通过一些伎俩对 Docker 公司软硬兼施,使其将 libcontainer 捐给了开源社区,也就是当初的 runc,一个 low level 的容器运行时。此外,巨头们又成立了 CNCF 去反抗 Docker 公司的一家独大,CNCF 成立的思路很明确:在容器畛域干不过 Docker,那就搞容器下层的建设——容器编排,从此 K8s 诞生了。尽管 Docker 公司也尝试应用 Swarm 去反抗 K8s,但最终也失败了。
自此,K8s 缓缓成为云原生畛域的标配,其生态也越做越大、越做越欠缺。Docker 公司为了融入生态,开源了 Docker 的外围依赖 containerd。此外 K8s 为了对接下一层的容器,也因为其中立性搞了一个运行时接口,也就是 CRI(Container Runtime Interface),runc、containerd 等运行时都去反对此接口。因为过后的确没有啥 high level 的 runtime,oci-o 尽管反对 CRI 接口,但其性能太弱;containerd 也尚未成熟,而且其过后的定位是嵌入到零碎中,并非给终端用户应用;rkt 有本人的一套体系(起初这个我的项目也失败了)。只能临时为了适配 Docker 搞了个 shim,将 CRI 转换为 Docker API。K8s 和 Docker 进入了沉着期,单方都在各自优化本人,互不烦扰。然而平静之下仍是暗潮汹涌,CNCF 社区始终在不断完善 containerd,其定位也产生了扭转,由原来的零碎嵌入组件,变成了明天的“工业规范容器运行时”,并提供给终端用户应用。直到去年,K8s 发表废除应用 Docker,而改用 Containerd。其实除了这些商业因素,另一方面 K8s 曾经提供了标准接口对接底层容器运行时,不再想独自保护一个 相似于 Docker shim 的适配层去投合不同的运行时,这样做也无可非议(其实我看就是本人做大了,把锅扔给底层了 \~ 嘘 \~)。
Containerd 架构
好了,当初瓜也吃完了,回到技术层面上来看看 Containerd 的架构是什么样的。首先看 containerd 的性能:
- 官网声称本人反对 OCI 的镜像规范
- OCI 的容器运行时
- 镜像的推送和拉取
- 容器运行时生命周期治理
- 多租户的镜像存储
- 网络管理以及网络 namespace 治理,反对容器网络退出已有的 namespace
我就间接好家伙,Docker 外围性能该有的都有了。再看看架构图
Containerd 的设计是一个大的插件零碎,图中每一个虚线框其实就对应一个插件。
从下往上看,底层反对 arm 和 x86 架构,反对 Linux 和 windows 零碎。
两头 containerd 蕴含三层:Backend、core、API。其中 Backend 中 Runtime plugin 提供了容器运行时的具体操作,为了反对不同的容器运行时 containerd 也提供了一系列的 containerd-shim
,如之前的文章 K8s & kata container 原理实际 提到的 shim 就是这个。Core 则是外围局部,提供了各种性能的服务,其中比拟罕用的是 Content service
,提供对镜像中可寻址内容的拜访,所有不可变的内容都被存储在这里;Images Service
提供镜像相干的操作;Snapshot Plugin
: 用来治理容器镜像的文件系统快照。镜像中的每一个 layer 都会被解压成文件系统快照,相似于 Docker 中的 graphdriver
。再往上则是 API 层,通过 GRPC 与客户端连贯,这其中提供了给 Prometheus 应用 API 来进行监控,这里给个好评!
最上层则是各种客户端,包含 K8s 的 kubelet,containerd 本人的命令行 ctr 等。
简化一下上图:
简化后,Containerd 分为三大块:Storage 治理镜像文件的存储;Metadata 治理镜像和容器的元数据;另外由 Task 触发运行时。对外提供 GRPC 形式的 API 以及 Metrics 接口。
总结
其实 containerd 的社区始终很沉闷,这个我的项目的成熟离不开社区各位的奉献。这篇文章重点在于回顾一下历史,以及当初它当初的架构。作为使用者就临时不去钻研其外部设计,置信也是及其简单且精妙的。仅在应用方面,我发现 containerd 和 Docker 还是有很多共同之处的,那么下一篇文章则着重聊一聊 containerd 的实际吧。