VantraOpsBeta
← Back to blog
·The VantraOps Team

PodDisruptionBudgets Explained: Why Your Deploys Keep Taking Down Prod

kubernetesavailabilitybest practices
Abstract Kubernetes hexagon node icon representing PodDisruptionBudgets

A routine node drain during a cluster upgrade shouldn’t take your service down. In practice, for a large share of Kubernetes deployments, it does — not because the upgrade did anything wrong, but because nothing told Kubernetes that taking down three replicas of a service at once, all at the same time, was unacceptable. That’s precisely the gap a PodDisruptionBudget closes, and it’s one of the most commonly missing pieces of production configuration in real clusters.

The distinction that actually matters: voluntary vs. involuntary disruptions

Kubernetes separates disruptions into two categories, and PodDisruptionBudgets (PDBs) only govern one of them.

Involuntary disruptions — a node crashing, a hardware failure, an out-of-memory kill — aren’t something a PDB can prevent. They’re unplanned by definition, and the right defense against them is redundancy (multiple replicas, spread across nodes and zones), not a PDB.

Voluntary disruptions — a node drain for maintenance, a cluster upgrade, a kubectl drain run by a human or an autoscaler — are planned, and this is exactly where a PDB matters. It tells Kubernetes “don’t evict more than N pods of this workload at once, no matter how convenient it would be for the drain to go faster.”

Without a PDB, a node drain will evict every pod on that node as fast as it can, with no awareness that three of those pods happen to be the only three replicas of your payments service. With one, the drain respects your stated minimum and proceeds more slowly, pod by pod, keeping your service available throughout.

What a PodDisruptionBudget actually looks like

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: checkout-service-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: checkout-service

This says: no voluntary disruption may proceed if it would drop the number of available checkout-service pods below 2. If you’re running 3 replicas, at most 1 can be evicted at a time during a drain — the other 2 stay up and serving traffic throughout.

You can express this as maxUnavailable instead of minAvailable, whichever maps more naturally to how you think about the service. For a service running a small, fixed replica count, minAvailable is usually more intuitive; for one that autoscales, maxUnavailable as a percentage (25%) scales more gracefully with replica count than a fixed number would.

The mistake that makes PDBs actively harmful: setting them too strict

A PDB that’s too conservative doesn’t just slow drains down — it can block them entirely. If minAvailable equals your total replica count (or maxUnavailable: 0), no voluntary disruption can ever proceed, which means a node can never be drained cleanly while that pod is scheduled on it. This turns a PDB from a safety mechanism into an operational deadlock: the drain simply hangs, waiting for a condition that can never be satisfied.

This is worth checking for directly if you’ve set PDBs defensively without doing the arithmetic: minAvailable needs to be strictly less than your typical running replica count, with enough gap that a drain can make real progress. For a 3-replica service, minAvailable: 2 allows one pod to move at a time; minAvailable: 3 allows none, ever.

How this interacts with autoscaling

If Horizontal Pod Autoscaling is in play, your PDB needs to be set with an awareness of minReplicas, not just your typical steady-state replica count. If HPA can legitimately scale a service down to 1 replica during a quiet period, and your PDB requires minAvailable: 2, you’ve created the same deadlock scenario as above — just triggered by autoscaling instead of a manifest with the wrong number typed in. The two settings need to be reasoned about together, not configured independently by whoever happened to touch each one.

Why this is worth checking across every production service, not just the important ones

The instinct is to add a PDB to the “important” services and skip it for the rest, but disruption during a drain doesn’t respect which services you consider critical — every pod on a node being drained is affected equally, whether it’s your payments API or an internal cron job. The cron job not having a PDB is lower-stakes if it goes down briefly, which is a reasonable place to accept the risk deliberately — but that should be a deliberate choice, not the default state because nobody got around to setting one.

This is exactly the kind of check that’s easy to do once and then forget as new services get added — which is why it’s one of the twelve checks in our Kubernetes Well-Architected checklist, and why ongoing architecture review matters more than a one-time pass: a new Deployment added this month without a PDB is just as exposed as one that’s been missing one for a year.

Frequently asked questions

Do I need a PDB for a single-replica service? A PDB with minAvailable: 1 on a single-replica service would block all voluntary disruption entirely — which is rarely what you want. For single-replica services, the real fix is usually running more than one replica, not a PDB working around the fact that you’re not.

Does a PDB protect against a node crashing unexpectedly? No — PDBs only govern voluntary, planned disruptions. Protection against unplanned node failure comes from running multiple replicas spread across nodes and zones, independent of whether a PDB exists.

What happens if a node needs to be drained but the PDB won’t allow it? The drain will wait, retrying until the PDB’s condition can be satisfied — which might mean it hangs indefinitely if the PDB is misconfigured (see the deadlock scenario above), or resolves once other pods on the node get rescheduled and free up room to proceed.

Should PDBs be set for StatefulSets differently than Deployments? The mechanism is the same, but StatefulSets often warrant more conservative settings since ordering and identity matter more — losing the wrong replica of a stateful workload can have consequences a stateless Deployment doesn’t share, so it’s worth being more deliberate about the minimum, not just copying the same number across workload types.

Check every production service for a missing or misconfigured PDB in one pass — start free with one cluster.