15-Pod 中断预算(PDB) Pod Disruption Budget概念引入你用过 Deployment#04管理多副本应用——即使某个节点挂了Pod 也会在其他节点重建。但集群升级时主动驱逐 Poddrain如果所有副本都在同一个节点上呢你的应用有 3 个副本某天管理员要升级节点❌ 没有 PDB 节点 drain → 3 个 Pod 同时被驱逐 → 应用全部下线 ✅ 有 PDBminAvailable: 2 节点 drain → 最多驱逐 1 个 → 至少 2 个始终在线 → 用户无感知Pod Disruption BudgetPDB就是给应用设最低在线人数——驱逐 Pod 时不能低于这个数。✅ 有 PDB: minAvailable2驱逐阻止阻止还有 2 个在跑drain 节点Pod 1Pod 2⏸️ 保持运行Pod 3⏸️ 保持运行服务正常❌ 无 PDB驱逐驱逐驱逐3 个全挂drain 节点Pod 1Pod 2Pod 3服务中断学完本篇你将能够创建 PodDisruptionBudget确保节点维护时应用保持最低可用副本数根据场景选择 minAvailable 或 maxUnavailable 参数在 drain 节点时观察 PDB 如何阻止过度驱逐原理讲解两种计算方式apiVersion:policy/v1kind:PodDisruptionBudgetmetadata:name:app-pdbspec:# 方式 1最少保持可用几个minAvailable:2# 方式 2二选一最多允许几个不可用# maxUnavailable: 1selector:matchLabels:app:my-app参数含义适合场景minAvailable驱逐时至少保持可用的 Pod 数你明确知道最少需要几个maxUnavailable驱逐时最多允许不可用的 Pod 数你不管总数只关心最多挂几个minAvailable: 2 和 maxUnavailable: 1 的区别3 副本为例3 副本时两者等价minAvailable2 ↔ maxUnavailable1 但副本数变化时 - minAvailable2副本数扩到 5 → 可同时驱逐 3 个 - maxUnavailable1副本数扩到 5 → 还是只能同时驱逐 1 个PDB 覆盖的场景PDB 保护的是自愿中断Voluntary Disruption不是意外故障场景自愿中断PDB 管不管kubectl drain✅ 是✅ 管集群自动缩容CA✅ 是✅ 管滚动更新Deployment✅ 是✅ 管Pod 崩溃OOMKilled❌ 否非自愿❌ 不管节点宕机❌ 否非自愿❌ 不管手动kubectl delete pod✅ 是⚠️ 不管delete 绕过 PDB⚠️重要kubectl delete pod是直接删除不会检查 PDB。只有 Eviction APIdrain 背后用的会检查 PDB。PDB 和 HPA 的配合集群缩容到底至少保证HPAminReplicas: 2maxReplicas: 10PDBminAvailable: 22 个 Pod2 个在线⚠️ drain 节点时HPA 只剩 2 个 PodPDB 也要 2 个→ 无法驱逐任何 Pod建议minAvailable要小于 HPA 的minReplicas否则缩容后 drain 会卡住。常见配置推荐副本数minAvailable说明1不设 PDB设了反而会阻止 drain永远达不到 minAvailable21保证至少 1 个在线32保证多数在线5replicas - 1或floor(replicas × 0.75)保证大多数在线动手实验配套实验位于docs/labs/beginner/pdb/步骤 1部署实验环境cddocs/labs/beginner/pdbbashsetup.sh步骤 2查看 PDB 状态kubectl get pdb# 输出NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE# pdb 2 N/A 1 10skubectl describe pdb app-pdb步骤 3测试 drain 被 PDB 阻止# 查看 Pod 分布在哪些节点kubectl get pods-owide# 预期3 个 Pod 分布在 2 个 worker 上其中一个 worker 有 2 个 Pod# 找到有 2 个 Pod 的 worker 节点对它执行 drain# 把下面的节点名换成你实际有 2 个 Pod 的节点kubectl drain有2个Pod的节点名--delete-emptydir-data --ignore-daemonsets--timeout5s# 预期输出关键行# evicting pod default/my-app-aaa ...# error when evicting pods/my-app-bbb ...: Cannot evict pod as it would violate the pods disruption budget.# ↑ 第 2 个 Pod 被 PDB 阻止# evicting pod default/my-app-aaa ...# error: unable to drain node ...: global timeout reached: 5s# ↑ drain 因 PDB 阻止而超时失败# 恢复节点kubectl uncordon节点名# 等待 Pod 恢复kubectlwait--forconditionready pod-lappmy-app--timeout60s关于 ALLOWED DISRUPTIONS这个值是实时计算的当前 Ready Pod 数 - minAvailable不是消耗型计数器。drain 期间它确实变为 0但 replacement Pod 在其他节点就绪后又回到 1。如果你在 drain 超时前快速执行kubectl get pdb能看到 0。步骤 4验证滚动更新也受 PDB 约束# 触发滚动更新kubectl rollout restart deployment/my-app# 观察 Pod 替换过程——同时不可用的 Pod 不会超过 maxUnavailablekubectl get pods-w步骤 5清理bashteardown.sh自检问题[基础]PDB 是保证 Pod 不挂掉吗它真正的保护范围是什么[理解]如果 Deployment 的 strategy 是maxSurge: 2, maxUnavailable: 1PDB 设了maxUnavailable: 0。RollingUpdate 会怎样[应用]生产环境一个 10 副本的关键服务要升级节点。你希望 drain 过程中至少 8 个 Pod 始终在线。PDB 怎么写副本数从 10 缩到 5非高峰期时会不会出问题查看答案PDB不保证Pod 不挂掉。它只保护自愿中断Voluntary Disruption——包括kubectl drain、集群自动缩容Cluster Autoscaler、滚动更新等受控驱逐操作。Pod 自身崩溃、节点宕机、OOMKilled 这些非自愿中断 PDB 完全不管。kubectl delete pod直接绕过 PDB。PDB 会阻止 RollingUpdate 进行。maxUnavailable: 0表示不允许任何 Pod 不可用。但 RollingUpdate 本身是通过终止旧 Pod、创建新 Pod 来实现的——这期间旧 Pod 是不可用的。如果 PDB 坚持 0 个不可用更新就卡住了。解决方案PDB 的maxUnavailable至少要 ≥ Deployment 策略中的maxUnavailable。spec:minAvailable:8selector:matchLabels:app:critical-service10 副本 → drain 最多驱逐 2 个 → ✅ 至少 8 个在线。如果缩到 5 副本 → 满打满算只能驱逐 0 个5 8→ ❌ drain 被永远阻止。解决方案minAvailable用百分比minAvailable: 75%副本数变小时自动调整5 的 75% 3.75 → 取整为 3允许驱逐 2 个。下一步应用高可用保证了。接下来深入理解 Pod 如何获得身份、如何认证→ 26. Pod 身份与认证机制 本文来自 K8s Guide —— 开源免费的 Kubernetes 中文学习指南️ 初学者轨道 面试轨道从零基础到拿 Offer 一站式覆盖 每篇文章配套 Kind 实验脚本本地一键运行 本文源码docs/beginner/20-gateway-api.md⭐ 如果对你有帮助欢迎 Star github.com/callmebg/k8s-guide