Kubernetes集群升级1.32:节点drained后Pod驱逐失败的排查路径

问题描述与现象

Kubernetes集群从1.30升级到1.32时,执行kubectl drain驱逐节点Pod,部分Pod卡在Terminating状态无法完成驱逐。节点上的DaemonSet Pod、带Local PV的Pod、以及配置了podDisruptionBudget但当前不满足minAvailable的Pod,这三类是高频出问题的地方。升级过程中如果多个节点同时出现驱逐阻塞,整个滚动升级就会卡住。

Pod驱逐失败的根因分析

DNS解析超时导致PreStop Hook阻塞。这个原因最容易被忽略。很多应用在PreStop Hook中调用其他服务的健康检查接口做优雅关闭,如果CoreDNS的Pod也在被驱逐的节点上,解析请求会超时,PreStop Hook一直等到terminationGracePeriodSeconds耗尽才被强制杀死。排查方法:查看Pod events中是否有FailedScheduling或PreStop超时日志;同时检查CoreDNS Pod的分布,确保至少有一个CoreDNS副本不在被驱逐节点上。

PDB约束导致驱逐排队。PDB的minAvailablemaxUnavailable配置过于严格时,集群中可同时驱逐的Pod数量被限制。比如一个3副本的Deployment配了minAvailable: 3,则任何时刻都不允许驱逐。排查命令:

kubectl get pdb -A -o wide

检查每个PDB的Allowed disruptions字段,如果为0,说明当前不允许任何驱逐。临时方案是在升级前调低minAvailable,升级完成后再调回去。

Local PV的Pod没有可调度节点。使用Local PersistentVolume的Pod,数据只存在于特定节点,驱逐后无法在其他节点重新调度。这种Pod的kubectl drain默认会跳过(加了--ignore-daemonsets也不行),需要加--delete-emptydir-data参数强制删除,或者手动删除Pod让它在原节点重建。

1.32版本的驱逐行为变化

Kubernetes 1.32对Pod驱逐的默认行为做了一项变更:当节点进入Unschedulable状态后,新创建的Pod不会再被调度到该节点。但在滚动升级场景中,如果你用kubectl drain逐个驱逐节点,每个节点驱逐完成后需要确保其上Pod全部完成迁移再继续下一个。1.32的kubectl drain新增了--timeout参数的默认值(5分钟),超时后命令返回非零退出码,但驱逐仍在后台继续。如果你的自动化脚本依赖命令退出码判断升级进度,这个变更可能导致误判。

完整的升级前检查清单

1. PDB审计。逐个命名空间检查PDB配置,将minAvailable调整为副本数的50%以下。升级完成后再恢复。

2. CoreDNS高可用。确保CoreDNS副本数>=2,且分布在不同节点上。升级前用kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide确认。

3. Local PV节点标记。对挂载Local PV的节点做标记,升级时单独处理——先迁移数据卷或接受短暂停机。

4. 驱逐超时配置。升级脚本中为kubectl drain设置合理的--timeout--grace-period,建议--timeout=600s --grace-period=120

5. 节点并行度控制。不要同时对超过30%的节点执行drain,否则集群可用性无法保障。分批drain,每批完成并验证后再继续。

升级后的验证步骤

升级完成后不要只看节点版本号。需要验证:kubectl get nodes所有节点Ready、kubectl get pods -A无CrashLoopBackOff、CoreDNS解析正常、Ingress Controller健康检查通过。更关键的是跑一遍完整的端到端业务验证——新建Pod、跨节点通信、持久卷读写各跑一次,确认控制平面和数据平面都正常。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-ji-qun-sheng-ji-132-jie-dian-drained-hou-pod-qu/

(0)
小编小编
上一篇 15小时前
下一篇 15小时前

相关推荐