服务器与大带宽专家 · 持牌IDC/CDN/ISP服务商
简米科技官网JIANMI TECH
资讯 2026-08-30 更新于 2026-08-30 简米科技 4,259 字 10 分钟阅读

有状态应用与无状态应用的排水,如何实现平稳迁移?

导读有状态应用和无状态应用的排水,处理逻辑的差异是运维事故的主要起因:无状态应用排水等同于“删了重建”,有状态应用排水则必须处理数据一致性、卷绑定和恢复顺序,按状态机逻辑逐个停机,很多团队第一次给节点做维护时,都以为两条 kubectl drain 能搞定所有工作负载,结果有状态应用的主节点被驱逐后写入中断,或者……

有状态应用和无状态应用的排水,处理逻辑的差异是运维事故的主要起因:无状态应用排水等同于“删了重建”,有状态应用排水则必须处理数据一致性、卷绑定和恢复顺序,按状态机逻辑逐个停机。
很多团队第一次给节点做维护时,都以为两条 kubectl drain 能搞定所有工作负载,结果有状态应用的主节点被驱逐后写入中断,或者 PVC 卡在 Terminating 状态拖垮整个命名空间,下面从排水视角拆解两类应用的差异和操作路径。

有状态应用和无状态应用的区别:排水视角下的本质差异

从 Kubernetes 调度的角度看,这两类应用对待“节点消失”的态度完全不同,无状态应用觉得“换个地方重跑就行”,有状态应用则认为“我这辈子就在这台机器上,换了地方就失忆了”。

无状态应用:随时可以“拔掉”的副本

Deployment 管理的 Pod 由 ReplicaSet 维持副本数,节点排水时,kubelet 先收到驱逐请求,Pod 进入 Terminating,ReplicaSet 立刻在其它节点创建新 Pod,Service 把流量切过去,整个过程对客户端几乎没有感知,唯一需要注意的是短时间内副本数波动,比如原本 3 个副本同时被驱逐,只剩下 1 个在支撑流量。

有状态应用:“身份证”和“记忆”都不能丢

StatefulSet 的 Pod 有稳定的网络标识和存储标识,Pod 名、PVC 名都是固定的,排水时控制器不会立即补一个新 Pod,而是等旧 Pod 完全终止、卷解绑后,再用同一个名字在新节点重建,这带来的结果是:如果卷是 RWO(单节点读写)模式,旧节点不释放卷,新 Pod 永远起不来

更复杂的是主从架构,MySQL 主从、Redis 哨兵、Kafka 这类应用,排水前必须确认角色切换是否完成,主节点所在的 Pod 被驱逐,如果健康检查配置不当,可能触发不了自动 failover,整个集群进入只读或不可写状态。

排水出错的高发点

行业共识认为,排水事故多数发生在“三类误判”:把有状态应用当成无状态应用处理、忽略 PDB 对自愿中断的限制、没检查存储是否支持跨节点重新挂载,这三类误判导致的现象分别是 Pod 反复重启、驱逐请求永久阻塞、卷卡在 Attached 状态。

kubernetes节点排水注意事项:先检查再动手

有状态应用与无状态应用的排水,如何实现平稳迁移?

节点排水是自愿中断,受 PodDisruptionBudget 约束,很多运维人员对 PDB 的理解停留在“保护应用可用性”,却没意识到它也会让排水卡死,动手之前,按下面清单逐项确认。

检查PodDisruptionBudget是否在“拦路”

执行下面的命令,看看目标节点上的 Pod 分布在哪些 PDB 下:

kubectl get pdb -A
kubectl describe pdb <pdb-name> -n <namespace>

重点关注 ALLOWED DISRUPTIONS 这一列,如果是 0,说明当前不满足 PDB 的最小可用副本要求,排水会一直等待,典型场景是单副本的 StatefulSet 搭配 minAvailable: 1:节点上就一个副本,驱逐它会导致可用副本数为 0,控制器拒绝释放。

检查PVC和存储的跨节点能力

无状态应用重建后可以在任何节点运行,有状态应用则要看 PVC 的 AccessModes,RWO 卷只允许单节点挂载,节点排水后控制器需要先 detach、再 attach 到新节点,中间有延迟,如果存储插件不支持在线扩容或跨可用区挂载,Pod 重建后只能卡在 ContainerCreating。

检查应用是否容忍同时下线多个副本

排水整个节点时,节点上所有 Pod 会同时进入 Terminating,对于多副本无状态应用,PDB 能限制“最多不可用数量”,但对有状态应用来说,同时停掉两个副本可能导致 quorum 丢失,比如三节点的 ZooKeeper,如果同一时间驱逐两个节点,选举机制被破坏,剩余节点无法形成多数派。

排水动作实操:两类应用的驱逐过程差异

确认完前置条件后,执行排水命令的基础形式是:

kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

--ignore-daemonsets 跳过 DaemonSet 管理的 Pod,因为它们在每个节点必须有副本;--delete-emptydir-data 允许删除 emptyDir 临时数据,但这只是起点,两类应用在命令执行后的表现差异很大。

无状态应用的排水:驱逐快,但要防“雪崩”

Deployment 的 Pod 被驱逐后,ReplicaSet 会在其它节点立刻重建副本,如果集群资源充足,整个过程是分钟级的,实操中建议对核心服务设置 maxUnavailable: 1,让控制器一个一个替换,避免所有副本同时重建造成调度器压力,排水命令执行时观察:

有状态应用与无状态应用的排水,如何实现平稳迁移?

kubectl get pods -o wide | grep <node-name>

等所有 Deployment 的 Pod 都处于 Running 且 Ready 状态,再处理下一个节点。

有状态应用的排水:逐个来,盯状态

StatefulSet 的 Pod 驱逐后,控制器会用相同的名字重建,但前提是旧 Pod 彻底终止、PVC 完成解绑,这里有两个常见的实际情况:

  • 单一写者型应用(如 MySQL 主节点):排水前手动触发主从切换,确认新主节点同步完成,再执行 drain。
  • 分布式一致性应用(如 etcd、ZooKeeper):不需要手动切换,但要保证排水节点上的实例不是最后几个可用副本。

StatefulSet节点维护停机的典型操作路径

先把节点标记为不可调度,防止新 Pod 调度上去:

kubectl cordon <node-name>

接着逐个删除或驱逐有状态 Pod,观察每个 Pod 的状态变化:

kubectl delete pod <pod-name> -n <namespace> --wait=false

等 PVC 变为 Released 或 Available 后,检查存储插件是否完成了 detach,然后执行排水,跳过已经处理的 Pod:

kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

节点维护结束后,先 uncordon 再恢复状态,这套流程比直接 drain 更可控,尤其在处理主从型应用时,能避开自动驱逐带来的角色切换混乱。

pod驱逐失败怎么处理:排水卡住的常见原因与解决路径

排水命令卡住是高频问题,表现是节点状态一直是 SchedulingDisabled,Pod 停在 Terminating,终端上不报错也不返回,原因是某个 Pod 的驱逐被阻塞,drain 默认会等待所有 Pod 成功驱逐。

卡在PDB上的处理

先看卡住的 Pod 关联的 PDB 是否允许驱逐:

kubectl get pdb -A

ALLOWED DISRUPTIONS 为 0,有两个选择:调整 PDB 的 minAvailable,或者临时删除 PDB,调整后 drain 继续执行,这里要注意,强制驱逐(--force)是最后手段,用之前必须确认应用支持非正常终止,否则可能产生数据不一致。

卡在RWO卷上的处理

RWO 卷在节点 NotReady 状态下,detach 操作有超时机制,超时后卷仍处于 Attached,Pod 删除不了,可以手动清理 VolumeAttachment:

kubectl get volumeattachment | grep <node-name>
kubectl delete volumeattachment <attachment-name>

删除后 PVC 会从 Released 变为 Available,新节点可以重新绑定,这属于有风险操作,只建议在确定旧节点不会再恢复时使用。

本地卷和系统组件的影响

使用 local volume 的 Pod 有硬性节点亲和性,排水后 Pod 即使重建也只能调度到原节点,如果原节点已经下线,Pod 会一直 Pending,这种情况必须提前把数据迁移走,或者在存储层复制到其它节点。DNS、网络插件等系统组件不能直接驱逐,drain 时需要加 --ignore-daemonsets 跳过,否则整个节点的网络会先于其它 Pod 断开,导致驱逐信号无法送达。

有状态应用与无状态应用排水相关问题

问:有状态应用排水时,StatefulSet 的 Pod 被驱逐后数据会丢吗?

不会自动丢,但重建前要确认 PVC 已解绑,StatefulSet 的 Pod 删掉后,PVC 默认保留,数据在存储层完整存在,真正丢数据的原因是误删 PVC,或者节点故障导致 RWO 卷无法 detach,新 Pod 等待卷期间被反复强制删除,只要 PVC 处于 Available 状态,数据就是安全的。

问:无状态应用排水前设置 PDB 还有意义吗?

有意义,PDB 主要就是为无状态应用设计的,没有 PDB 时,节点排水会同时终止多个副本,如果其它节点资源不足,新副本创建速度跟不上,服务会退化,设置 minAvailable: 2maxUnavailable: 1,可以控制驱逐节奏,保证业务在维护期间保持完整能力。

问:排水卡住后直接强制驱逐,有没有安全做法?

有,但必须分级,PDB 不满足,先调整或删除 PDB,让正常驱逐流程走完,如果卷无法解绑,先手动清 VolumeAttachment,再重试,只有这两步都无效,才考虑 kubectl drain --force --grace-period=0,强制驱逐会跳过终止钩子和优雅退出,对无状态应用影响较小,对有状态应用可能导致数据分片未同步完,所以仅限维护窗口内使用,且要提前在其它节点备份好数据。

分享本文
本文为 简米科技官网 原创,已由运维技术专家审核。转载请注明来源:原文链接
售前咨询 服务热线 售后 邮箱