containerd 是 Docker 1.11 后拆分出的核心容器运行时,Docker Engine 作为其客户端通过 gRPC 调用它,而 Kubernetes 1.20+ 默认使用 containerd 替代 dockerd,二者监听不同 socket、状态不共享。

containerd 是什么,和 Docker 有什么关系
containerd 不是 Docker 的替代品,而是 Docker 1.11 之后拆出来的核心运行时组件。Docker Engine 实际上是 containerd 的一个客户端封装——它把镜像拉取、容器启停等操作转成 gRPC 请求发给 containerd,后者再调用 runc 创建实际的 Linux 容器。
你直接用 containerd,等于绕过 Docker CLI 和 daemon,更轻、更可控,也更贴近 Kubernetes 的真实运行链路(K8s 1.20+ 默认用 containerd 替代 dockerd)。
- 如果你在 K8s 节点上查
ps aux | grep containerd,看到进程在跑,说明集群已经在用它 -
dockerd默认监听/var/run/docker.sock;containerd默认监听/run/containerd/containerd.sock,路径和协议都不一样 - 不要试图用
docker ps查containerd直接启的容器——它们彼此不共享状态
怎么手动启动一个容器(不用 docker run)
本质是三步:拉镜像 → 解包到本地存储 → 调用 containerd API 启动。生产环境一般用 ctr(containerd 自带的命令行工具)调试。
ctr image pull docker.io/library/nginx:alpine ctr run --rm -d --net-host docker.io/library/nginx:alpine my-nginx
-
--net-host表示复用宿主机网络命名空间,省去 CNI 配置麻烦;不加的话默认是空网络,容器起得来但没网 -
ctr默认不自动创建 rootfs,所以必须先pull,否则报错failed to resolve rootfs: no such image -
ctr run是“即时运行”,适合测试;长期服务推荐写containerd的 config.toml + 用crictl(K8s CRI 工具)管理
配置文件里 runtime-type 和 runtime-engine 的区别
containerd 的 config.toml 中,真正决定容器怎么跑的是 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes] 下的配置块,关键字段是:
-
runtime_type:固定为"io.containerd.runc.v2"(runc)或"io.containerd.runhcs.v1"(Windows HC);改错会直接启动失败,报unknown runtime type -
runtime_engine:已废弃,v1.4+ 忽略;旧文档里写的runc或crun其实该填在runtime_type对应的插件名里 - 如果要用
crun(更轻量的 OCI 运行时),得先装好二进制,再在配置里写:[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun] runtime_type = "io.containerd.runc.v2" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.crun.options] BinaryName = "crun"
常见报错:failed to create containerd task: failed to create shim task: OCI runtime create failed
这个错误出现在 ctr run 或 K8s Pod 启动阶段,根本原因是 runc 执行失败,但 containerd 只透出一层包装错误。真实原因藏在 shim 日志里:
- 先查 shim 进程:
ps aux | grep 'containerd-shim',找到对应容器的 PID - 再看日志:
journalctl -u containerd -n 100 | grep -A5 -B5 $PID,或者直接读/run/containerd/io.containerd.runtime.v2.task/default/$CONTAINER_ID/log.json - 常见真凶:
-
no such file or directory: unknown→ 镜像层损坏,删掉/var/lib/containerd/io.containerd.content.v1.content/blobs/对应 digest 重拉 -
permission denied→ SELinux 或 AppArmor 拦了runc,临时关 SELinux 测试:setenforce 0 -
invalid argument→ cgroup v1/v2 混用,确认内核启动参数含systemd.unified_cgroup_hierarchy=1且containerd配置里disabled_plugins = ["cri"]没误开
-
containerd 的日志默认不打详细错误,不查 shim 日志就只能猜;而 shim 日志路径、格式、权限又随版本微调,这点最容易卡住人。










