Kubernetes 从 1.24 版本起彻底移除了对 Docker 的内置支持,containerd 成为默认且使用最广泛的容器运行时。当集群节点出现 NotReady、Pod 一直处于 ContainerCreating 状态、或者 kubelet 日志反复报出容器运行时连接失败的错误时,问题几乎都出在 containerd 的配置或运行状态上。本文将从配置结构、常见故障现象、排查命令到修复方案,系统梳理 containerd 在 Kubernetes 环境下的排障方法。

一、containerd 配置文件结构与关键参数
containerd 的主配置文件位于 /etc/containerd/config.toml。很多情况下故障的根源是这个文件根本不存在,或者内容过于精简。安装 containerd 后默认生成的配置非常简单,缺少 Kubernetes CRI 所需的必要设置,需要手动生成并修改完整配置。
首先执行以下命令导出默认配置:
containerd config default > /etc/containerd/config.toml
生成后需要重点检查以下几个配置段。第一个是插件路径下的 CRI 配置,涉及 sandbox 镜像地址。Kubernetes 依赖 registry.k8s.io/pause:3.x 这类沙箱镜像创建 Pod 的网络命名空间,如果集群环境无法访问海外仓库,沙箱镜像拉取失败会导致所有 Pod 卡在 ContainerCreating 状态。可以修改为可用的镜像源,或提前手动拉取后通过 crictl pull 确认可用。第二个关键项是 SystemdCgroup 参数,它决定了容器 cgroup 的管理模式,必须与 kubelet 的 cgroup 驱动保持一致,否则节点会持续报 cgroup 相关错误。
# 查看关键配置项 grep -A 5 'plugins."io.containerd.grpc.v1.cri"' /etc/containerd/config.toml # 输出中关注 SystemdCgroup 与 sandbox_image 字段
第三个需要了解的是 containerd 的 socket 路径,默认为 /run/containerd/containerd.sock。kubelet 启动参数中的 --container-runtime-endpoint 必须指向这个路径,路径写错或 socket 文件不存在是节点 NotReady 的常见原因。另外 /etc/crictl.yaml 中也要配置相同的 endpoint,否则使用 crictl 命令排查时会连接失败,干扰判断。
二、常见故障现象与排查流程
排查 containerd 问题应该遵循从进程到 socket 再到配置的顺序。第一步确认进程是否存活,使用 systemctl status containerd 查看服务状态。如果服务处于 inactive 或 failed 状态,日志中通常能直接看到原因,比如 config.toml 语法错误导致启动失败。TOML 语法对格式要求严格,多一个引号或缩进错误都会让 containerd 拒绝启动。
# 查看服务状态与详细日志 systemctl status containerd journalctl -u containerd -f --no-pager # 验证 socket 是否存在 ls -l /run/containerd/containerd.sock
第二步用 crictl 验证 CRI 接口是否可用。执行 crictl info 能返回 JSON 信息说明运行时接口正常,执行 crictl ps 能列出容器。如果 crictl 报连接拒绝,先检查 containerd 进程,再检查 /etc/crictl.yaml 中的 runtime-endpoint 配置。第三步检查 kubelet 日志,执行 journalctl -u kubelet --no-pager | grep -i containerd,关注是否有拨号超时或版本不匹配的报错。
一个容易被忽视的故障是 runc 版本过旧。containerd 通过 runc 实际创建容器,老版本 runc 与新版 cgroup 或内核存在兼容性问题,报错信息类似 OCI runtime create failed。可以通过 runc --version 确认版本,必要时升级 containerd.io 软件包连带更新 runc。
三、镜像拉取失败与加速配置
镜像拉取问题是生产环境最高频的故障类型。Pod 事件中出现 ImagePullBackOff 时,先通过 crictl pull 手动拉取验证,观察具体报错是超时、认证失败还是仓库不存在。对于国内服务器访问海外仓库超时的情况,需要为 containerd 配置镜像加速端点。
containerd 1.5 以上版本在 config.toml 的 CRI 插件配置段中通过 registry 配置 mirrors。示例如下:
# /etc/containerd/config.toml 中追加 [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://registry.ipipp.com"] [plugins."io.containerd.grpc.v1.cri".registry.configs."registry.ipipp.com".auth] username = "yourname" password = "yourpassword"
配置修改后必须重启服务才能生效,执行 systemctl restart containerd,随后用 crictl pull 测试。需要注意,如果集群中部署了 Docker Hub 的私有仓库认证信息,老版本 containerd 的认证配置方式与新版本不同,1.6 之后推荐使用 registry.configs 段配置认证,而不是依赖 kubelet 传递镜像凭证。私有仓库如果使用自签证书,还需要将 CA 证书放到 /etc/containerd/certs.d 对应目录或系统信任列表中,否则会报 x509 证书验证失败。
四、cgroup 驱动不匹配与节点 NotReady 处理
当 kubelet 日志中出现运行时网络未就绪、或节点频繁在 Ready 与 NotReady 之间抖动时,一个典型原因是 cgroup 驱动不一致。kubelet 使用 systemd 驱动而 containerd 使用 cgroupfs 驱动时,资源统计与管理会出现冲突。正确做法是两边统一为 systemd,这也是目前官方推荐的方式。
在 containerd 侧,修改 config.toml 中 runc 的 SystemdCgroup 为 true:
# /etc/containerd/config.toml [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true
在 kubelet 侧,确认 /var/lib/kubelet/config.yaml 中 cgroupDriver 为 systemd,两处都修改后重启 containerd 与 kubelet。对于使用 kubeadm 部署的集群,建议在 kubeadm 初始化配置中也显式声明 cgroupDriver,避免节点扩容时新节点配置漂移。
最后一种常见情况是沙箱镜像版本不匹配。kubeadm 初始化时会在控制组件参数中指定 pause 镜像版本,如果 config.toml 中的 sandbox_image 版本与其不一致,节点组件虽然能启动但 Pod 沙箱创建会失败。排查时对比 kubelet 参数与 containerd 配置中的镜像地址版本,统一后重启即可。掌握以上排查路径后,绝大多数 containerd 相关的集群故障都能在短时间内定位并修复,核心思路始终是:进程、socket、CRI 接口、配置一致性逐层验证。
containerdKubernetes容器运行时修改时间:2026-09-01 00:06:46