containerd containerd

containerd 的命令行工具:ctr、nerdctl 与 crictl

三个命令行工具,三种不同的用途 —— 何时该用哪一个。

10 min 初级

当 Docker 不再是节点上运行容器的组件时,docker ps 和 docker logs 在那里就不再可用了。有三个工具填补了这个空缺,它们由两个不同的社区为两种不同的目的而构建。在节点上直接排查问题时,用错工具是最常见的困惑来源。

三个工具一览

工具开发方通信对象用途类似 Docker?
ctrcontainerd 项目直接与 containerd 通信调试 containerd 本身否,精简且偏底层
nerdctlcontainerd 项目直接与 containerd 通信通用容器管理是,与 docker 高度相似
crictlKubernetes 项目任何兼容 CRI 的运行时从 Kubernetes 的视角调试运行时部分相似,感知 Pod

ctr:自带、精简、仅用于调试

ctr 随 containerd 一起发布,因此只要有 containerd 的地方它就一定可用,但它明确是一个调试工具,功能集刻意保持很小,并不适合日常的容器管理:

ctr images pull docker.io/library/redis:7
ctr run docker.io/library/redis:7 my-redis
ctr containers list

containerd 项目本身建议,除调试和检查 containerd 自身状态之外,不要将 ctr 用于其他用途。如果你发现自己想用它编写部署脚本,这就是该改用 nerdctl 的信号。

nerdctl:类似 Docker 的日常主力

nerdctl 是另一个命令行工具,同样来自 containerd 项目,它的设计目标是在外观和行为上足够像 docker CLI,以至于大多数 docker 命令只需替换二进制名称就能运行:

nerdctl run -d -p 8080:80 nginx:1.25
nerdctl ps
nerdctl logs my-container
nerdctl build -t myapp:latest .

除了与熟悉的 Docker 工作流保持一致之外,nerdctl 还提供了 Docker 所没有的 containerd 原生能力:加密镜像、lazy pulling、P2P 镜像分发、镜像签名与验证,以及直接与 containerd 自身数据模型中的 Kubernetes 命名空间交互。对于安装了 containerd 但没有 Docker 的机器上的一般容器工作,nerdctl 是该用的工具。

crictl:从 Kubernetes 的视角

crictl 由 Kubernetes 项目自己维护,而不是 containerd,它使用 CRI(也就是 kubelet 所用的同一接口)通信,而不是 containerd 的原生 API。这意味着它在 containerd、CRI-O 或任何其他兼容 CRI 的运行时上表现一致,并且它理解 ctr 和 nerdctl 所不理解的 Kubernetes 概念,最重要的是 Pod,而不仅仅是容器:

crictl images
crictl ps
crictl pods
crictl exec -it CONTAINER_ID sh
crictl logs CONTAINER_ID

注意 crictl pods:无论是 ctr、nerdctl,还是更早的 Docker,都没有原生的 Pod 概念,即一组共享网络和存储的容器。这是 Kubernetes 特有的,而 crictl 正是为直接处理它而构建的工具。

和 ctr 一样,crictl 用于检查和调试,而不是创建工作负载。如果你用它启动了一个 Kubernetes 不知道的容器,kubelet 对此没有任何记录,一旦发现就会将其删除,因为在 Kubernetes 看来,节点上出现意料之外的容器是需要被纠正的漂移,而不是需要保留的工作负载。

crictl 连接哪个端点

由于 crictl 可以跨运行时工作,它需要知道要连接哪一个。如果不做配置,它会按顺序尝试一组固定的默认套接字(历史上依次是 dockershim 的、containerd 的、CRI-O 的,以及其他)。在现代节点上这种歧义很少造成影响,因为只安装了一个运行时,但在装有多个运行时的节点上,或在排查套接字路径问题时,请显式设置:

crictl --runtime-endpoint unix:///run/containerd/containerd.sock ps
# or
export CONTAINER_RUNTIME_ENDPOINT=unix:///run/containerd/containerd.sock

如何在它们之间选择

  • 检查或排查 Kubernetes 本身所看到的情况,即将 kubectl describe pod 报告的内容与节点上实际运行的内容对照,使用 crictl。
  • 在节点上或本地开发中进行一般容器工作,例如快速运行某个东西、构建镜像、查看日志,使用 nerdctl。
  • 调试 containerd 自身的内部状态,也就是某些特定于 containerd、而非与运行时无关的 CRI 视图的问题,使用 ctr,并做好需要同时打开 containerd 自己文档的准备。

热门指南