You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

K8S集群从CRI-O切换容器运行时至Docker 主节点drain失败处理

故障原因

cordon、drain操作失败通常是三类问题导致:

  • 执行命令的账号未加载管理员级别的kubeconfig,权限不足
  • drain默认会拒绝驱逐DaemonSet管控Pod、挂载emptyDir的Pod、无控制器绑定的裸Pod,缺少对应跳过参数就会直接报错退出
  • 双节点集群没有控制面冗余,如果你先操作master节点,驱逐过程中控制面组件(etcd、kube-apiserver等)被关停会直接导致集群API断连,命令超时失败
前置修复(解决cordon/drain报错)
  1. 所有kubectl操作优先在master节点用root账号执行,非root账号执行前先加载管理员配置:
    export KUBECONFIG=/etc/kubernetes/admin.conf
  2. drain节点时统一带上以下参数,跳过无法驱逐的系统级Pod:
    kubectl drain <节点名> --ignore-daemonsets --delete-emptydir-data --force
    参数说明:
  • --ignore-daemonsets:跳过DaemonSet管控的Pod,这类Pod和节点生命周期绑定,节点恢复后会自动拉起,不影响切换
  • --delete-emptydir-data:允许删除挂载emptyDir临时存储的Pod,系统核心组件均使用该类存储,确认无业务在emptyDir存持久化数据即可使用
  • --force:强制驱逐无ReplicaSet/Deployment/StatefulSet等控制器绑定的裸Pod
双节点集群CRI从CRI-O切换Docker的标准操作流程

核心原则:双节点无冗余,绝对不能同时操作两个节点,必须先切换worker节点,确认业务、集群状态全正常后,再切换master节点

worker节点切换步骤

  1. 标记worker节点不可调度,驱逐节点上的业务负载:
kubectl cordon <worker节点名称>
# 确认节点状态变为SchedulingDisabled后执行驱逐
kubectl drain <worker节点名称> --ignore-daemonsets --delete-emptydir-data --force

驱逐完成后,原本跑在worker上的业务Pod会暂时处于Pending状态,属于正常现象。
2. 登录worker节点,停kubelet服务、禁用CRI-O:

systemctl stop kubelet
systemctl disable crio --now
  1. 安装Docker CE与cri-dockerd组件(K8s 1.24及以上版本已移除内置dockershim,必须通过cri-dockerd对接Docker),安装完成后启动docker、cri-dockerd服务并设置开机自启。
  2. 修改kubelet的CRI端点配置,配置文件默认路径为/var/lib/kubelet/kubeadm-flags.env,将其中--container-runtime-endpoint参数的值从CRI-O默认的unix:///var/run/crio/crio.sock修改为cri-dockerd的socket地址unix:///var/run/cri-dockerd.sock。
  3. 重载系统配置,启动kubelet:
systemctl daemon-reload
systemctl start kubelet
  1. 等待1-2分钟,执行kubectl get nodes确认worker节点状态变为Ready,可在worker节点执行crictl info | grep runtimeType校验,返回值为docker即表示CRI对接正常。
  2. 解除worker节点的调度封锁:
    kubectl uncordon <worker节点名称>
    观察3-5分钟,等所有Pending状态的业务Pod全部在worker节点拉起、运行正常后,再开始master节点的切换操作。

master节点切换步骤

  1. 标记master节点不可调度,驱逐节点负载:
kubectl cordon <master节点名称>
kubectl drain <master节点名称> --ignore-daemonsets --delete-emptydir-data --force

驱逐master过程中kube-apiserver会出现10-30秒的短暂不可用,属于正常现象,不要中途中断命令。

  1. 登录master节点,停kubelet服务、禁用CRI-O:
systemctl stop kubelet
systemctl disable crio --now
  1. 和worker节点操作一致:安装Docker CE、cri-dockerd,启动服务并设置开机自启。
  2. 修改master节点/var/lib/kubelet/kubeadm-flags.env中的--container-runtime-endpoint参数为cri-dockerd的socket地址。
  3. 重载系统配置,启动kubelet:
systemctl daemon-reload
systemctl start kubelet
  1. 等待2分钟左右,执行kubectl get nodes确认两个节点均为Ready状态,执行kubectl get pods -A确认所有系统组件、业务Pod均为Running状态。
  2. 解除master节点的调度封锁:
    kubectl uncordon <master节点名称>
回滚预案

如果切换过程中节点持续NotReady超过5分钟,立刻将kubelet配置中的--container-runtime-endpoint改回CRI-O的socket地址,启动crio服务和kubelet,先恢复集群状态再排查问题。临时测试完成后需要切回CRI-O时,按照上述先worker后master的顺序,反向修改CRI端点、停Docker服务启动CRI-O即可。

内容的提问来源于stack exchange,提问作者johnny k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:51:27