Kubernetes 1.24 起正式移除 Dockershim。这不是一次“可选升级”,而是一次架构层面的必然迁移。
本文将带你完成一次企业级生产可落地的迁移方案,包含:
- ✅ 架构原理讲解
- ✅ 迁移完整流程
- ✅ 企业级滚动 SOP
- ✅ 常见事故复盘
- ✅ 优化与监控适配
- ✅ 回滚预案
一、为什么必须迁移?
在 Kubernetes v1.20 开始弃用 dockershim,v1.24 正式移除。
旧架构:
Kubelet
│
Dockershim
│
Docker Engine
│
containerd
│
runc
新架构:
Kubelet
│
CRI Plugin
│
containerd
│
runc
本质区别
| 对比项 |
Docker |
Containerd |
| CRI 支持 |
通过 dockershim |
原生支持 |
| 组件数量 |
多一层 Engine |
更轻量 |
| 资源占用 |
较高 |
更低 |
| 社区趋势 |
已边缘化 |
主流 |
👉 containerd 本来就是 Docker 的底层运行时。 迁移,本质是“去掉 Docker 外壳”。
二、Containerd 架构深度解析
containerd 是 CNCF 孵化项目,属于云原生核心基础设施,是构建现代容器平台的关键云原生/IaaS组件。
内部架构
containerd
├── CRI Plugin
├── Image Service
├── Snapshotter (overlayfs)
├── Runtime (runc)
└── Shim v2
关键机制
1️⃣ CRI Plugin
直接对接 kubelet,无需适配层。
2️⃣ Snapshotter
默认 overlayfs,支持:
3️⃣ Shim v2
每个容器独立 shim 进程:
三、迁移总体策略(生产推荐)
⚠️ 原则:逐节点滚动迁移
生产标准流程:
for node in cluster:
cordon
drain
migrate runtime
restart kubelet
verify Ready
uncordon
四、企业级迁移完整步骤
Step 1:节点隔离
kubectl cordon <node>
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
Step 2:停止 Docker
systemctl stop kubelet
systemctl stop docker
systemctl disable docker
Step 3:安装 Containerd
Ubuntu:
apt install containerd -y
CentOS:
yum install containerd.io -y
Step 4:生成默认配置
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
Step 5:生产级优化配置
1️⃣ 统一 cgroup
SystemdCgroup = true
必须与 kubelet 保持一致。
2️⃣ 配置 pause 镜像
sandbox_image = "registry.k8s.io/pause:3.9"
3️⃣ 国内镜像加速(必做)
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://registry.aliyuncs.com"]
Step 6:启动 containerd
systemctl enable containerd --now
Step 7:修改 kubelet 运行时
编辑 kubelet 服务配置文件(通常位于 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf),确保包含以下参数:
--container-runtime=remote
--container-runtime-endpoint=unix:///run/containerd/containerd.sock
Step 8:重启 kubelet
systemctl daemon-reload
systemctl start kubelet
Step 9:验证节点
kubectl get nodes
kubectl describe node | grep Runtime
应显示:
containerd://x.x.x
Step 10:恢复调度
kubectl uncordon <node>
五、生产事故复盘(真实案例)
🚨 案例:迁移后所有节点 NotReady
现象:
container runtime network not ready
排查:
journalctl -u kubelet -f
发现:
- kubelet 使用 systemd cgroup
- containerd 默认 cgroupfs
解决:
在 /etc/containerd/config.toml 中设置 SystemdCgroup = true,重启 containerd + kubelet,节点恢复。
🚨 案例:Pod 无法拉取镜像
原因:
- 未配置 registry mirror
- pause 镜像拉取失败
解决:
配置 registry.mirrors 并重启 containerd。
六、迁移后验证清单(Checklist)
1️⃣ 节点状态
kubectl get nodes
2️⃣ CRI 验证
crictl info
crictl ps
3️⃣ 监控系统
如果你使用 Prometheus、Fluentd、Filebeat 等监控日志工具,必须检查采集路径是否仍在正常工作,例如 /var/log/pods/ 和 /var/log/containers/ 的日志是否正常生成和采集。这种底层运行时变更,是运维/DevOps/SRE工作中需要重点关注的环节。
七、Docker 命令对照表
| Docker |
Containerd |
| docker ps |
crictl ps |
| docker images |
crictl images |
| docker logs |
crictl logs |
| docker exec |
crictl exec |
如果想保持 Docker 使用习惯,可以安装 nerdctl:
nerdctl ps
nerdctl run nginx
八、版本兼容建议
| Kubernetes |
Containerd |
| 1.23 |
1.6.x |
| 1.24 |
1.6.x |
| 1.25+ |
1.7.x |
⚠️ 不建议使用 1.5 以下版本。
九、回滚方案(生产保命)
kubectl cordon <node>
kubectl drain <node>
systemctl stop kubelet
systemctl stop containerd
systemctl enable docker --now
# 修改 kubelet 配置,将 runtime 改回 docker
# --container-runtime=docker
systemctl start kubelet
kubectl uncordon <node>
十、迁移后的收益
| 维度 |
改善 |
| 启动速度 |
更快 |
| 内存占用 |
更低 |
| 组件复杂度 |
更简单 |
| 社区支持 |
更强 |
🎯 终极总结
从 Docker 到 Containerd 迁移,不是简单换工具,而是 Kubernetes 架构彻底 CRI 化的标志。如果你还在使用 Docker 运行时,那更多是“历史遗留”,而非面向未来的技术方向。
🔥 给生产环境管理员的建议
强烈建议:
- 先在测试环境全流程演练
- 使用滚动迁移,控制影响面
- 严格验证监控和日志采集链路
- 准备好随时可执行的回滚预案
遵循本文的步骤与注意事项,你可以平稳地完成这次重要的基础设施升级。如果在迁移过程中遇到更多复杂场景,欢迎到云栈社区的技术板块与其他工程师交流探讨。