Kubernetes 对接 Docker shim 废弃后 containerd 怎么迁移

文章导读
Kubernetes v1.24 正式移除了 Dockershim 组件,升级至此版本及以上前,必须将节点运行时从 Docker 迁移至 containerd,否则 kubelet 无法管理容器。
📋 目录
  1. A 迁移前准备
  2. B 步骤一:安装与配置 Containerd
  3. C 步骤二:迁移容器镜像
  4. D 步骤三:修改 Kubelet 配置
  5. E 怎么验证是否生效
  6. F 常见坑与排查
  7. G 参考来源
A A

Kubernetes v1.24 正式移除了 Dockershim 组件,升级至此版本及以上前,必须将节点运行时从 Docker 迁移至 containerd,否则 kubelet 无法管理容器。

先说结论:升级至 1.24 及以上版本前,必须将节点运行时从 Docker 迁移至 containerd,否则 kubelet 无法管理容器。

  • 适合:Kubernetes 1.24 及更高版本集群,或计划升级至此版本的场景
  • 先准备:备份节点数据,确认工作负载不依赖节点上的 Docker 命令构建镜像,务必提前迁移或预热镜像
  • 验收:检查节点运行时状态为 containerd,且业务 Pod 正常运行,Cgroup 驱动一致

迁移前准备

迁移过程建议先在测试环境验证,生产环境建议在业务低峰期操作。操作前请务必备份关键配置文件,以便出现问题时快速回滚。

# 备份 containerd 配置
cp /etc/containerd/config.toml /etc/containerd/config.toml.bak

# 备份 kubelet 配置
cp /etc/systemd/system/kubelet.service.d/10-kubeadm.conf /etc/systemd/system/kubelet.service.d/10-kubeadm.conf.bak

步骤一:安装与配置 Containerd

安装 containerd 后,生成的默认配置通常不满足 Kubernetes 要求,特别是 Cgroup 驱动设置。直接使用默认配置可能导致节点 NotReady。

# 生成 containerd 默认配置
containerd config default | sudo tee /etc/containerd/config.toml

修改配置说明:不建议直接使用 sed 替换,不同版本配置结构可能不同。请手动编辑 /etc/containerd/config.toml,找到 [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] 部分,确保 SystemdCgroup 设置为 true

Kubernetes 对接 Docker shim 废弃后 containerd 怎么迁移
[plugins."io.containerd.grpc.v1.cri"]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

修改完成后重启服务:

systemctl daemon-reload
systemctl restart containerd
systemctl enable containerd

步骤二:迁移容器镜像

Docker 与 containerd 镜像存储隔离,直接停止 Docker 未迁移镜像会导致 Pod 无法启动。需将 Docker 中的业务镜像导出并导入到 containerd 的 k8s.io 命名空间中。

# 1. 从 Docker 导出镜像
docker save -o my-app.tar my-app:latest

# 2. 导入到 containerd (注意指定 k8s.io 命名空间)
ctr -n k8s.io images import my-app.tar

# 3. 验证导入结果
ctr -n k8s.io images | grep my-app

若集群规模较大,建议编写脚本批量处理所有业务镜像。

Kubernetes 对接 Docker shim 废弃后 containerd 怎么迁移

步骤三:修改 Kubelet 配置

需指定 Kubelet 使用 containerd 的 CRI Socket。根据安装方式不同,配置文件路径有所区别。

场景 A: Kubeadm 安装 (常见)

编辑 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf,找到 KUBELET_EXTRA_ARGS 行。

# 修改前
KUBELET_EXTRA_ARGS=`--node-ip`=192.168.1.10

# 修改后 (添加 runtime-endpoint)
KUBELET_EXTRA_ARGS=`--node-ip`=192.168.1.10 `--container-runtime-endpoint`=unix:///run/containerd/containerd.sock

场景 B: 二进制安装

Kubernetes 对接 Docker shim 废弃后 containerd 怎么迁移

修改 kubelet 启动脚本或 systemd service 文件,添加 `--container-runtime-endpoint`=unix:///run/containerd/containerd.sock 参数。

配置修改完成后重载并重启:

systemctl daemon-reload
systemctl restart kubelet

怎么验证是否生效

检查节点运行时状态为 containerd,且业务 Pod 正常运行。

# 查看节点信息,确认 CONTAINER-RUNTIME 列显示 containerd
kubectl get nodes -o wide

# 查看 CRI 运行时信息
crictl info

# 检查 Pod 状态
kubectl get pods -A

常见坑与排查

  • 镜像缺失:containerd 与 Docker 镜像存储隔离,需重新拉取或导入镜像。若 Pod 处于 ImagePullBackOff,检查 ctr -n k8s.io images 是否存在对应镜像。
  • Cgroup 驱动不一致:会导致 Kubelet 启动失败。需确保 kubelet 与 containerd 一致(推荐 systemd)。查看 kubelet 日志 journalctl -u kubelet 排查。
  • Docker 特有功能依赖:工作负载若依赖 Docker 特有功能(如 docker.sock 挂载),需提前评估兼容性,改为使用 CRI 兼容方式。
  • 配置格式错误:修改 config.toml 时注意 TOML 格式规范,缩进错误会导致 containerd 无法启动。

参考来源