← 中文资源

简体中文版本

排空节点而不丢弃请求

先 cordon 再带明确参数 drain,遵守 PodDisruptionBudget,并在终止节点前确认工作负载已在其他节点恢复。

阅读英文原文

概述

kubectl drain 不会迁移 Pod,它先 cordon 节点,再通过 Eviction API 逐个驱逐 Pod。Eviction API 会遵守 PodDisruptionBudget,这正是关键所在:要求两个可用副本的预算会拒绝任何只剩一个副本的驱逐。所有 Pod 清空后,节点才可以重启或销毁。急于求成时常用的 --force 与 --delete-emptydir-data 会绕过部分保护,应有意识地使用而不是形成习惯。

步骤

  1. 先 cordon,防止节点在排空过程中又被调度新 Pod:
kubectl cordon ip-10-0-3-17
  1. 列出将被驱逐的 Pod,识别需要特殊处理的有状态负载:
kubectl get pods -A --field-selector spec.nodeName=ip-10-0-3-17 -o wide
  1. 带超时执行 drain,并明确处理 DaemonSet 与 emptyDir:
kubectl drain ip-10-0-3-17 \
  --ignore-daemonsets --delete-emptydir-data --timeout=300s
  1. 确认只剩 DaemonSet,且被驱逐的工作负载在其他节点就绪:
kubectl get pods -A -o wide --field-selector spec.nodeName=ip-10-0-3-17
kubectl get pods -A -o wide | grep payments

验证

drain 成功返回 0 后,节点上应只剩 DaemonSet Pod;被驱逐的 Pod 应在其他节点处于 Running 与 Ready。若命令因 PDB 违规而挂起,日志会指出具体的工作负载。若替代 Pod 一直 Pending,说明集群容量不足,问题只是被转移而不是解决。维护结束后执行 kubectl uncordon 恢复调度。

注意事项

  • drain 本身不迁移 Pod,放置由调度器决定,容量不足时会留下 Pending。
  • emptyDir 数据会随驱逐删除,需要提前备份或改用持久卷。
  • DaemonSet Pod 会保留到节点被删除,这是预期行为。
  • 有状态负载应逐个处理,避免同时失去多个副本。
  • 维护记录中应写明排空原因,便于后续排查。