Kubernetes 对接 Docker shim 废弃后,containerd 配置怎么迁移?

文章导读
Kubernetes v1.24 版本正式移除了 Dockershim 组件,集群节点不再能直接使用 Docker Engine 作为容器运行时,必须迁移到符合 CRI 标准的运行时,如 containerd。迁移过程涉及运行时配置、Kubelet 参数调整及镜像处理,需严谨操作以避免业务中断。
📋 目录
  1. 1. 配置 Containerd(重点修正 Cgroup)
  2. 2. 修改 Kubelet 启动参数
  3. 3. 镜像迁移与预热
  4. 4. 验证与回滚
  5. 常见故障排查
A A

Kubernetes v1.24 版本正式移除了 Dockershim 组件,集群节点不再能直接使用 Docker Engine 作为容器运行时,必须迁移到符合 CRI 标准的运行时,如 containerd。迁移过程涉及运行时配置、Kubelet 参数调整及镜像处理,需严谨操作以避免业务中断。

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

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

1. 配置 Containerd(重点修正 Cgroup)

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

步骤:

  1. 生成默认配置文件:
mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
  1. 关键修改:启用 systemd cgroup 驱动。Kubernetes 推荐使用 systemd 驱动,需确保 kubelet 与 containerd 一致。
# 将 SystemdCgroup = false 修改为 true
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml

# 验证修改是否生效
grep SystemdCgroup /etc/containerd/config.toml
  1. 重启 containerd 服务:
systemctl daemon-reload
systemctl restart containerd
systemctl enable containerd

2. 修改 Kubelet 启动参数

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

场景 A:Kubeadm 安装(常见)

通常通过 systemd drop-in 文件配置。编辑 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

# 找到 KUBELET_EXTRA_ARGS 行,添加或修改 runtime-endpoint
Environment="KUBELET_EXTRA_ARGS=`--container-runtime-endpoint`=unix:///run/containerd/containerd.sock"

场景 B:二进制安装

修改 kubelet 启动脚本或 systemd service 文件,添加参数:

`--container-runtime-endpoint`=unix:///run/containerd/containerd.sock

生效配置:

Kubernetes 对接 Docker shim 废弃后,containerd 配置怎么迁移?
systemctl daemon-reload
systemctl restart kubelet

3. 镜像迁移与预热

风险警告:containerd 与 Docker 镜像存储隔离。直接停止 Docker 服务会导致原有本地镜像不可用,Pod 无法启动。必须在停止 Docker 前完成镜像迁移或确保镜像可从 registry 拉取。

方案一:从 Registry 拉取(推荐)

使用 crictl 预拉取业务所需镜像:

# 配置 crictl 使用 containerd socket
crictl config runtime-endpoint unix:///run/containerd/containerd.sock

# 拉取镜像
crictl pull <image-name>:<tag>

方案二:离线导入(无 Registry 场景)

若镜像仅存在于本地 Docker 中,需导出并导入 containerd:

# 1. 从 Docker 导出镜像
docker save -o image.tar <image-name>:<tag>

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

# 3. 验证镜像存在
ctr -n k8s.io images | grep <image-name>

4. 验证与回滚

验证步骤:

  1. 检查节点状态:
kubectl get nodes -o wide
# 确认 CONTAINER-RUNTIME 列显示 containerd://...
  1. 检查运行时信息:
crictl info | grep cgroup
# 确认 cgroupDriver 为 systemd
  1. 检查 Pod 状态:
kubectl get pods -A
# 确认业务 Pod 处于 Running 状态

故障回滚方案:

若迁移后节点异常且无法快速修复,可回滚至 Docker 运行时:

  1. 修改 Kubelet 参数,移除 `--container-runtime-endpoint` 或指向 Docker shim(若版本支持)。
  2. 启动 Docker 服务:systemctl start docker
  3. 重启 Kubelet:systemctl restart kubelet
  4. 注意:回滚后需重新调度 Pod 以确保镜像可用。

常见故障排查

  • 节点 NotReady:检查 journalctl -u kubelet 日志。若报错 cgroup 驱动不一致,请确认 containerd 配置中 SystemdCgroup = true 且 kubelet 启动参数包含 `--cgroup-driver`=systemd
  • Pod 镜像拉取失败:确认镜像已导入 containerd 命名空间(k8s.io)。使用 ctr -n k8s.io images 查看。
  • Sandbox 镜像问题:containerd 默认可能使用较新的 pause 镜像,若与集群预期不符,需在 config.toml 中指定 sandbox_image 并与 kubelet 配置一致。
  • 网络插件异常:部分 CNI 插件依赖特定运行时接口,迁移后建议重启 CNI Pod(如 Calico、Flannel)。