PDB 到底保护了什么?drain 的时候它是怎么起作用的?为什么 kubectl delete pod 拦不住?这篇用 Eviction API 直接发请求,看 allowed 数怎么算、429 长什么样、drain 怎么重试,以及不健康的 Pod 在两种策略下的不同命运。
minAvailable: 2 → currentHealthy=5 desiredHealthy=2 disruptionsAllowed=3 expectedPods=5 minAvailable: "50%" → currentHealthy=5 desiredHealthy=3 disruptionsAllowed=2 expectedPods=5 maxUnavailable: 1 → currentHealthy=5 desiredHealthy=4 disruptionsAllowed=1 expectedPods=5 maxUnavailable: "50%" → currentHealthy=5 desiredHealthy=2 disruptionsAllowed=3 expectedPods=5 minAvailable: "100%" → currentHealthy=5 desiredHealthy=5 disruptionsAllowed=0 expectedPods=5
PDB 的 status 里 disruptionsAllowed = currentHealthy − desiredHealthy。同样 5 个健康 Pod:minAvailable: 2 允许 3 个;minAvailable: "50%" 的 desiredHealthy 是 3(2.5 向上取整),允许 2 个;maxUnavailable: 1 允许 1 个;maxUnavailable: "50%" 允许 3 个;minAvailable: "100%" 一个都不让动。写成 100% 的 PDB 会让节点 drain 永远卡住。
3 个 Pod、minAvailable: 2:currentHealthy=3 desiredHealthy=2 disruptionsAllowed=1 expectedPods=3
驱逐第 1 个 Pod:退出码 0;{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Success","code":201}
紧接着驱逐第 2 个 Pod:退出码 1;Error from server (TooManyRequests): Cannot evict pod as it would violate the pod's disruption budget.
此时 PDB:currentHealthy=2 desiredHealthy=2 disruptionsAllowed=0 expectedPods=3
从第 1 次驱逐算起,Deployment 补出新 Pod 并就绪用了 6.0 秒(就绪探针 initialDelaySeconds=5);PDB:currentHealthy=3 desiredHealthy=2 disruptionsAllowed=1 expectedPods=3
现在再驱逐一个:退出码 0;{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Success","code":201}3 个 Pod、minAvailable: 2(允许 1 个)。直接调 Eviction API:第 1 次 201;紧接着第 2 次 TooManyRequests: Cannot evict pod as it would violate the pod's disruption budget.。这时 currentHealthy=2、disruptionsAllowed=0,要等 Deployment 补出的新 Pod 真的 Ready(这里就绪探针延迟 5 秒,总共 6.0 秒)预算才恢复,再驱逐才会成功。429 是让调用方重试,不是失败。
3 个 web Pod 的分布:worker:1, worker2:2;要清空的节点:worker2(2 个 Pod)
kubectl drain worker2(退出码 0,用了 6 秒)输出里和驱逐有关的行:
node/kx-main-worker2 cordoned
evicting pod k37/web-c4d4744bd-m4wpg
evicting pod k37/web-c4d4744bd-lhvnt
pod/web-c4d4744bd-m4wpg evicted
evicting pod k37/web-c4d4744bd-lhvnt
pod/web-c4d4744bd-lhvnt evicted
node/kx-main-worker2 drained
error when evicting pods/"web-c4d4744bd-lhvnt" -n "k37" (will retry after 5s): Cannot evict pod as it would violate the pod's disruption budget.
对比:kubectl delete pod 一次删掉 2 个(不经过 Eviction API,PDB 拦不住):0.5 秒后 ready 的 Pod 有 1 个;PDB:currentHealthy=1 desiredHealthy=2 disruptionsAllowed=0 expectedPods=3kubectl drain 对节点上的 2 个 Pod 同时发起驱逐:第 1 个成功,第 2 个被 PDB 拦住,输出 error when evicting … (will retry after 5s),5 秒后重试成功,一共 6 秒。而 kubectl delete pod 一次删 2 个不是驱逐,PDB 拦不住:0.5 秒后只剩 1 个 Ready,PDB 变成 currentHealthy=1 < desiredHealthy=2。PDB 只约束自愿中断(驱逐),节点宕机、直接删除这类它管不了。
unhealthyPodEvictionPolicy=IfHealthyBudget:3 个 Pod 里 1 个就绪探针失败、minAvailable: 3:currentHealthy=2 desiredHealthy=3 disruptionsAllowed=0 expectedPods=3
驱逐那个不健康的 Pod:退出码 1;Error from server (TooManyRequests): Cannot evict pod as it would violate the pod's disruption budget.
unhealthyPodEvictionPolicy=AlwaysAllow:3 个 Pod 里 1 个就绪探针失败、minAvailable: 3:currentHealthy=2 desiredHealthy=3 disruptionsAllowed=0 expectedPods=3
驱逐那个不健康的 Pod:退出码 0;code=201 message=None3 个 Pod 里 1 个就绪探针失败、minAvailable: 3:currentHealthy=2,disruptionsAllowed=0。默认的 unhealthyPodEvictionPolicy: IfHealthyBudget 下,连这个不健康的 Pod 也驱逐不了(429),drain 会一直卡;改成 AlwaysAllow 之后不健康的 Pod 随时可以驱逐(201),应用本来就坏了,没必要再为它保留名额。