17.6 containerd - 核心容器运行时
本节介绍 containerd,它是现代容器技术栈中最为核心的基础组件之一。了解 containerd 有助于更深入地理解 Docker 和 Kubernetes 的底层运行机制。
containerd 简介
containerd 是一个行业标准的容器运行时,它最初是由 Docker 引擎中剥离出来的一个核心组件,后来 Docker 将其捐赠给了云原生计算基金会(CNCF),目前已经是一个 CNCF 毕业(Graduated)项目。
它的主要职责是管理单个宿主机上完整的容器生命周期,包括:
镜像的传输和存储
容器执行和管理
存储和网络接口的管理
简单来说,当你在使用 Docker 或者 Kubernetes 时,真正去底层调用操作系统接口(如 Linux 的 Namespace 和 Cgroups)来启动和管理容器进程的,往往是 containerd(及它所调用的 runc 组件)。
与 Docker 和 Kubernetes 的关系
理解 containerd,首先要理清它与用户日常操作的 Docker 以及 Kubernetes 的关系。
Docker 的架构
在早期,Docker 引擎是一个包含了所有功能的单体架构。随着技术的发展和标准化要求,Docker 将底层关于容器运行时的部分解耦出来,形成了 containerd 和 runc。
当你执行一个 docker run 命令时,调用链路大致如下:
Docker Client 发送请求给 Docker Daemon(
dockerd)。dockerd将请求转发给containerd。containerd准备好镜像和容器的必要环境,然后调用runc。runc负责按照 OCI(Open Container Initiative)标准,拉起并运行真正的容器进程。
因此,Docker 现在实际上是构建在 containerd 之上的一个包含更多开发者友好特性(如构建镜像、Compose 管理等)的增强平台。
Kubernetes 与 CRI
Kubernetes 作为一个容器编排系统,为了屏蔽底层不同容器运行时的实现差异,引入了 CRI(Container Runtime Interface)标准。
早期版本中,Kubernetes 默认使用 docker 作为运行时,通过一个名为
dockershim的桥接组件对接 Docker,Docker 再对接 containerd。随着 containerd 原生支持了 CRI 插件,Kubernetes 开始直接与 containerd 通信,去掉了
dockershim和dockerd的中间层。这就是为什么从 Kubernetes v1.24 开始“弃用 Docker”引发了广泛关注,实际上 Kubernetes 只是弃用dockershim,底层依然在使用从 Docker 基因中诞生的 containerd。
为什么直接使用 containerd?
对普通应用开发者来说,Docker 依然是本地开发和测试的首选。但对于构建云平台、自动化流水线或深度管理 Kubernetes 集群的系统工程师来说,直接使用 containerd 可以带来:
更高的性能与更少的开销:去掉了 Docker Daemon 等附加组件的资源占用,链路更短。
更强的稳定性:作为专注于运行时的底层组件,它的核心功能极为稳定且更新受控。
直接符合 Kubernetes CRI 标准:在生产级 Kubernetes 集群中作为标准配置。
基础用法与工具介绍
不同于 docker 命令行工具,containerd 提供了不同的客户端来满足不同的使用场景:
ctr:containerd 自带的调试用客户端。它功能比较基础,主要用于开发者在开发 containerd 时进行快速调试,一般不作为最终用户的日常管理工具。
crictl:Kubernetes 提供的 CRI 命令行工具。它用于排查 Kubernetes 节点上的容器和沙箱(Pod)问题。
nerdctl:这是一个由系统社区成员(主要是 containerd 项目的维护者)开发的,完全兼容 Docker CLI 体验的 containerd 命令行客户端。对于习惯了
docker run/ps/build命令的用户来说,nerdctl可以作为直接操作 containerd 的理想替代品,并且它还支持直接构建镜像(依赖 BuildKit)。
nerdctl 使用示例
安装完 containerd 和 nerdctl 后,你可以体验到几乎与 Docker 完全一致的命令行:
对于那些希望在生产服务器上剥离 Docker 庞大体积,但又想要保留类似 Docker 方便的命令行体验的用户,containerd + nerdctl 是一个极佳的组合。
最后更新于