Kubernetes节点维护中cordon和drain怎么配合使用?

来源:建站教程作者:关中王头衔:草根站长
导读:本期聚焦于关中王创作的《Kubernetes节点维护中cordon和drain怎么配合使用?》,敬请观看详情。节点要升级内核或更换故障磁盘,是不是直接执行 kubectl delete node 就可以?这样做很可能让业务 Pod 被粗暴终止甚至引发数据不一致。Kubernetes 提供了两个更安全的节点维护原语:cordon 和 drain。cordon 将节点标记为不可调度,阻止新 Pod 被分配上来;drain 则通过驱逐 API 把现有 Pod 优雅迁移到其他节点,同时尊重 PodDisruptionBudget 与宽限期。本文会先厘清两者的执行顺序与底层字段差异,再逐一解释 --ignore-daemonsets、--delete-emptydir-data、--force 等关键参数的行为边界,最后给出一套从标记、驱逐到恢复调度的完整操作流程以及常见卡住场景的排查思路。掌握这些细节可以避免节点维护时误伤有状态服务和本地存储工作负载。

对 Kubernetes 集群进行节点维护时,最忌讳的就是直接关机或删除节点对象。节点上的 Pod 不会自动获得迁移机会,kubelet 停止响应后,控制平面通常要等待较长时间才会把这些 Pod 标记为未知,最终触发重建,业务会出现明显中断。为了安全地让节点退出调度并清空工作负载,Kubernetes 原生提供了 cordon 与 drain 两个操作。它们经常配合使用,但各自职责不同,参数选择也会直接影响维护期间的服务可用性。

Kubernetes节点维护中cordon和drain怎么配合使用?

cordon 与 drain 的核心区别

kubectl cordon 的作用只是把节点的 spec.unschedulable 字段设置为 true。一旦被标记,调度器在为新 Pod 选择节点时会跳过该节点,但已经运行在上面的 Pod 完全不受影响。可以通过 kubectl get node 查看节点状态,被 cordon 的节点会显示 SchedulingDisabled。这个操作非常轻量,适合在观察期先阻止新负载进入。

kubectl drain 则更进一步,它会先自动执行 cordon,然后逐个驱逐节点上现有的 Pod。驱逐并不是直接删除 Pod,而是通过 Eviction API 向 API Server 发起驱逐请求。对于由 Deployment、StatefulSet、ReplicaSet 等控制器管理的 Pod,控制器会在其他可用节点上重新创建副本;对于裸 Pod,驱逐后不会自动重建。理解这个区别能帮助判断哪些工作负载在 drain 后可能消失。

简单来说,cordon 是只进不出的状态切换,drain 是清空节点的完整流程。生产环境通常先手动 cordon,等待观察期确认没有异常后,再执行 drain。如果直接执行 drain,它会隐含 cordon 步骤,但最好显式操作,避免遗漏。

drain 的关键参数与驱逐行为

执行 kubectl drain 时,有几个参数直接决定操作是否顺畅。--ignore-daemonsets 是最常用的一个。DaemonSet 管理的 Pod 会在每个匹配节点上运行,即使驱逐它们,控制器也会立刻在同节点重新拉起,因此 drain 默认会因为无法驱逐 DaemonSet Pod 而失败。加上该参数后,drain 会跳过 DaemonSet Pod,允许节点继续清空其他工作负载。

另一个容易误用的参数是 --delete-emptydir-data。当 Pod 使用了 emptyDir 卷时,驱逐会导致临时数据被删除,drain 默认会拒绝驱逐这类 Pod,以提示用户确认。只有在明确知道这些数据可以丢弃时,才加上该参数。类似地,--force 并不会粗暴地强制删除 Pod,它只是在 Pod 不受 ReplicationController、ReplicaSet、Job、DaemonSet 或 StatefulSet 管理时,允许继续删除裸 Pod。真正的宽限期由 --grace-period 控制,默认 -1 表示使用 Pod 自身 terminationGracePeriodSeconds。

下面这条命令是一个比较稳妥的驱逐示例:

kubectl drain node-1 \
  --ignore-daemonsets \
  --delete-emptydir-data \
  --grace-period=120 \
  --timeout=5m

其中 --timeout 表示如果驱逐在指定时间内未完成,命令返回错误,但已经发出的驱逐请求仍然有效。此时需要通过 kubectl get pods -o wide 反复确认节点上是否还有残留 Pod。

节点维护完整流程与恢复调度

一次标准的节点维护应遵循以下步骤。先确认节点与 Pod 状态:

kubectl get nodes
kubectl get pods -o wide | grep node-1

然后执行 cordon,让节点进入不可调度状态:

kubectl cordon node-1

观察一段时间,确认没有新 Pod 被调度到该节点,且现有 Pod 运行稳定后,执行 drain:

kubectl drain node-1 \
  --ignore-daemonsets \
  --delete-emptydir-data \
  --grace-period=120 \
  --timeout=5m

维护完成后,通过 kubectl uncordon node-1 恢复调度。此时节点会重新出现在调度器的候选列表中,但之前被驱逐的 Pod 不一定会自动调度回来,新 Pod 会按资源情况分布。对于有状态服务,建议等待控制器重新平衡或手动触发滚动更新。

实际操作中还要关注 PodDisruptionBudget。如果一个 Deployment 配置了 maxUnavailable: 1,而节点上有多个副本,drain 会尊重这一限制,确保同一时间被驱逐的副本数不超过允许值。如果 PDB 配置过于严格,drain 可能会长时间卡住。查看 PDB 的命令是 kubectl get pdb,必要时临时调整或先扩容副本。

常见卡住场景与排查方法

drain 卡住是最常见的运维问题。第一个原因是 DaemonSet Pod 没有被忽略。如果没有加 --ignore-daemonsets,drain 会报类似 DaemonSet-managed pods 的错误并停止。修复方法就是显式加上该参数,或者先评估是否可以在维护期间暂停 DaemonSet。

第二个原因是 Pod 使用本地存储或 emptyDir,drain 会提示需要 --delete-emptydir-data。如果直接加参数,会清空这些临时数据;对于使用 hostPath 或 local PV 的有状态服务,drain 无法迁移数据,需要先手动备份或调整工作负载存储类型。

第三个原因是 PDB 阻止驱逐。通过 kubectl get pdb -A 查看状态,如果 ALLOWED DISRUPTIONS 为 0,说明当前没有可中断预算。此时可以临时调高 minAvailablemaxUnavailable,或者扩容副本后再 drain。排查时可以使用 kubectl describe pdb 查看事件。

最后还可以使用 kubectl drain --dry-run=server 预演,它会模拟驱逐过程但不会真正删除 Pod。这在生产变更前非常有用,能提前暴露参数遗漏和 PDB 限制。

Kubernetescordondrain修改时间:2026-08-20 21:53:30

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。