A PodDisruptionBudget limits eviction-based disruption for a selected group of Pods. It can help preserve serving capacity or quorum during maintenance, but cannot guarantee either. Its protection depends on the caller using the Eviction API, the selector identifying the intended members, and Ready conditions meaning something useful for the application.

Choose the permitted disruption from the application’s failure model. A three-member majority system normally needs two functioning members, but Pod readiness does not itself prove membership, synchronized state, or connectivity between those members. The PDB complements application health and maintenance procedures; it does not replace them.

Normal drain requests use the Eviction API and may wait on PDB protection; direct deletion, rollout deletions and involuntary failures are not prevented. Under settled conditions three qualifying healthy Pods and minAvailable two allow one healthy eviction. CurrentHealthy excludes unready, deleting and outstanding-disruption members. Integer minimums use selected Pod objects; percentage minimums and maxUnavailable use controller scale in Kubernetes 1.34.0. IfHealthyBudget and AlwaysAllow differ for Running-unready Pods; healthy evictions remain budget-gated. Selector scope and rounded percentages need inspection, and no live eviction or application-quorum proof is provided.
A PDB constrains a specific eviction path. Verify the selected members, readiness, policy and application health before treating an allowance as safe maintenance capacity.

The boundary is eviction

Node crashes, network partitions, and node-pressure eviction are not prevented by PDBs. Unavailable members can nevertheless reduce the remaining disruption allowance. Directly deleting a Pod or workload bypasses PDB enforcement, as do a workload controller’s normal rolling-update deletions. Voluntary does not automatically mean budget-protected.

A normal drain uses eviction requests and retries when protection blocks them. A caller that chooses direct deletion bypasses that protection. Review the maintenance tool’s behavior before relying on a budget. Deployment and StatefulSet rolling availability is controlled by their own update strategies, so coordinate rollouts and node maintenance instead of assuming one PDB serializes everything.

Read the arithmetic with its denominator

Set either minAvailable or maxUnavailable. For three healthy replicas, an integer minAvailable of two allows one healthy eviction under ordinary settled conditions. maxUnavailable of one expresses an allowance relative to intended scale. CurrentHealthy counts qualifying Ready Pods, excluding members being deleted or already recorded for disruption; Running alone is insufficient.

ExpectedPods is not always the controller’s desired replicas. In the reviewed Kubernetes 1.34.0 implementation, integer minAvailable uses the number of selected Pod objects. Percentage minAvailable and maxUnavailable derive expected scale from owning controllers. Therefore a mismatch with StatefulSet replicas can reflect policy type or reconciliation state, not only a selector typo.

The status allowance is broadly currentHealthy minus desiredHealthy, floored at zero, with additional safety checks and outstanding-eviction accounting. Inspect observedGeneration and conditions when interpreting it. Zero is a current decision, not a diagnosis. It can mean an intentionally strict policy, unavailable Pods, an in-progress eviction, or a controller synchronization problem.

Percentages round upward. Half of seven requires four healthy Pods, while maxUnavailable thirty percent on one desired replica permits losing that single replica. Percentage notation does not automatically make a small workload safe. Check the smallest scale your application can reach, including autoscaling and maintenance changes.

Health policy changes drain behavior

Under the default IfHealthyBudget policy, a Running but unready Pod can be evicted when currentHealthy is at least desiredHealthy. If the application is already below that threshold, such a Pod can block a drain while it has a chance to recover. The PDB sees its unhealthy state; it is not blind to the Pod.

AlwaysAllow permits eviction of those Running-but-unhealthy Pods regardless of that health threshold. It does not authorize unrestricted eviction of healthy Pods. Select the policy with recovery and maintenance needs in mind, especially when a broken readiness check could keep a replacement from ever becoming healthy.

For three healthy voting members, allowing one disruption is a common conservative choice. Recalculate quorum and availability when membership changes; an allowance of one is not suitable for every possible scale or membership protocol. Maintenance may wait for a replacement to become genuinely ready before another healthy eviction fits within the budget.

When it breaks

A minimum equal to all available replicas can deliberately block healthy evictions, rather than necessarily being a mistake. Document how maintenance should obtain room. Do not remove the budget simply because a drain is slow: first check replacement scheduling, readiness, existing disruption, and the application owner’s availability requirement.

A selector matching nothing protects nothing. Conversely, an empty policy/v1 selector matches every Pod in its namespace, which can broaden scope unexpectedly. Compare the complete selector, including matchExpressions, against live labels and owning controllers. Avoid treating a single status number as proof that the right application is protected.

Check it quickly

Inspect existing objects in the intended read-only context and namespace. These original commands were retained and were not rerun on a cluster during this review.

kubectl get pdb -A -o custom-columns=NAME:.metadata.name,MIN:.spec.minAvailable,MAX:.spec.maxUnavailable,EXPECTED:.status.expectedPods,HEALTHY:.status.currentHealthy,ALLOWED:.status.disruptionsAllowed
kubectl get pdb zk-pdb -o jsonpath='{.spec.selector.matchLabels}{"\n"}'
kubectl get statefulset zookeeper -o jsonpath='{.spec.replicas}{"\n"}'
kubectl get pods -l app=zookeeper --field-selector=status.phase=Running --no-headers | wc -l

The final command counts Running Pods, not Ready Pods. The selector command displays only matchLabels, so it omits any matchExpressions. Use those outputs as initial clues and inspect complete PDB and Pod objects before concluding that HEALTHY or EXPECTED is wrong. A zero allowance does not reveal its cause, and positive allowance does not prove application-level quorum survives an eviction.

Sources