Kubernetes 集群节点迁移如何排水驱逐 Pod 避免服务中断?

文章导读
Kubernetes 集群节点迁移时,推荐先使用kubectl cordon标记节点不可调度,再执行kubectl drain安全驱逐 Pod,配合 PodDisruptionBudget (PDB) 限制同时中断的副本数量。该方案适用于有状态和无状态服务维护,风险边界在于 PDB 配置过严可能导致排水阻塞,本地存储数据需提前备份。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

Kubernetes 集群节点迁移时,推荐先使用kubectl cordon标记节点不可调度,再执行kubectl drain安全驱逐 Pod,配合 PodDisruptionBudget (PDB) 限制同时中断的副本数量。该方案适用于有状态和无状态服务维护,风险边界在于 PDB 配置过严可能导致排水阻塞,本地存储数据需提前备份。

先说结论:节点迁移必须遵循“隔离 - 排水 - 恢复”流程,强制驱逐需确认业务容忍度。

  • 适合:集群版本升级、硬件维护、节点下线场景
  • 先看:PodDisruptionBudget 配置及 StatefulSet 存储类型
  • 建议:业务低峰期操作并实时监控 Pod 迁移状态

命令速用版

以下命令用于标准节点维护流程,需替换<node-name>为实际节点名称:

# 1. 标记节点不可调度
kubectl cordon <node-name>

# 2. 驱逐 Pod(忽略 DaemonSet 并删除临时数据)
kubectl drain <node-name> `--ignore-daemonsets` `--delete-emptydir-data` `--force`

# 3. 维护完成后恢复调度
kubectl uncordon <node-name>

为什么会这样

节点排水本质是触发 Kubernetes 的自愿性中断机制,PDB 可拦截超出预算的驱逐。

Kubernetes 将中断分为自愿性(如维护、升级)和非自愿性(如节点故障)。kubectl drain属于自愿性中断,会尊重 PodDisruptionBudget 设置。若 PDB 规定最小可用副本数,当驱逐导致可用数低于阈值时,API Server 会阻塞驱逐请求,从而避免服务中断。此外,DaemonSet 管理的 Pod 通常由节点守护进程控制,需显式忽略以防死循环。

分步处理

按顺序执行以下步骤,确保每步验证通过后再继续:

1. 预检准备
检查节点状态及 PDB 配置,确认无异常事件:

kubectl describe node <node-name> | grep -A 10 "Conditions"
kubectl get pdb `--all-namespaces`

2. 节点隔离
阻止新 Pod 调度到该节点,现有 Pod 继续运行:

Kubernetes 集群节点迁移如何排水驱逐 Pod 避免服务中断?
kubectl cordon <node-name>

验证状态应显示SchedulingDisabled

3. 安全排水
根据业务类型选择参数,有状态服务需确认存储卷可迁移:

# 无状态服务
kubectl drain <node-name> `--ignore-daemonsets`

# 含本地临时数据服务
kubectl drain <node-name> `--ignore-daemonsets` `--delete-emptydir-data` `--force` `--timeout`=300s

4. 维护与恢复
完成硬件或系统操作后,恢复节点调度能力:

kubectl uncordon <node-name>

怎么验证是否生效

通过节点状态和 Pod 分布确认迁移结果:

  • 检查节点状态:kubectl get nodes应显示Ready且无SchedulingDisabled(恢复后)。
  • 检查 Pod 分布:kubectl get pods -o wide `--field-selector` spec.nodeName=<node-name>应无业务 Pod(排水后)。
  • 检查 PDB 状态:kubectl get pdbALLOWED DISRUPTIONS列应显示允许的中断数。

常见坑

  • PDB 阻塞排水:若kubectl drain卡住,检查是否违反 PDB 约束,需等待其他 Pod 就绪或临时调整 PDB。
  • DaemonSet 死循环:未加`--ignore-daemonsets`参数时,网络插件 Pod 被删除后会立即重建,导致排水无法完成。
  • 本地数据丢失:使用emptyDir或本地 PV 的 Pod 排水后会丢失数据,需提前备份或确认数据可重建。
  • StatefulSet 存储:有状态服务需确认存储卷能自动迁移至新节点,否则需手动处理 PVC 绑定。

常见问题

drain 命令一直阻塞怎么办?

通常是因为 PodDisruptionBudget 限制或 Pod 无法终止。检查kubectl get pdb确认是否达到中断上限,或查看卡住 Pod 的终止日志。

DaemonSet 的 Pod 需要手动删除吗?

不需要。使用`--ignore-daemonsets`参数后,drain 命令会跳过 DaemonSet 管理的 Pod,它们会随节点恢复自动运行。

StatefulSet 可以直接排水吗?

可以,但需谨慎。需确认后端存储支持多节点挂载或已配置数据迁移策略,否则可能导致数据不可用。

参考来源

  • 最硬核 K8s 节点维护指南:零宕机排水策略实战
  • 如何从 Kubernetes 集群中安全移除节点
  • pod 为什么会被驱逐及如何避免 pod 被驱逐导致的服务中断
  • PodDisruptionBudget 配置:避免集群维护时的业务中断策略
  • kubernetes 节点排水维护 cordon, drain, uncordon