Kubernetes1.24 版本发布时,正式宣布弃用 Dockershim,转向 Containerd 作为默认的容器运行环境。Kubernetes 以 CRI(Container Runtime Interface) 容器运行时接口制定接入准则,用户可以使用 Containerd、CRI-O、CRI- Dockerd 及其他容器运行时作为 Kubernetes 的容器引擎。
Docker 在早期没有实现 Container Runtime Interface (CRI),而 CRI 是 Kubernetes 后来增加的对额外运行时的支持标准。Dockershim 的存在是为了支持将 Docker 硬编码到 Kubernetes 中,但随着容器化成为行业标准,Kubernetes 项目增加了对额外运行时的支持,比如通过 Container Runtime Interface (CRI) 容器运行时接口来支持运行容器。因此,在 Kubernetes1.20 版本发布的时候提到未来会弃用 Dockershim 引擎,而在 Kubernetes1.24 版本发布时,?正式弃用之。
containerd 是一种容器运行时引擎,原属于 Docker 的组件的一部分,主要提供容器生命周期管理(从创建到销毁容器)、拉取和推送镜像、存储管理(管理镜像及容器数据的存储)、调用 runc 容器运行等,现已由开源社区拆分脱离出来单独作为容器运行时项目。
在 Kubernetes 中,Containerd 作为容器运行环境,负责管理 Pod 的生命周期,包括容器的创建、启动、停止和删除等操作。与 Dockershim 相比,Containerd 具有更好的性能、更强的可扩展性以及更简洁的架构。
Docker Client 和 Docker Daemon:Docker Client 是 Docker 的客户端,它可以通过命令行或 API 向 Docker Daemon 发送请求。Docker Daemon 是 Docker 的核心组件,负责管理镜像、容器、网络和卷等资源,并将 Docker API 暴露给客户端。
Docker 镜像和 Docker 容器:Docker 镜像是只读的模板,包含了所有用于运行应用程序所需要的代码、库文件、环境变量和配置文件等内容。Docker 容器是基于 Docker 镜像创建的可运行实例。每个容器都是一个独立的、轻量级的操作系统,它们之间相互隔离并且可以共享主机的内核。
CRI(Container Runtime Interface)和容器运行时:CRI 是 Kubernetes 的容器运行时标准接口,满足这个标准的所有容器运行时都可以被使用。容器运行时则提供了一个轻量级的容器运行环境,用于创建、启动和停止容器。
OCI(Open Container Initiative)和 runc:OCI 是一个开放的容器组织,它制定了容器运行时的规范,包括运行时规范、容器镜像规范等。runc 是 OCI 标准的一个参考实现,它与容器所依赖的 cgroup/linux kernel 等进行交互,是容器最终运行的形态之一。
在 Kubernetes 1.24 版本以前,Kubernetes 通过调用 Docker 命令来创建容器。具体来说,Kubernetes 将任务发送给 Docker 客户端,然后 Docker 客户端通过与 Docker 守护进程(daemon)通信来创建容器。Docker 守护进程会通过 Image 模块下载镜像并保存,然后通过 client 调用 containerd 创建并运行容器。在这个过程中,如果需要给容器添加持久化存储,可以使用 volume 参数;如果需要配置容器网络,可以通过 network 参数来实现。
然而,Kubernetes 提供了更强大的卷挂载能力和集群级别的网络能力。在集群中,kubelet 只会使用到 Docker 提供的镜像下载和容器管理功能,而编排、网络、存储等功能都不会用到。
在 Kubernetes 1.24 版本以后,Containerd 作为容器运行时被引入,带来了创建 Pod 所需的所有功能。与之前的方案相比,这不仅带来了更纯粹的功能模块,而且缩短了调用链,提高了系统的效率和稳定性。因此,用户可以使用 Containerd、CRI-O、CRI-Dockerd 及其他容器运行时作为 Kubernetes 的容器引擎。
Kubelet 通过 CRI 运行时服务 API 调用 CRI 插件来创建 Pod。
CRI 创建一个特殊的沙箱容器(pause 容器),并将其放置在 Pod 的 Cgroups 和 NameSpace 命名空间中。
CRI 使用 CNI 配置 Pod 的网络命名空间。
Kubelet 随后通过 CRI 镜像服务 API 调用 CRI 插件来拉取应用容器镜像。如果镜像不存在于节点上,CRI 会进一步使用 Containerd 来拉取镜像。
Kubelet 通过 CRI 运行时服务 API 调用 CRI,并使用拉取的容器镜像在 Pod 内创建和启动应用程序容器。
CRI 创建应用程序容器,将其放入 Pod 的 Cgroups 和 NameSpace 中,然后启动 Pod 的新应用容器。
在这些步骤之后,一个 Pod 及其相应的应用程序容器被创建并运行。
容器镜像,由于 Docker 镜像符合 OCI 规范,因此可以直接使用而不受影响。此外,原镜像打包方式仍然可用,即使用 docker build 方式打包镜像。这意味着用户在构建和打包镜像时不需要做出任何改变
Kubernetes 中的运行过程,作为终端用户(Kubernetes 使用者)基本也不会有任何影响,因为 Kubernetes 的使用逻辑没有任何变化。然而,与 Dockershim 相关的 API 接口已经弃用,如果创建了此类 CRD,需要注意修改相关代码。
运维方式,节点后端运维时使用的命令由 docker 命令改为 containerd。如果旧环境使用的是 Dockershim 引擎,需要先改为 containerd 运行时再进行升级。运维人员则需要适应新的命令行工具和运行时环境。
Kubernetes 弃用 Dockershim 而采用 containerd 作为容器运行时对用户和运维方式会有一些影响,但对于已经符合 OCI 规范的镜像和使用 docker build 方式打包镜像的用户来说,基本无感知。
用户需要按照 Kubernetes 官方提供的迁移指南进行操作。这包括更新 Kubernetes 版本、修改 Pod 配置文件、调整部署流程、更换镜像管理工具以及重新配置监控和日志采集工具等步骤。在迁移过程中,用户还需要注意测试新环境的稳定性和性能,确保迁移成功。
在迁移过程中,用户可能会遇到各种问题,如配置错误、兼容性问题、性能下降等。为了解决这些问题,用户可以参考 Kubernetes 官方文档和社区资源,或者向灵雀云的服务团队寻求帮助和支持。此外,用户还可以在测试环境中模拟迁移过程,提前发现和解决问题。
迁移到 Containerd 后,用户可以对系统进行一系列优化和改进,以提高性能和稳定性。例如,优化 Pod 的配置和部署流程、使用更高效的网络配置方式、改进监控和日志采集策略等。此外,用户还可以关注 Kubernetes 和 Containerd 的最新版本和功能更新,及时跟进技术发展趋势。
Kubernetes 弃用 Dockershim 并转向 Containerd 已经成为一个明显的趋势信号。对于现有的 Kubernetes 用户来说,应尽快了解这一变化的影响和应对策略,找到适合自己的方案并尽早进行改进。未来,Kubernetes 与 Containerd 的发展趋势将更加紧密地结合在一起,共同推动容器技术的不断创新和发展。
参考文档:
https://kubernetes.io/zh-cn/blog/2022/02/17/dockershim-faq/
https://kubernetes.io/zh-cn/blog/2020/12/02/dont-panic-kubernetes-and-docker/