Skip to main content
reliability · kubernetes

PodDisruptionBudgets with maxUnavailable set to 0 or 0%

resource types
1
rule IDs covered
3
severity
high

What does ZopNight detect here?

ZopNight flags any PodDisruptionBudget on EKS, GKE or AKS whose `spec.maxUnavailable` is `0` or `0%`. The Kubernetes API reference gives 0 as the value that prevents all voluntary evictions, so a drain of any node hosting one of the selected pods never completes, whatever state the pods are in.

Signal and threshold

How ZopNight evaluates PodDisruptionBudgets with maxUnavailable set to 0 or 0%.
Field Value
Rule IDsRC-1748 · RC-1848 · RC-1948
Categoryreliability
Severityhigh
Metricspec.maxUnavailable
Threshold0 or 0%
SourceZopNight
Permissions usedlist poddisruptionbudgets.policy

Zero unavailable means zero evictions

maxUnavailable sets how many selected pods may be down after an eviction. The PodDisruptionBudget API reference uses 0 as its own example of a value that prevents all voluntary evictions. The disruption budget task page confirms that 0 and 0% both require zero voluntary evictions, and that a node running one of those pods cannot be drained: the drain simply never finishes. Kubernetes permits the setting, but every routine operation that moves pods, from node upgrades to scale-downs, will wait on it.

The value is often written with good intent, to protect a quorum or a stateful primary. The budget cannot tell a planned upgrade from an accident, though, so it blocks both.

Listing budgets that forbid eviction

Terminal window
kubectl get poddisruptionbudgets -A -o json | jq -r '
.items[]
| select(.spec.maxUnavailable == 0 or .spec.maxUnavailable == "0%")
| "\(.metadata.namespace)/\(.metadata.name) maxUnavailable=\(.spec.maxUnavailable)"'

A spec check, independent of pod health

ZopNight reads the maxUnavailable value recorded for each budget and fires when it is exactly 0 or 0%. Nothing else is weighed: not the pod count, not pod health, not the budget’s age. A budget that uses minAvailable instead, or sets no maxUnavailable, is outside this check. Changing the value to anything above zero clears the finding on the next evaluation.

How it relates to the other budget findings

Because this is a spec check, it catches the problem before any drain fails. The live counterpart, PDB blocks all voluntary disruptions, reads the status and also fires when a minAvailable budget has no room left, so a budget with maxUnavailable: 0 and running pods usually appears in both. Budgets whose selector finds no pods are reported by PDB matches no pods.

An operational cost, not a billing one

No saving is calculated. The consequence is maintenance that cannot finish: node pools stuck on old versions and nodes kept alive only because their pods cannot leave.

Allowing one pod out at a time

  1. Decide how many replicas the application can lose briefly. For most services with three or more replicas, one is safe.
  2. Set maxUnavailable: 1, or a percentage. Kubernetes rounds a maxUnavailable percentage up, so even 10% of three pods allows one eviction.
  3. Apply the change with kubectl apply and confirm status.disruptionsAllowed is now at least 1.
  4. If the workload truly must never be evicted, document the exception and plan how its nodes will be maintained by hand.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

472 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

472 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·