Appearance
containerd 与 CRI
containerd 是容器运行时,Docker 和 Kubernetes 都会和它发生关系。早期接触容器时常用 docker 命令,到了 Kubernetes 里,kubelet 不再直接调用 Docker CLI,而是通过 CRI(Container Runtime Interface)和运行时通信。containerd 是当前最常见的 CRI 实现之一。
这几个名字容易混在一起:Docker 是面向使用者的完整工具链,containerd 负责镜像和容器生命周期,runc 按 OCI 规范真正创建容器进程,CRI 是 kubelet 和运行时之间的接口。
一、运行时关系
Docker 场景里,用户通过 Docker CLI 调 dockerd,dockerd 再调 containerd。Kubernetes 场景里,kubelet 通过 CRI 直接调 containerd,不需要 dockerd 夹在中间。
Docker 仍然可以在单机开发、Compose、镜像构建场景里使用;Kubernetes 节点上更关心 containerd、kubelet 和 CNI。
二、CRI 是什么
CRI 是 kubelet 调用容器运行时的标准接口。它把“拉镜像、创建 Pod sandbox、启动容器、停止容器、查日志”这些动作抽象成统一 API。
| 动作 | kubelet 通过 CRI 请求运行时 |
|---|---|
| 拉镜像 | PullImage |
| 创建 Pod 沙箱 | RunPodSandbox |
| 创建容器 | CreateContainer |
| 启动容器 | StartContainer |
| 获取状态 | ContainerStatus |
| 删除资源 | RemoveContainer、StopPodSandbox |
Pod sandbox 是 Pod 的基础运行环境,通常对应 pause 容器和网络命名空间。业务容器会加入这个 sandbox,共享 Pod IP 和网络空间。
三、containerd 配置
containerd 常见配置文件:
bash
# 生成默认配置,已有配置时要先备份再操作
containerd config default | sudo tee /etc/containerd/config.tomlKubernetes 节点上常见配置点:
toml
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true| 配置 | 说明 |
|---|---|
sandbox_image | Pod sandbox 使用的 pause 镜像 |
SystemdCgroup | 和 kubelet 的 cgroup driver 保持一致 |
| registry mirrors | 镜像源和私有仓库配置 |
修改后重启:
bash
sudo systemctl restart containerd
sudo systemctl status containerd --no-pagerKubernetes 节点上重启 containerd 会影响正在运行的容器管理面,操作前要确认节点是否需要先 drain。
四、crictl
crictl 是面向 CRI 的排查工具。它不依赖 Docker daemon,适合 Kubernetes 节点排查。
配置 /etc/crictl.yaml:
yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false常用命令:
bash
# 查看 Pod sandbox
crictl pods
# 查看容器
crictl ps -a
# 查看镜像
crictl images
# 查看某个容器日志
crictl logs <container-id>
# 查看运行时信息
crictl infokubectl 从 API Server 看对象状态,crictl 从节点运行时看真实容器状态。API Server 正常但某个节点 Pod 状态异常时,登录节点用 crictl 能看到更底层的信息。
五、nerdctl
nerdctl 是 containerd 的 Docker 风格客户端。命令体验接近 Docker:
bash
nerdctl images
nerdctl pull nginx:1.26
nerdctl run -d --name web -p 8080:80 nginx:1.26
nerdctl pscontainerd 有 namespace 概念。Kubernetes 默认使用 k8s.io namespace:
bash
nerdctl --namespace k8s.io images
nerdctl --namespace k8s.io ps看不到 Kubernetes 镜像时,经常是因为 namespace 查错了。default namespace 里没有,不代表节点没有镜像。
六、镜像源和私有仓库
containerd 的镜像源配置和 Docker 的 daemon.json 不一样。K3s 内置 containerd 常用 /etc/rancher/k3s/registries.yaml,标准 containerd 常用 certs.d 或 config.toml。
K3s 示例:
yaml
mirrors:
docker.io:
endpoint:
- "https://docker.1ms.run"
configs:
registry.example.com:
tls:
insecure_skip_verify: false标准 containerd 的 hosts.toml 示例:
toml
server = "https://docker.io"
[host."https://docker.1ms.run"]
capabilities = ["pull", "resolve"]Docker 能拉镜像,不代表 Kubernetes 节点也能拉。Kubelet 通过 containerd 拉镜像,排查 ImagePullBackOff 时要看 containerd 的 registry 配置、证书和凭据。
七、排查入口
| 现象 | 查看方式 |
|---|---|
| Pod 一直 ContainerCreating | crictl pods、crictl ps -a、kubelet 日志 |
| ImagePullBackOff | containerd 镜像源、证书、Secret、仓库权限 |
| 容器日志 kubectl 看不到 | 节点上 crictl logs |
| 节点 NotReady | kubelet、containerd、CNI、磁盘和 cgroup |
| 镜像占用过多 | crictl images、containerd 内容存储清理 |
常用节点侧命令:
bash
systemctl status containerd --no-pager
journalctl -u containerd -n 100 --no-pager
journalctl -u kubelet -n 100 --no-pager
crictl info
crictl ps -acontainerd 是 Kubernetes 节点排查里绕不开的一层。Pod 在 API 里只是对象,真正的镜像拉取、容器创建、日志文件和退出码,都落在节点运行时上。
Kubernetes 节点维护时,containerd 会和 kubelet、镜像清理、磁盘压力、Pod 驱逐一起出现,相关操作见 节点运维。