Pod 中断预算 PDB
本教程共 65 篇 · 第 51 篇 · 更新于 2026-08-14 · 约 15 分钟阅读
本节目标:搞懂什么是”自愿干扰”,PDB 怎样用一句话限制”同一时间能下线的 Pod 数”,以及它真正管得住什么、管不住什么。
你精心跑了 5 个副本,结果集群管理员一句 kubectl drain node-1 把节点上所有 Pod 全赶走了。如果这 5 个恰好在同一个节点,服务瞬间就剩 0 个可用——这就是”中断”的破坏力。
Kubernetes 用 PDB(Pod Disruption Budget,Pod 中断预算) 来给这种事设一道闸:告诉系统”我的应用,同一时间最多只能挂 N 个”。
51-1 自愿干扰 vs 非自愿干扰
先分两类,PDB 只管其中一类:
- 非自愿干扰(Involuntary):你控制不了的。比如节点物理机宕机、内核崩了、网络脑裂、节点资源耗尽被驱逐。这类 PDB 拦不住,但它们会计入预算。
- 自愿干扰(Voluntary):有人主动搞的。比如你删 Deployment、管理员 drain 节点升级、节点自动缩容腾挪。其中通过驱逐 API(Eviction API) 发起的,PDB 才管得着。
也就是说,PDB 是针对”计划内维护”的保护伞。它让升级、缩容这些操作变得温柔:干掉一个、等补上、再干下一个。
Warning直接
kubectl delete pod或kubectl delete deployment是绕过 PDB 的!PDB 只在走”驱逐 API”时才生效。kubectl drain走的就是驱逐 API,所以它会乖乖遵守 PDB。
51-2 PDB 是怎么算的
PDB 用标签选择器圈出”一组 Pod”(和你的 Deployment/StatefulSet 选 Pod 的 selector 一致),然后规定这组里”同时能有几个不可用”。
“期望总数”不是你写的,而是控制器去数:看这些 Pod 的 owner(Deployment 的 .spec.replicas),算出来当前应该有几个。然后 PDB 保证”可用数 ≥ 期望数 - 允许不可用数”。
举例:Deployment 副本数 5,PDB 说最多允许 1 个不可用。那么驱逐时,系统一次只允许干掉 1 个;等新的 Pod 起来变可用了,才放行进下一个。
51-3 定义 PDB
PDB 有两种写法,二选一:minAvailable 或 maxUnavailable。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
# 圈定受保护的一组 Pod,和 Deployment 的 selector 对应
selector:
matchLabels:
app: web
# 写法一:至少要有 4 个可用(即最多挂 1 个)
minAvailable: 4
# 写法二:最多允许 1 个不可用(和上面等价,二选一)
# maxUnavailable: 1
两者区别:
minAvailable: 4:绝对要保证”至少 4 个活着”。副本扩到 10 也还是至少 4。maxUnavailable: 1:按比例感更直观——“随便你扩到多少,同时最多挂 1 个”。
Tip多数场景用
maxUnavailable更顺手,因为它跟着副本数走。比如maxUnavailable: 1在 5 副本和 50 副本下都”只坏 1 个”,语义稳定。
数字也能写成百分比:maxUnavailable: 20% 表示 5 副本里最多挂 1 个(20%×5=1)。
51-4 它怎么真正生效
关键在 kubectl drain。当管理员执行:
kubectl drain node-1 --ignore-daemonsets
drain 会把节点标记为不可调度(cordon),然后逐个向 API 提交驱逐请求。每个驱逐请求都会被 PDB 审核:会不会让”不可用数”超预算?超了就拒绝,drain 工具会等一会儿重试,直到那个 Pod 的替身就绪。
这就是前面说的”干掉一个、等补上、再干下一个”。PDB 把”一波带走”变成了”排队慢慢来”。
用一个具体场景体会一下。假设 3 节点集群,应用 3 副本分散在 3 个节点,PDB 设 maxUnavailable: 1:
- 管理员 drain 节点 A。Pod-a 被优雅终止,Deployment 在别的节点补一个 Pod-d。
- 此时只有 2 个可用,已达预算底线(最多挂 1 个)。管理员再去 drain 节点 B 时,驱逐请求被 PDB 拒绝,drain 卡住等待。
- 等 Pod-d 就绪、变回 3 个可用,drain 才放行干掉 Pod-b,再等替身就绪。
- 如果集群资源不够调度新副本,drain 会一直阻塞——这时管理员得加节点才能继续。
drain 的速度被 PDB 主动限制了。这正是它的价值:宁可维护慢一点,也不能把服务可用性拖垮。
Note被驱逐的 Pod 会被优雅终止,参照它的
terminationGracePeriodSeconds慢慢收尾,不是硬杀。这也保护了正在进行中的请求。
51-5 几个必须知道的注意点
PDB 很好用,但也有边界,踩错会以为它”失灵”:
- 管不住删除操作:
kubectl delete pod/delete deployment直接绕过 PDB。只有走驱逐 API(如 drain)才受控。 - 管不住滚动更新:Deployment/StatefulSet 自己做滚动更新时不受 PDB 限制,因为它们自己会保证容量。但更新途中被删/不可用的 Pod 会计入预算——所以更新和 drain 同时发生时要留足余量。
- 非自愿干扰计入预算:节点突然宕机,那几个 Pod 算”不可用”,会占用你的预算额度。PDB 拦不下宕机,只是别让后续自愿操作雪上加霜。
- 不健康 Pod 的驱逐策略:PDB 有个
unhealthyPodEvictionPolicy字段。默认行为是”等 Pod 健康了才继续 drain”;若设为AlwaysAllow,则允许在 drain 时把行为异常的 Pod 也赶走,避免卡住维护。
Warning不要把
minAvailable设得等于副本数(比如 5 副本设minAvailable: 5)。那样意味着”一个都不许挂”,drain 会永远卡住,节点永远腾不空。至少要留出 1 个的可下线空间。
51-6 排查 PDB
查看当前 PDB 状态:
# 看预算与允许的不可用数
kubectl get pdb
# 看详情:当前允许中断几个、已中断几个
kubectl describe pdb web-pdb
describe 里有两个关键值:
Allowed disruptions:当前还能再干掉几个(受预算限制)。Current/Desired/Total:当前不可用、期望总数、总 Pod 数。
如果 drain 卡住不动,先看 Allowed disruptions 是不是 0——是的话说明预算用尽,得等新 Pod 就绪,或检查控制器为什么补不出新 Pod(资源不够?镜像拉不下来?)。
小结
PDB 是”计划内维护”的安全网:
- 它只管自愿干扰里走驱逐 API 的那部分,删 Pod 删 Deployment 它拦不住。
- 用
minAvailable或maxUnavailable圈定”最多挂几个”,selector 要和控制器对齐。 - 和
kubectl drain配合,把”一波带走”变成”排队慢慢来”。 - 别把阈值设到”一个都不许挂”,否则维护卡死。
下一章我们串起整本教程里散落的自愈能力:控制器调谐、kubelet、探针、重启策略,看 Kubernetes 是怎么”自己把自己修好”的。