🚀 CRI 详解:ctr、nerdctl、crictl 与 Docker 命令对照

CKA 备考:容器运行时接口 CRI 知识点详解,含 ctr、nerdctl、crictl 命令行工具与 docker 命令对照

CRI(Container Runtime Interface,容器运行时接口)是 kubelet 与容器运行时之间的标准接口,也是 CKA 考试的重要知识点。它对应官方课程 Cluster Architecture(集群架构,权重 25%)中的 “Understand extension interfaces (CNI, CSI, CRI)” 主题,属于扩展接口里必考的一项。考试不只考概念,更常以节点排障的形式考察 ctrnerdctlcrictl 三个命令行工具的实际用法。

本篇把 CRI 的原理、容器运行时的演进以及三个工具与 docker 的语法对照整理成一份可直接背诵的备考笔记。先搞懂 CRI 是什么,再记住每个工具的命令对照,最后用高频检查命令清单收尾,考场上遇到运行时相关的题目就不会慌。

适用对象:CKA 考生
考察范围:CRI 原理、容器运行时演进、ctr / nerdctl / crictl 命令行工具
核心对照:三个工具与 docker 命令语法对照

1. CRI:概念与演进

CRI 定义:CRI 是 kubelet 与容器运行时之间约定的 gRPC 接口,kubelet 不关心运行时具体实现,只要满足 CRI 规范就能接入。它由两个 gRPC 服务组成:RuntimeService 负责 Pod 沙箱(PodSandbox)与容器的创建、启停、删除;ImageService 负责镜像的拉取、列表与删除。

OCI 规范:CRI 之上还有 OCI(Open Container Initiative)约束运行时行为。runtime-spec 定义了容器运行时的标准,runc 是最常见的实现;image-spec 定义了镜像格式标准。完整的调用链是 kubelet → CRI → containerd / CRI-O → OCI → runc,每一层只关心自己的职责。

dockershim 历史:Docker 出现早于 Kubernetes,早期 kubelet 通过内置的 dockershim 组件把 CRI 调用翻译成 Docker API。由于维护成本高,k8s 在 1.24(2022 年 4 月)正式移除 dockershimcontainerd 成为 kubeadm 默认的 CRI 运行时。有意思的是,Docker 引擎底层本来就在用 containerd,移除后只是少了一层 Docker 自己的 API。

演进阶段说明
Docker 引擎Docker CLI / API 之上运行 containerd + runc,kubelet 无法直接使用
dockershimkubelet 内置的适配层,把 CRI 调用翻译成 Docker API,维护成本高
CRI 标准化引入 containerd / CRI-O 直接实现 CRI,去掉中间翻译层
移除 dockershimk8s 1.24 移除,containerd 成为默认 CRI 运行时

2. ctr:containerd 原生底层命令

ctr 是 containerd 自带的命令行客户端,定位低层,命令风格与 Docker 不兼容,主要用于调试和运维 containerd 本身。它默认使用 default namespace,而 Kubernetes 的资源放在 k8s.io namespace 下,因此查看 k8s 相关容器与镜像必须加 -n k8s.io

1
2
3
4
5
6
7
8
9
ctr images pull docker.io/library/nginx:latest
ctr images ls
ctr run -d docker.io/library/nginx:latest nginx1
ctr containers create docker.io/library/nginx:latest nginx2
ctr containers start nginx2
ctr tasks ls
ctr namespaces ls
ctr namespaces create myns
ctr namespaces rm myns

-n / --namespace 标志用于指定命名空间,也可以用环境变量 CONTAINERD_NAMESPACE 设置默认值,设置后后续命令可以省略 -n。注意 ctr tasks exec 对应 docker execctr run 隐含了创建与启动两步,而 ctr containers create + ctr containers start 是拆开的两步操作。

containerd 2.x 的主要变化:

  • 移除 CRI v1alpha2,只保留 v1
  • 移除 aufs snapshotter,只剩 overlayfs 等主流实现
  • schema1 旧格式镜像默认无法拉取,需要设置 CONTAINERD_ENABLE_DEPRECATED_PULL_SCHEMA_1_IMAGE=1 并配合 --local 参数
  • 新增 ctr deprecations list 查看弃用项清单
  • 新增 ctr sandboxes 命令管理沙箱
  • 当前版本为 v2.3.4,属于 2.3 LTS 线
dockerctr(k8s 场景加 -n k8s.io
docker imagesctr images ls
docker pullctr images pull
docker psctr containers ls
docker run -dctr run -d
docker execctr tasks exec

3. nerdctl:Docker 兼容的 containerd CLI

nerdctl 是 containerd 生态中的类 Docker CLI,命令名与 docker 几乎一一对应,目标是让 containerd 用起来和 Docker 一样顺手。它依赖 containerd daemon 提供容器能力、CNI 插件提供网络、BuildKit 提供镜像构建;nerdctl-full 捆绑包一次装齐全部依赖,是免去逐个安装的省心选择。

常用全局 flag:

  • --namespace:指定命名空间,默认 default,k8s 资源用 k8s.io
  • -H / --host:指定 containerd 服务地址
  • --snapshotter:指定快照器,如 overlayfs
  • --cgroup-manager:cgroup 管理器,如 systemd
  • --insecure-registry:允许非 HTTPS 镜像仓库
  • --data-root:数据目录
  • --cni-path:CNI 插件路径
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
nerdctl run -d -p 8080:80 nginx:latest
nerdctl build -t myapp:latest .
nerdctl pull nginx:latest
nerdctl exec -it nginx1 sh
nerdctl logs -f nginx1
nerdctl ps -a
nerdctl images
nerdctl rmi nginx:latest
nerdctl namespace ls
nerdctl namespace create myns
nerdctl namespace rm myns
nerdctl compose up -d
dockernerdctl
docker runnerdctl run
docker buildnerdctl build
docker composenerdctl compose
docker networknerdctl network
docker psnerdctl ps

4. crictl:CRI 调试客户端(CKA 核心)

crictl 是 cri-tools 项目提供的 CRI 调试客户端,直接与 CRI 运行时通信,不经过 kubelet。它是 Kubernetes 节点排障的专用工具,killer.sh 和 KodeKloud 模拟环境都经常考,是三个工具里 CKA 备考价值最高的一个。

配置文件默认位于 /etc/crictl.yaml,也可以放到用户级路径 $XDG_CONFIG_HOME/crictl/crictl.yaml。执行 crictl config 可以交互式生成配置,crictl config --set runtime-endpoint=unix:///var/run/containerd/containerd.sock 可以单独修改某项。

1
2
3
4
runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
timeout: 10
debug: false

常用命令与 flag(已对照 cri-tools 源码验证):

  • crictl ps:列出容器;-a / --all 包含已退出容器,-p / --pod 按 Pod 过滤,--image 按镜像过滤,-s / --state 按状态过滤,--name 按容器名正则过滤,--namespace 按 Pod 命名空间正则过滤,--label 按标签过滤,-o json|yaml|table 控制输出格式,-l / --latest 只显示最近一个,-n / --last 显示最近 N 个,--no-trunc 不截断输出
  • crictl pods:列出 Pod 沙箱,--namespace 按命名空间正则过滤
  • crictl images / crictl pull / crictl rmi:镜像管理
  • crictl inspect / crictl inspectp / crictl inspecti:分别查看容器、Pod 沙箱、镜像详情
  • crictl logs:查看容器日志;-f / --follow 持续输出,-p / --previous 查看上一次实例,--tail 指定行数,-t / --timestamps 显示时间戳
  • crictl exec:进入容器,-i / -t 语义与 docker exec 一致,--pod 指定所属 Pod,--name 按名称选中容器
  • crictl stats:查看容器资源占用
  • crictl runp / create / start / stop / rm / stopp / rmp:手动管理 Pod 沙箱与容器
  • crictl info:查看运行时信息
  • crictl version:查看客户端与运行时版本
dockercrictl
docker pscrictl ps -a
docker imagescrictl images
docker pullcrictl pull
docker exec -itcrictl exec -it
docker logscrictl logs

考题场景:Pod 状态异常是 CKA 节点排障的常考题型,典型的排查链如下。

  1. k get pods 显示 ContainerCreatingCrashLoopBackOffImagePullBackOff,先 k describe pod 看事件。
  2. SSH 到 Pod 所在节点,用 crictl ps -a 查看容器实际状态(含已退出容器)。
  3. crictl logs <container-id> 看应用日志,判断是启动崩溃还是配置错误。
  4. crictl inspect <container-id> 看容器配置、挂载与退出码。
  5. 镜像拉取失败时,先 crictl images 确认本地是否有镜像,再手动 crictl pull <image> 验证仓库连通性。
1
2
3
4
crictl ps -a
crictl logs <container-id>
crictl inspect <container-id>
crictl pull <image>

5. Docker 与三工具总对照

操作dockernerdctlctrcrictl
查看容器docker psnerdctl psctr containers lscrictl ps -a
查看镜像docker imagesnerdctl imagesctr images lscrictl images
拉取镜像docker pullnerdctl pullctr images pullcrictl pull
运行容器docker run -dnerdctl run -dctr run -dcrictl runp + create + start
进入容器docker exec -itnerdctl exec -itctr tasks execcrictl exec -it
查看日志docker logsnerdctl logs不支持(直接读文件)crictl logs
构建镜像docker buildnerdctl build不支持不支持
编排docker composenerdctl compose不支持不支持
网络docker networknerdctl network不支持不支持

关键差异:

  • ctr 不能构建镜像,也没有 compose 与网络管理能力,它的职责就是调试 containerd 本身
  • crictlctr 都不管理 CNI 网络
  • docker build 对应 nerdctl build,依赖 BuildKit
  • docker compose 对应 nerdctl compose
  • crictlrunp + create + start 面向 Pod 沙箱与容器,而不是单容器

一句话定位ctr 是底层调试工具,nerdctl 是类 Docker 的日常操作工具,crictl 是 CKA 节点排障的首选。

6. crictl 配置与常见易错点

/etc/crictl.yaml 完整示例:

1
2
3
4
runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
timeout: 10
debug: false

如果节点运行的是 CRI-O,把两个 endpoint 改成 unix:///var/run/crio/crio.sock 即可。

版本对应关系:

  • crictl / cri-tools v1.36.0,跟随 Kubernetes 小版本发布,k8s 当前稳定版为 1.37
  • containerd v2.3.4,位于 2.3 LTS 线
  • nerdctl v2.3.5

常见易错点:

  • ctr 默认 namespace 是 default,不是 k8s.io,不加 -n k8s.io 就看不到 k8s 资源
  • crictl ps 不带 -a 看不到已退出的容器,排查崩溃重启必须加 -a
  • crictl 通过 CRI 直接与运行时通信,绕过 kubelet,所以它看到的容器名是 sandbox 名称,而不是 kubectl 里的 Pod 名
  • runtime-endpoint 配错会导致 crictl 连不上运行时,报连接失败错误,先检查 /etc/crictl.yaml

高频检查命令

1
2
3
4
5
6
7
8
9
crictl ps -a
crictl pods
crictl images
crictl logs <container-id>
crictl inspect <container-id>
ctr -n k8s.io images ls
ctr -n k8s.io containers ls
nerdctl -n k8s.io ps -a
crictl info | grep runtime

考场压缩记忆

  • dockershim:k8s 1.24 已移除,containerd 成为默认 CRI 运行时。
  • CRI:kubelet 与运行时之间的 gRPC 接口,含 RuntimeServiceImageService 两个服务。
  • ctr 命名空间:默认 default,k8s 资源在 k8s.io,查看必须加 -n k8s.io
  • crictl 配置:默认读取 /etc/crictl.yaml,也可用用户级 $XDG_CONFIG_HOME/crictl/crictl.yaml
  • 三工具定位ctr 底层调试,nerdctl 类 Docker 日常操作,crictl 节点排障首选。
  • crictl ps -a:排查崩溃重启必加 -a,否则看不到已退出容器。
  • crictl 视角:看到的容器名是 sandbox 名称,不是 kubectl 里的 Pod 名。
comments powered by Disqus