containerd 从入门到精通实战手册
版本基线:containerd 1.7.x(LTS)与 2.x、CRI(Kubernetes 运行时)、nerdctl、crictl
目录
第 1 章 containerd 是什么 1.1 背景:为什么需要 containerd containerd(读作 “container-dee”)是一个工业级容器运行时 ,由 Docker 公司在 2017 年捐献给 CNCF,2019 年 2 月成为 CNCF 毕业项目 ,与 Kubernetes、Prometheus 同级。
它是目前云原生生态的事实标准底层运行时 :
Docker Engine 的容器执行底层就是 containerd。
Kubernetes 通过 CRI 接口对接 containerd(自 K8s 1.24 移除 dockershim 后,containerd 是主流默认运行时)。
它只做”运行容器”这一件事,把镜像构建(Build)、编排(Orchestration)等留给上层。
1.2 containerd 在整个技术栈中的位置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +-------------------------------------------------------------+ | Docker CLI / Docker Compose | kubectl / kubelet | +------------------+-------------+--------------+--------------+ | Docker Engine | | CRI (K8s) | | | (docker daemon) | | | | +------------------+ +--------------+ | | containerd(统一底座) | | +------------+ +-----------+ +----------+ +------------+ | | | 镜像管理 | | 容器生命周期 | | 快照存储 | | 命名空间 | | | +------------+ +-----------+ +----------+ +------------+ | | containerd-shim(每个容器一个) | | runc / runsc / kata(OCI 运行时) | +--------------------------------------------------------------+ | Linux 内核(namespace/cgroup/overlayfs) | +--------------------------------------------------------------+
一句话总结 :containerd 是”操作系统的容器子系统”,上层无论是 Docker 还是 Kubernetes,最终都通过它来拉镜像、建容器、跑进程。
1.3 核心组件与进程 安装 containerd 后,主要二进制与进程:
进程/二进制
作用
containerd
守护进程,暴露 gRPC API,管理镜像、容器、快照、元数据
containerd-shim-runc-v2
每个容器一个 的垫片进程,隔离 containerd 与容器进程
runc
OCI 运行时,真正创建/运行容器进程
ctr
containerd 自带 CLI(调试/运维用)
crictl
CRI 客户端(K8s 视角的运维工具)
nerdctl
Docker 兼容 CLI(社区推荐)
shim 的作用(重要):
1 2 3 containerd 重启/升级 -> 容器不受影响(shim 还在) containerd 崩溃 -> 运行中的容器继续跑 容器退出 -> shim 回收资源并上报状态
shim 让”containerd 重启不杀容器”成为可能,这是它相比”单守护进程架构”的核心优势(对应 Docker 的 live-restore 是更上层的近似实现)。
1.4 containerd 与 Docker 的对比
维度
Docker Engine
containerd
定位
完整容器平台(build+run+compose)
纯运行时(run only)
镜像构建
内置(buildkit)
不支持(需 buildkit/nerdctl build)
编排
Compose / Swarm
无(对接 K8s)
网络
内置 bridge/host/overlay
不管理网络(CRI 场景靠 CNI)
端口映射
内置
无(nerdctl 通过 CNI 实现)
CLI
docker
ctr(原始)/ crictl(CRI)/ nerdctl(类 docker)
重启策略
restart 参数
无(上层负责,如 K8s/kubelet)
数据卷
volume/bind
无内置(nerdctl 支持)
使用场景
单机开发/小规模
K8s 节点运行时、嵌入式/裁剪场景
资源占用
较大(多一层 daemon)
更小、更稳
结论 :Docker 适合单机开发与交付;生产 K8s 节点直接用 containerd,去掉多余组件,减少攻击面与资源占用。
1.5 版本与演进
版本
状态
关键变化
1.6.x
EOL
大量 K8s 版本默认搭载
1.7.x
LTS(长期支持)
支持镜像签名验证、改进快照器、Windows 容器增强
2.0.x
当前主线
默认启用镜像存储(image store)、配置语法更新、runc 升级、移除旧兼容层
1 2 3 containerd --version ctr version
生产选择:K8s 节点用 containerd 1.7 LTS (稳定、文档多),新集群可评估 2.x;升级前先看官方”升级到 2.x”的兼容性说明(配置、插件、API 变化)。
第 2 章 安装与基础配置 2.1 系统要求
项目
要求
内核
Linux ≥ 4.x(推荐 5.x+),需支持 overlayfs、cgroup v2(推荐)
架构
x86_64 / arm64 / ppc64le / s390x 等
磁盘
视镜像量而定,建议 ≥ 20GB 给 /var/lib/containerd
K8s 节点
与 kubelet/kubeadm 版本匹配(见官方兼容矩阵)
1 2 3 uname -rcat /etc/os-release grep -c cgroup /proc/filesystems
2.2 通过发行版包安装(推荐) Ubuntu / Debian:
1 2 3 4 5 6 7 8 9 10 sudo apt-get updatesudo apt-get install -y containerd.io curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpgecho "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" \ | sudo tee /etc/apt/sources.list.d/containerd.listsudo apt-get updatesudo apt-get install -y containerd.io
CentOS / Rocky / AlmaLinux:
1 2 3 sudo yum install -y yum-utilssudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.reposudo yum install -y containerd.io
发行版包会:创建 containerd 用户与组、安装 systemd unit、默认配置 /etc/containerd/config.toml、自动启动。
2.3 官方二进制安装(手动,可控性最强) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 wget https://github.com/containerd/containerd/releases/download/v1.7.22/containerd-1.7.22-linux-amd64.tar.gz tar -C /usr/local -xzf containerd-1.7.22-linux-amd64.tar.gz wget https://github.com/opencontainers/runc/releases/download/v1.1.14/runc.amd64 install -m 755 runc.amd64 /usr/local/sbin/runc wget https://github.com/containernetworking/plugins/releases/download/v1.5.0/cni-plugins-linux-amd64-v1.5.0.tgzmkdir -p /opt/cni/bin tar -C /opt/cni/bin -xzf cni-plugins-linux-amd64-v1.5.0.tgzmkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.tomlcat > /etc/systemd/system/containerd.service <<'EOF' [Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target local-fs.target [Service] ExecStartPre=-/sbin/modprobe overlay ExecStart=/usr/local/bin/containerd Restart=always RestartSec=5 Delegate=yes KillMode=process LimitNOFILE=1048576 TasksMax=infinity [Install] WantedBy=multi-user.target EOFsudo systemctl daemon-reloadsudo systemctl enable --now containerd
2.4 验证安装 1 2 3 4 5 6 7 8 9 10 11 systemctl status containerd containerd --version ctr versionls -l /run/containerd/containerd.sockls /var/lib/containerd/ ctr image pull docker.io/library/hello-world:latest ctr run --rm docker.io/library/hello-world:latest hello
安装检查清单:
2.5 目录与文件布局 1 2 3 4 5 6 7 8 9 10 11 12 /var/lib/containerd/ # 数据根目录(重要数据,需备份/监控) ├── io.containerd.content.v1.content/ # 内容存储(镜像 blob) ├── io.containerd.metadata.v1.bolt/ # 元数据(bolt 数据库) ├── io.containerd.snapshotter.v1.overlayfs/ # 快照(镜像层/容器层) ├── io.containerd.image.v1.containerd/ # 镜像存储(2.x 默认) └── tmp/ /run/containerd/ # 运行时状态(socket、shim 目录) ├── containerd.sock └── containerd.sock.ttrpc /etc/containerd/config.toml # 配置文件
磁盘规划 :/var/lib/containerd 与系统盘分离(独立分区/数据盘),并设置容量监控告警。
2.6 配置文件 config.toml 1 2 3 4 5 containerd config default > /etc/containerd/config.toml containerd config check
核心配置块解读(1.7 风格):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 root = "/var/lib/containerd" state = "/run/containerd" grpc.address = "/run/containerd/containerd.sock" grpc.uid = 0 grpc.gid = 0 disabled_plugins = []snapshotter = "overlayfs" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] runtime_type = "io.containerd.runc.v2" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://docker.m.daocloud.io" ][metrics] address = "127.0.0.1:1338"
1 2 3 sudo systemctl restart containerdsudo containerd config check
2.7 Windows 上的 containerd(简述)
官方提供 containerd-windows-amd64 压缩包与 MSI(2.x 提供 MSI)。
服务:sc.exe create containerd ... 或用 MSI 一键安装。
运行容器依赖 Windows 容器特性(Hyper-V 隔离/进程隔离),与 Linux 容器机制不同。
K8s Windows 节点同样用 containerd 作为运行时。
第 3 章 命令行工具:ctr / crictl / nerdctl 3.1 三个 CLI 的定位
工具
接口
面向
特点
ctr
containerd 原生 gRPC API
运维调试 containerd 本身
原始、命令少、需理解命名空间
crictl
CRI(Kubernetes 运行时接口)
K8s 节点排障
看 Pod/Sandbox 视角,K8s 标配
nerdctl
containerd 原生 API(模拟 docker)
日常开发/单机
命令与 docker 几乎一致,含 build/网络/卷
生产经验:K8s 节点优先用 crictl (与 kubelet 视角一致);单机测试/开发用 nerdctl;ctr 用来做底层诊断。
3.2 命名空间(Namespace) containerd 用命名空间逻辑隔离数据(镜像/容器/快照互不可见):
命名空间
使用者
default
ctr 默认
moby
Docker Engine
k8s.io
Kubernetes(kubelet/CRI)
1 2 3 4 5 6 7 8 9 10 11 ctr namespace ls ctr ns ls ctr ns create staging ctr ns remove staging ctr -n k8s.io images ls ctr -n moby images ls
运维提示:排查”镜像看不到/容器找不到”,先确认命名空间对不对。K8s 的一切都在 k8s.io 下。
3.3 ctr 常用命令(原生视图) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 ctr images ls ctr -n k8s.io images ls ctr images pull docker.io/library/nginx:alpine ctr images push registry.example.com/app:v1 ctr images rm docker.io/library/nginx:alpine ctr images import app.tar ctr images export app.tar app:v1 ctr images check ctr image ls ctr image pull --platform linux/amd64 nginx:alpine ctr containers ls ctr run --rm -t docker.io/library/alpine:latest shell /bin/sh ctr run -d --env TZ=Asia/Shanghai docker.io/library/redis:7-alpine redis ctr tasks ls ctr tasks kill -s SIGTERM redis ctr tasks exec -t --exec-id sh1 redis /bin/sh ctr containers rm redis ctr tasks rm redis ctr snapshots ls ctr content ls ctr content rm sha256:xxxx ctr events ctr plugins ls
ctr run 语法:
1 2 3 4 5 6 7 8 9 10 11 12 ctr run [options] <image-ref> <container-name> <command> [args...] # 常用参数 ctr run -d # 后台运行(detach) ctr run --rm # 退出即删容器 ctr run -t # 分配 TTY ctr run --env KEY=VAL # 环境变量 ctr run --cwd /app # 工作目录 ctr run --snapshotter overlayfs # 指定快照器 ctr run --runtime io.containerd.runc.v2 # 指定运行时 ctr run --mount type=bind,src=/data,dst=/data,options=rbind:ro # 挂载 ctr run --net-host # 使用宿主机网络(不依赖 CNI)
ctr 不管理网络(除非 --net-host),不提供端口映射/重启策略,这些由上层(CRI/CNI/nerdctl)负责。
3.4 crictl(CRI 视角,K8s 运维首选) 配置(/etc/crictl.yaml):
1 2 3 4 runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false
1 2 3 4 5 6 7 wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.30.0/crictl-v1.30.0-linux-amd64.tar.gz tar -C /usr/local/bin -xzf crictl-v1.30.0-linux-amd64.tar.gz crictl version
常用命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 crictl ps crictl ps -a crictl pods crictl pods -q | xargs -I{} crictl inspectp {} crictl images crictl pull nginx:alpine crictl rmi nginx:alpine crictl exec -it <container-id> sh crictl logs -f <container-id> crictl stats crictl top <container-id> crictl inspect <container-id> crictl inspectp <pod-id> crictl start/stop/rm <id > crictl events
crictl vs kubelet 注意事项:
crictl ps 的字段是 CRI 语义(CONTAINER / SANDBOX)。
crictl rmi 只删镜像引用,不回收层 ;磁盘回收主要靠 kubelet 的镜像 GC(--image-gc-high-threshold=85)。
不要用 crictl 乱删 K8s 的 Pod 容器——kubelet 会自动重建,除非你在排障。
端口转发:crictl portforward <pod-id> 8080:80(调试用)。
3.5 nerdctl(docker 兼容 CLI,强烈推荐) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 wget https://github.com/containerd/nerdctl/releases/download/v1.7.6/nerdctl-1.7.6-linux-amd64.tar.gz tar -C /usr/local/bin -xzf nerdctl-1.7.6-linux-amd64.tar.gz nerdctl ps nerdctl images nerdctl run -d -p 8080:80 --name web nginx:alpine nerdctl exec -it web sh nerdctl logs -f web nerdctl stop web && nerdctl rm web nerdctl build -t myapp:v1 . nerdctl compose up -d nerdctl network create app-net nerdctl volume create data-vol
前提条件:
网络功能依赖 CNI 插件(/opt/cni/bin)与 nerdctl 的 CNI 配置。
端口映射需要 rootlesskit(rootless 模式)或 root 权限。
build 功能需要 buildkit:containerd + buildkitd 两个 daemon。
3.6 三工具对照表(docker 习惯迁移)
操作
docker
crictl
nerdctl
ctr
列容器
docker ps
crictl ps
nerdctl ps
ctr containers ls
运行容器
docker run -d nginx
(由 K8s 管理)
nerdctl run -d nginx
ctr run -d nginx n1
进容器
docker exec -it c sh
crictl exec -it c sh
nerdctl exec -it c sh
ctr tasks exec -t --exec-id e c sh
看日志
docker logs -f c
crictl logs -f c
nerdctl logs -f c
无(需日志驱动/文件)
列镜像
docker images
crictl images
nerdctl images
ctr images ls
拉镜像
docker pull
crictl pull
nerdctl pull
ctr images pull
资源占用
docker stats
crictl stats
nerdctl stats
无
网络
内置
CNI(kubelet 配置)
CNI(自带配置)
无(–net-host)
第 4 章 镜像管理 4.1 containerd 镜像模型 containerd 对镜像的处理与 Docker 一致(OCI 标准),但存储更”原始”:
1 2 3 4 5 6 镜像 = 配置(manifest/config) + 层列表(blobs) /var/lib/containerd ├── io.containerd.content.v1.content/ # blob 二进制(压缩/未压缩层) └── io.containerd.snapshotter.v1.overlayfs/ └── snapshots/ # 解压后的只读快照(按需解压)
content store :保存所有 blob(镜像层、配置、清单),以 digest(sha256)寻址,天然去重。
snapshotter :把 blob 解压成挂载可用的快照链,容器可写层基于此。
元数据 :bolt 数据库记录镜像名 → digest 的映射(1.7 之前);2.x 引入独立的 image store(io.containerd.image.v1.containerd),镜像按名/摘要管理,删除更彻底、支持多引用。
2.x 默认启用 image store 后,ctr images ls/crictl images 的语义更接近 Docker:镜像删除会真正回收未引用内容。
4.2 镜像拉取与列出 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ctr images pull docker.io/library/nginx:1.27-alpine ctr images pull --platform linux/arm64 nginx:alpine ctr images ls --quiet ctr -n k8s.io images ls -q crictl pull nginx:1.27-alpine crictl images crictl images --digests nerdctl pull nginx:1.27-alpine nerdctl images
镜像全名格式(containerd 需要完整 repo 名):
1 2 3 docker.io/library/nginx:1.27-alpine registry.example.com/team/app:v1.2.3 docker.io/library/nginx@sha256:xxxx... # 按 digest 引用(最安全)
注意:ctr 里 nginx 简写可能解析失败,建议始终写全 docker.io/library/nginx。CRI/crictl 支持简写(内部会补全)。
4.3 镜像导入导出(离线分发) 1 2 3 4 5 6 7 8 9 10 11 ctr images export nginx.tar docker.io/library/nginx:1.27-alpine ctr images import nginx.tar ctr images export --platform linux/amd64 out.tar app:v1 ctr images import --no-unpack app.tar nerdctl save -o nginx.tar nginx:1.27-alpine nerdctl load -i nginx.tar
断网机房/离线交付:nerdctl save → 拷贝 → nerdctl load,或直接走私有 Registry。
4.4 镜像加速与私有仓库配置 containerd 的镜像加速配置在 CRI 插件的 registry.mirrors 下(不是 registry-mirrors 那种 Docker 顶层键)。
1.7 风格(config.toml):
1 2 3 4 5 6 7 8 9 10 11 [plugins."io.containerd.grpc.v1.cri".registry] config_path = "/etc/containerd/certs.d" [plugins."io.containerd.grpc.v1.cri".registry.mirrors] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = [ "https://docker.m.daocloud.io" , "https://dockerproxy.com" ] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.example.com"] endpoint = ["https://registry.example.com" ]
2.x / 推荐做法(certs.d 目录,声明式):
1 2 3 4 5 6 7 8 9 10 11 mkdir -p /etc/containerd/certs.d/docker.iocat > /etc/containerd/certs.d/docker.io/hosts.toml <<'EOF' server = "https://docker.io" [host."https://docker.m.daocloud.io" ] capabilities = ["pull" , "resolve" ] [host."https://registry.example.com" ] capabilities = ["pull" , "push" , "resolve" ] ca = "/etc/containerd/certs.d/registry.example.com/ca.crt" EOF
1 2 3 4 5 6 7 8 9 10 mkdir -p /etc/containerd/certs.d/registry.example.comcat > /etc/containerd/certs.d/registry.example.com/hosts.toml <<'EOF' server = "https://registry.example.com" [host."https://registry.example.com" ] ca = "/etc/containerd/certs.d/registry.example.com/ca.crt" [host."https://registry.example.com" .header] authorization = "Basic BASE64(user:password)" EOF
更推荐的认证方式:K8s 用 imagePullSecrets;containerd 侧也可用 crictl pull --creds user:pass / nerdctl login(登录凭据存入 containerd auth 文件,由 config_path 指定)。
4.5 镜像校验与安全 1 2 3 4 5 6 7 8 9 10 11 ctr images ls --digests ctr images check --ref docker.io/library/nginx:1.27-alpine ctr content ls | grep sha256 crictl images --digests crictl pull docker.io/library/nginx@sha256:2f23b580b8ba9d2b4f0... ctr images pull docker.io/library/nginx@sha256:2f23b580b8ba9d2b4f0...
镜像签名(Notation,containerd 1.7+ 实验、2.x 可用):
用 Notation 对镜像签名,containerd 在拉取时可校验签名(需启用 verify_image_signatures 相关配置/插件)。
Harbor 2.x 原生支持 Notation/Cosign 签名与验证,是生产首选路径。
4.6 镜像 GC 与磁盘回收 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 crictl rmi <image-id> ctr content prune ctr images ls -q | xargs -I{} sh -c 'echo {}' nerdctl system prune -a -f nerdctl image prune -f
血泪教训:K8s 节点 /var/lib/containerd 爆满的经典原因 = 日志不轮转 + 镜像 GC 阈值太高 + 悬空 blob。见第 9 章排障。
4.7 镜像平台与多架构 1 2 3 4 5 6 7 8 9 ctr images ls --digests ctr content get <manifest-digest> | jq . crictl pull --platform linux/arm64 ubuntu:24.04 ctr images pull --platform linux/arm64 ubuntu:24.04
手动装镜像到节点时注意架构匹配,否则报 exec format error(见附录报错表)。
第 5 章 容器与任务 5.1 容器(Container)与任务(Task)的区别 containerd 把”容器”拆成两个概念:
概念
含义
类比
Container
静态描述:镜像、rootfs 快照、配置(元数据)
docker 的容器配置
Task
实际运行中的进程实例(有 PID、状态)
进程本身
1 2 3 4 5 6 ctr containers create(只创建配置) | v ctr task start(启动进程)-> Running | +-> 停止/退出 -> Stopped(进程没了,容器配置还在)
一个 Container 可以多次创建/启动 Task(每次新进程)。
ctr run = containers create + tasks start 的便捷组合。
5.2 创建并运行容器(ctr) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ctr run -d \ --env TZ=Asia/Shanghai \ --env MYSQL_ROOT_PASSWORD=Root123! \ --mount type =bind ,src=/data/mysql,dst=/var/lib/mysql,options=rbind:rw \ docker.io/library/mysql:8.0 mysql ctr containers create docker.io/library/redis:7-alpine redis ctr tasks start redis ctr tasks ls ctr run --rm -t docker.io/library/alpine:3.20 shell /bin/sh ctr run --runtime io.containerd.runc.v2 --snapshotter overlayfs app:v1 myapp
生命周期命令:
1 2 3 4 5 6 7 8 ctr tasks ls ctr tasks kill -s SIGTERM redis ctr tasks kill --all -s SIGKILL redis ctr tasks pause redis ctr tasks resume redis ctr tasks rm -f redis ctr containers rm redis ctr containers rm -f redis
5.3 快照(Snapshotter)机制 快照是 containerd 管理 rootfs 的核心抽象:
1 2 3 4 Active 快照(可写,容器层) | v commit Committed 快照(只读,镜像层)<-- 可被多个容器共享
1 2 3 ctr snapshots ls ctr snapshots info <snapshot-key>
常用快照器对比:
快照器
说明
适用
overlayfs(默认)
基于内核 overlayfs,性能好、省磁盘
Linux 通用,首选
native
直接目录拷贝,无层共享
老内核/特殊文件系统
devmapper
基于 Device Mapper(thin provisioning)
overlayfs 不可用时
btrfs / zfs
基于文件系统快照
对应文件系统环境
nydus
容器镜像加速(按需加载)
大规模镜像分发优化
stargz
懒加载镜像(lazy pulling)
启动加速场景
1 2 3 4 ctr run --snapshotter devmapper ...
5.4 挂载(Mount) 1 2 3 4 5 6 7 8 9 10 11 12 ctr run -d \ --mount type =bind ,src=/srv/config,dst=/etc/app,options=rbind:ro \ app:v1 app ctr run -d \ --mount type =tmpfs,dst=/tmp,options=size=128m \ app:v1 app ctr run -d --rootfs-ro app:v1 app
注意:ctr 没有 docker 的”命名卷”概念;持久化靠 bind mount 或上层(nerdctl volume / K8s volume)。
5.5 nerdctl 视角(贴近 docker 体验) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 nerdctl run -d --name web \ -p 8080:80 \ -v /srv/www:/usr/share/nginx/html:ro \ -e TZ=Asia/Shanghai \ --restart unless-stopped \ nginx:1.27-alpine nerdctl ps -a nerdctl inspect web nerdctl exec -it web sh nerdctl logs -f web nerdctl stop web && nerdctl rm web nerdctl volume create data-vol nerdctl network create app-net nerdctl run -d --network app-net --name api myapi:v1
nerdctl 与 docker 的差异提醒:
--restart 由 nerdctl 自己实现(复刻策略),不是 containerd 原生能力。
端口映射依赖 CNI + iptables,rootless 模式依赖 rootlesskit。
nerdctl build 需要 buildkitd 在跑。
5.6 运行时(Runtime)概念 containerd 支持多 OCI 运行时,通过 shim 调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes] [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] runtime_type = "io.containerd.runc.v2" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc] runtime_type = "io.containerd.runc.v2" runtime_path = "/usr/local/bin/runsc" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata] runtime_type = "io.containerd.kata.v2"
1 2 ctr run --runtime io.containerd.runc.v2 alpine:3.20 shell /bin/sh
K8s 中通过 RuntimeClass 选择运行时(runtimeClassName: runsc)。
第 6 章 CRI 集成与 Kubernetes 6.1 什么是 CRI CRI(Container Runtime Interface) 是 Kubernetes 定义的、kubelet 与容器运行时之间的标准接口 (gRPC + protobuf),包含两组服务:
1 2 3 4 5 6 7 8 9 10 kubelet | |-- RuntimeService(管理 Pod sandbox 与容器生命周期) | RunPodSandbox / CreateContainer / StartContainer / StopPodSandbox ... | |-- ImageService(管理镜像) PullImage / ListImages / RemoveImage ... | v containerd(CRI 插件 io.containerd.grpc.v1.cri)
kubelet 不关心底层是 Docker/containerd/CRI-O,只认 CRI。
containerd 的 CRI 插件把 CRI 请求翻译成 containerd 原生 API。
自 K8s 1.24 移除 dockershim 后,containerd 成为默认/主流运行时。
6.2 节点准备(kubeadm 部署前) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 containerd config default | grep -A3 'cri' sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.tomlsudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.tomlsudo systemctl restart containerd crictl version crictl pods
核心配置项(CRI 相关):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 version = 2 root = "/var/lib/containerd" state = "/run/containerd" [plugins."io.containerd.grpc.v1.cri"] sandbox_image = "registry.k8s.io/pause:3.10" enable_selinux = false enable_unprivileged_ports = true enable_unprivileged_icmp = true [plugins."io.containerd.grpc.v1.cri".containerd] snapshotter = "overlayfs" default_runtime_name = "runc" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] runtime_type = "io.containerd.runc.v2" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true [plugins."io.containerd.grpc.v1.cri".registry] config_path = "/etc/containerd/certs.d"
6.3 Pod 与 Sandbox(pause)机制 K8s 的”Pod”在运行时层面 = sandbox(pause 容器) + 业务容器:
1 2 3 4 Pod sandbox(pause 容器) ├── 持有网络命名空间 / 共享网络栈 ├── 持有 IPC、UTS namespace └── 业务容器(app1、sidecar...)加入 sandbox 的命名空间
pause 镜像默认 registry.k8s.io/pause:3.10(不同 K8s 版本要求不同版本)。
国内环境必须把 sandbox_image 换成可访问的镜像源(如 registry.aliyuncs.com/google_containers/pause:3.10)。
1 2 3 4 5 6 crictl pods crictl inspectp <sandbox-id> crictl pull registry.k8s.io/pause:3.10
高频故障 :节点无法拉取 pause 镜像 → Pod 一直 ContainerCreating(Error: ErrImagePull)。处理:配置镜像加速/换源,或预拉 pause 镜像到节点。
6.4 kubelet 对接 1 2 3 4 --container-runtime-endpoint=unix:///run/containerd/containerd.sock --kubelet-cgroups=/systemd/system.slice --cgroup-driver=systemd
kubeadm 初始化:
1 2 kubeadm config print init-defaults --component-configs KubeletConfiguration > kubeadm-init.yaml
1 2 3 4 5 6 7 kind: KubeletConfiguration cgroupDriver: systemd --- kind: InitConfiguration --- kind: ClusterConfiguration
1 2 3 kubeadm init --config kubeadm-init.yaml kubectl get nodes kubectl get pods -A
kubelet + containerd 健康自检:
1 2 3 4 crictl version crictl pods journalctl -u kubelet -n 100 crictl logs <container-id>
6.5 K8s 节点日常排障(crictl 实战) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 kubectl get pods -A -o wide kubectl describe pod <pod> -n <ns> crictl ps -a crictl inspect <container-id> | grep -A5 -i state crictl logs -f <container-id> crictl exec -it <container-id> sh crictl stats crictl images crictl pull <image> crictl events
常见 CRI 问题对照:
现象
常见原因
处理
Pod 卡 ContainerCreating
pause 镜像拉不到
配加速/换 sandbox_image
ErrImagePull / ImagePullBackOff
镜像不存在/仓库认证失败
crictl pull 复现;配 imagePullSecrets
CrashLoopBackOff
应用启动失败
crictl logs 看退出原因
节点 NotReady
containerd 挂了/cgroup 驱动不一致
systemctl status containerd;检查 SystemdCgroup
sandbox 泄漏(大量 exited sandbox)
异常删除 Pod
重启 kubelet/containerd 清理
failed to create containerd task
快照/存储异常、权限
看 containerd 日志、检查磁盘
exec format error
架构不匹配
换对应架构镜像
6.6 卸载/更换运行时(Docker → containerd 迁移) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 kubectl drain <node> --ignore-daemonsets --delete-emptydir-datasudo systemctl stop dockersudo apt-get purge -y docker-ce docker-ce-cli containerd.io sudo apt-get purge -y docker-ce docker-ce-cli docker-buildx-plugin docker-compose-plugin kubectl uncordon <node>
重要 :containerd.io 与 Docker Engine 是同一发行渠道;迁移时只移除 docker-ce,保留 containerd.io 即可无缝切换。
第 7 章 网络与存储 7.1 containerd 的网络模型 核心事实:containerd 自己不管理 Pod 网络。
CRI 场景:kubelet 调用 CNI 插件 (calico/flannel/cilium 等)为 sandbox 配置网络。
nerdctl 场景:nerdctl 自带 CNI 配置(bridge/portmap 等插件)实现网络与端口映射。
ctr 场景:默认无网络(只有 --net-host)。
1 2 3 4 Pod sandbox 创建 -> kubelet 调用 CNI(/opt/cni/bin + /etc/cni/net.d 配置) -> 插件创建 veth、分配 IP、配置路由 -> 业务容器加入 sandbox 网络命名空间
1 2 3 4 5 6 ls /opt/cni/bin ls /etc/cni/net.d/ /opt/cni/bin/bridge --version 2>/dev/null || echo "bridge not found"
常用 CNI 插件:
插件
特点
适用
bridge + portmap
默认/最简
单机、nerdctl
flannel
VXLAN 覆盖网络,简单
小集群
calico
BGP/overlay、NetworkPolicy、性能好
生产主流
cilium
eBPF、服务网格能力、高性能
大规模/云原生高级场景
7.2 存储(快照与数据)
镜像层:snapshotter 管理(见 5.3)。
容器可写层:默认 overlayfs,限制与 Docker 相同(写敏感应用建议挂载)。
K8s 数据卷:由 CSI(Container Storage Interface)插件负责,containerd 不参与。
日志:K8s 场景由 kubelet 写到 /var/log/pods;containerd 不直接管理容器日志。
生产存储建议:
/var/lib/containerd 放独立数据盘,监控容量。
高 IO 的数据库类工作负载:避免 overlayfs 可写层,用宿主机裸盘/CSI 本地卷 + 数据目录挂载。
大批量镜像分发:评估 nydus/stargz 懒加载方案降低启动时间。
7.3 nerdctl 网络实战(单机) 1 2 3 4 5 6 7 8 9 nerdctl network ls nerdctl network create --subnet 10.10.0.0/24 app-net nerdctl run -d --network app-net --name api myapi:v1 nerdctl run -d --network app-net -p 8080:80 --name web nginx:alpine nerdctl exec web getent hosts api nerdctl network inspect app-net
7.4 镜像存储与 GC 调优(K8s 生产) 1 2 3 4 5 6 7 imageGCHighThresholdPercent: 85 imageGCLowThresholdPercent: 80 crictl rmi --prune nerdctl -n k8s.io image prune -a -f
不要直接删 /var/lib/containerd 下的文件 ——绕过 API 会导致元数据不一致,只能用 GC 工具。
第 8 章 安全加固 8.1 安全面梳理
层面
风险
措施
守护进程
socket 未授权访问、远程 gRPC 裸奔
收紧权限、不开放 TCP、认证
镜像供应链
恶意/带漏洞镜像、被投毒镜像
私有仓库 + 签名验证 + 扫描
运行时
容器逃逸、内核漏洞
非 root、seccomp/AppArmor、最小能力
配置
敏感信息入镜像、root 运行
规范 Dockerfile/CRI 配置
节点
K8s 攻击面(kubelet 未认证等)
加固 OS + RBAC + 审计
8.2 守护进程安全 1 2 3 4 5 6 7 8 9 10 ls -l /run/containerd/containerd.sock grep -A3 'grpc' /etc/containerd/config.toml auditctl -w /var/lib/containerd -k containerd
containerd 官方不支持无认证的远程 gRPC 暴露;远程管理一律走受控通道(SSH、K8s API、堡垒机)。
8.3 镜像安全 1 2 3 4 5 6 7 8 9 10 trivy image registry.example.com/app:v1.2.3 --severity HIGH,CRITICAL --ignore-unfixed notation cert add --type ca --store mytrust ca.crt notation sign --key mykey registry.example.com/app:v1.2.3
供应链安全基线:
镜像锁定 digest(image@sha256:...)。
CI 中加入漏洞扫描门禁(HIGH/CRITICAL 阻断发布)。
Harbor/私有仓库开启内容信任与签名策略。
定期更新基础镜像与运行时(runc 升级尤其重要,历史多次逃逸 CVE 出在 runc)。
8.4 运行时安全(容器内)
CRI 配置示例(config.toml):
1 2 3 4 5 6 7 8 9 [plugins."io.containerd.grpc.v1.cri".containerd] default_runtime_name = "runc" discard_unpacked_layers = true [plugins."io.containerd.grpc.v1.cri"] enable_selinux = true enable_unprivileged_ports = true enable_unprivileged_icmp = true enable_seccomp = true
K8s 安全上下文示例:
1 2 3 4 5 6 7 8 9 securityContext: runAsNonRoot: true runAsUser: 1001 readOnlyRootFilesystem: true allowPrivilegeEscalation: false capabilities: drop: ["ALL" ] seccompProfile: type: RuntimeDefault
8.5 Rootless 模式 containerd 支持 rootless(非 root 运行),配合用户命名空间:
1 2 3 4 5 6 7 8 9 10 sudo sysctl kernel.unprivileged_userns_clone=1 containerd-rootless-setuptool.sh install containerd-rootless-setuptool.sh install-buildkit containerd-rootless-setuptool.sh install-kubectl nerdctl run -d -p 8080:80 nginx:alpine
rootless 依赖:fuse-overlayfs、slirp4netns/rootlesskit;性能与功能有取舍(如部分网络能力受限)。适合开发与多租户场景,生产 K8s 节点通常仍用 root 模式 + 纵深防御。
8.6 加固检查清单
第 9 章 运维与故障排查 9.1 日志体系 1 2 3 4 5 6 7 8 containerd daemon 日志(systemd journal) journalctl -u containerd -n 200 -f 容器标准输出(K8s 场景由 kubelet 接管) /var/log/pods/<ns>_<pod>_<uid>/<container>/0.log shim 日志(每个容器) /run/containerd/io.containerd.runtime.v2.task/<ns>/<container>/log.json
1 2 3 journalctl -u containerd -n 100 --no-pager journalctl -u containerd --since "10 minutes ago" journalctl -u kubelet -n 100 --no-pager
containerd 本身不负责容器日志持久化;单机用 nerdctl 时日志在 shim 的 log.json,可配日志轮转。
9.2 磁盘爆满(第一高频事故) 排查顺序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 df -h /var/lib/containerddu -sh /var/lib/containerd/* | sort -hdu -sh /var/log/pods 2>/dev/null | sort -hdu -sh /run/containerd/io.containerd.runtime.v2.task/* 2>/dev/null | sort -h crictl images ctr -n k8s.io content ls | head -20 crictl rmi --prune crictl images | grep '<none>' ctr -n k8s.io content prune nerdctl system prune -a -f
containerd 日志轮转(CRI 配置):
1 2 3 4 5 6 7 [plugins."io.containerd.grpc.v1.cri".containerd] max_container_log_line_size = 16384 [plugins."io.containerd.grpc.v1.cri".containerd.logs] max_size = 52428800 max_files = 5
9.3 常见故障速查表
现象
原因
处置
failed to connect to /run/containerd/containerd.sock
containerd 未启动/崩溃
systemctl status containerd,看 journal
Pod 一直 ContainerCreating
pause 镜像拉不到/CNI 故障
crictl pods + crictl pull pause
ErrImagePull
镜像不存在/无权限
crictl pull 复现;检查认证与地址
容器启动报 permission denied
非 root 用户无权限/AppArmor
检查镜像 USER、挂载属主
exec format error
架构不匹配
拉取对应 --platform 镜像
节点 NotReady
containerd 或网络插件异常
journal 定位;重启 containerd/calico
大量 exited sandbox
异常 Pod 清理不彻底
重启 kubelet;crictl rmp -f 清理
failed to reserve sandbox name
同名 sandbox 残留
crictl rmp 删除残留沙箱
磁盘持续增长
镜像 GC 不回收/日志不轮转
见 9.2
unexpected EOF 拉取中断
网络/仓库不稳定
重试、配加速、加代理
no such image(ctr)
命名空间/名称写错
-n k8s.io;写全镜像名
9.4 性能调优 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 version = 2 root = "/var/lib/containerd" state = "/run/containerd" max_concurrent_downloads = 10 max_concurrent_uploads = 5 [plugins."io.containerd.grpc.v1.cri".containerd] discard_unpacked_layers = true net.ipv4.ip_local_port_range = 1024 65535 net.core.somaxconn = 1024 fs.file-max = 1000000
1 sysctl -w vm.max_map_count=262144
性能要点:
使用 overlayfs 快照器(默认),避免 native。
镜像构建阶段就尽量精简(层数、大小),减少拉取/解压时间。
大批量镜像预热:提前 crictl pull 或使用懒加载(nydus)。
高并发创建容器:关注 shim 数量与 PID 限制(TasksMax=infinity)。
基准:ctr 创建容器毫秒级;对比 Docker 多一层 daemon 开销更小。
9.5 备份与迁移 1 2 3 4 5 6 7 8 9 10 11 12 13 sudo systemctl stop containerdsudo tar -czf /backup/containerd-$(date +%F).tar.gz /var/lib/containerdsudo mkdir -p /var/lib/containerdsudo tar -xzf /backup/containerd-xxxx.tar.gz -C /sudo systemctl start containerd ctr -n k8s.io images ls | head
备份注意:跨 containerd 大版本恢复不一定兼容(bolt 元数据格式变化),建议用镜像仓库做制品备份 ,/var/lib/containerd 只做节点级灾备。数据库等有状态数据务必走应用自身备份。
9.6 事件与指标 1 2 3 4 5 6 7 8 9 ctr events --namespace k8s.io crictl events curl -s http://127.0.0.1:1338/metrics | grep -E '^container|^containerd'
关键指标:
containerd_containers_total / containerd_tasks_running
containerd_events_total
container_tasks_state
containerd_snapshotter_*(快照使用)
Grafana 面板建议: node-exporter(主机)+ cAdvisor(容器)+ containerd metrics(运行时)。
9.7 巡检脚本骨架 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #!/bin/bash set -euo pipefail systemctl is-active containerd >/dev/null || echo "ALERT: containerd down" USAGE=$(df -h /var/lib/containerd | awk 'NR==2{print $5}' | tr -d '%' ) [ "$USAGE " -gt 80 ] && echo "ALERT: disk usage ${USAGE} %" ABNORMAL=$(crictl ps -a --state exited 2>/dev/null | wc -l) [ "$ABNORMAL " -gt 50 ] && echo "ALERT: ${ABNORMAL} exited containers" crictl version >/dev/null 2>&1 || echo "ALERT: cri endpoint unreachable"
第 10 章 进阶与生态 10.1 插件体系 containerd 由插件构成,全部通过 gRPC 接口注册:
config.toml 中启用/禁用插件:
1 2 3 4 disabled_plugins = []required_plugins = []
10.2 内容校验、租约(Lease)与 GC
Content 按 digest 寻址 :天然防篡改、自动去重。
Lease :给内容打”引用标记”,防止 GC 误删(如”正在解压”的内容)。
GC :containerd 定期清理未被引用的 content/snapshots;也可手动 ctr content prune。
10.3 Go 客户端编程(简介) containerd 官方 Go 客户端是上层工具(nerdctl、kubelet CRI 插件)的基础:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package mainimport ( "context" "log" "github.com/containerd/containerd" "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/oci" )func main () { client, err := containerd.New("/run/containerd/containerd.sock" ) if err != nil { log.Fatal(err) } defer client.Close() ctx := namespaces.WithNamespace(context.Background(), "default" ) image, err := client.Pull(ctx, "docker.io/library/alpine:3.20" ) if err != nil { log.Fatal(err) } container, err := client.NewContainer( ctx, "demo" , containerd.WithImage(image), containerd.WithNewSnapshot("demo-snap" , image), containerd.WithNewSpec(oci.WithImageConfig(image), oci.WithProcessArgs("/bin/sh" , "-c" , "echo hello; sleep 5" )), ) if err != nil { log.Fatal(err) } defer container.Delete(ctx, containerd.WithSnapshotCleanup) log.Println("container created:" , container.ID()) }
1 2 go get github.com/containerd/containerd/v2
一般运维不需要写 Go;了解 API 分层有助于理解 nerdctl/kubelet 行为。
10.4 nerdctl 完整能力(开发/单机主力) 1 2 3 4 5 6 nerdctl run / ps / exec / logs / inspect / stats nerdctl build / commit / tag / push / pull nerdctl compose up -d nerdctl network / volume / namespace nerdctl image prune / system prune nerdctl info
与 Docker CLI 的细微差异:
nerdctl run -d 默认不分配 TTY;-it 行为一致。
端口映射依赖 CNI portmap 插件。
nerdctl build 依赖 buildkitd(systemctl start buildkit 或 nerdctl builder)。
支持 rootless 全链路。
10.5 与生态的完整关系图 1 2 3 4 5 6 7 8 9 10 11 12 开发者视角: Docker CLI / docker compose / nerdctl | | v v BuildKit(构建) containerd(运行) | | +--------+---------+ v Kubernetes(CRI + CNI + CSI) | v containerd(每节点运行时)
什么时候选什么:
场景
推荐
开发机/单机容器体验
Docker Desktop 或 nerdctl
生产 K8s 集群
containerd(每节点)+ CRI
边缘/嵌入式
containerd 精简部署
离线内网
containerd + Harbor + crictl/nerdctl
多租户开发隔离
rootless containerd + nerdctl
10.6 containerd 2.x 升级要点 1 2 3 4 5 6 7 8 9 10 11 containerd --version ctr version containerd config dump > /tmp/config-backup.tomlsudo systemctl stop containerdsudo tar -C /usr/local -xzf containerd-2.0.x-linux-amd64.tar.gzsudo containerd config checksudo systemctl start containerd crictl version && crictl pods
2.x 主要变化(迁移注意):
默认启用独立镜像存储(image store),镜像管理行为更接近 Docker。
配置语法/字段变化:用 containerd config default 重新生成并合并自己的修改。
移除部分废弃 API/插件(旧 snapshotters、旧客户端版本)。
runc 升级到 v3 运行时接口(runc 版本需配套)。
更多细节以官方升级文档为准。
升级原则:测试环境先验证 → 灰度节点 → 全量;K8s 集群升级 containerd 前确认与 kubelet 版本兼容矩阵。
第 11 章 常用命令速查表 11.1 ctr(原生) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ctr version ctr namespace ls / ns create / ns remove ctr images pull docker.io/library/nginx:alpine ctr images push registry.example.com/app:v1 ctr images ls [-q] ctr images rm <image> ctr images import app.tar ctr images export app.tar <image> ctr images check ctr images prune ctr content ls ctr content rm sha256:xxxx ctr containers ls ctr run -d --env A=B --mount type =bind ,src=/x,dst=/y img name ctr run --rm -t img sh ctr tasks ls ctr tasks exec -t --exec-id e1 name sh ctr tasks kill -s SIGTERM name ctr tasks pause/resume name ctr tasks rm -f name ctr containers rm -f name ctr snapshots ls ctr events ctr plugins ls ctr leases list
11.2 crictl(CRI / K8s 节点) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 crictl version crictl ps [-a] crictl pods crictl images crictl pull nginx:alpine crictl rmi <image> crictl exec -it <id > sh crictl logs -f <id > crictl stats crictl top <id > crictl inspect <id > crictl inspectp <pod-id> crictl start/stop/rm/rmp <id > crictl events crictl portforward <pod-id> 8080:80 crictl rmi --prune
11.3 nerdctl(docker 兼容) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 nerdctl version nerdctl run -d -p 8080:80 --name web nginx:alpine nerdctl ps -a nerdctl exec -it web sh nerdctl logs -f web nerdctl stop/start/restart/rm web nerdctl images / pull / push / tag / rmi nerdctl save -o x.tar img nerdctl load -i x.tar nerdctl build -t app:v1 . nerdctl compose up -d nerdctl network ls /create/rm nerdctl volume ls /create/rm nerdctl stats nerdctl system prune -a -f nerdctl image prune -f nerdctl info
11.4 系统级 1 2 3 4 5 6 7 systemctl status/start/stop/restart containerd journalctl -u containerd -n 200 -f containerd config default > /etc/containerd/config.toml containerd config check crictl version ss -l | grep containerddf -h /var/lib/containerd
附录 A. 术语表
术语
含义
OCI
开放容器标准(image/runtime 规范)
CRI
Kubernetes 容器运行时接口
CNI
容器网络接口(K8s Pod 网络)
CSI
容器存储接口(K8s 卷)
Sandbox
CRI 中的 Pod 沙箱(pause 容器)
Shim
每容器一个的 containerd 垫片进程
Snapshotter
rootfs 快照管理(存储驱动)
Content Store
镜像 blob 内容存储
Namespace
containerd 数据逻辑隔离空间
Task
运行中的容器进程实例
Lease
内容引用标记(防 GC)
RuntimeClass
K8s 选择容器运行时的机制
Rootless
非 root 运行容器
B. 官方与推荐资料
C. 常见报错对照表
报错
含义
处理
failed to connect to containerd
daemon 不可达
启动 containerd;检查 socket
connection refused
socket 未监听/权限
ss -lx;确认用户
permission denied(socket)
非 root/非 containerd 组
sudo 或加组
not found: image ...
镜像不存在/命名空间错
用 -n k8s.io;写全名
failed to resolve reference
拉取失败(网络/认证)
配加速/仓库认证
image is not used 删除失败
镜像仍被容器引用
删容器后再删镜像
exec format error
架构不匹配
换 --platform 镜像
failed to create shim task
运行时/快照/权限问题
journal 定位;查 runc 版本
sandbox name already reserved
sandbox 残留
crictl rmp -f 清理
no space left on device
磁盘满
见 9.2 清理流程
snapshot already exists
同名快照冲突
删旧容器/快照再试
unexpected EOF
拉取中断
重试/换源/加代理
D. 进阶自测清单
学完本手册,你就掌握了云原生”运行时底座”。下一步建议深入 Kubernetes 控制面(kubelet、CRI、CNI 插件)与镜像供应链安全(签名、扫描、策略)。