Kubernetes will sometimes need to evict your Pods — during node drains, cluster upgrades, or autoscaler scale-downs. A Pod Disruption Budget (PDB) tells Kubernetes how much disruption your application can tolerate, preventing it from taking down too many Pods at once.

1. Voluntary vs Involuntary Disruptions

TypeCausePDB Respected?
Voluntarykubectl drain, cluster autoscaler scale-down, rolling updates, Pod eviction API✅ Yes — PDB blocks the operation until safe
InvoluntaryNode crash, OOMKill, kernel panic, hardware failure❌ No — these happen without asking
PDBs only protect against voluntary disruptions. If a node's power goes out, Kubernetes can't ask permission first — your Pods die regardless of PDB. PDBs protect you from controlled operations: drains, upgrades, and autoscaler decisions.

The Eviction API

Voluntary disruptions go through the Eviction API (POST /api/v1/namespaces/{ns}/pods/{name}/eviction). This API checks PDBs before allowing the eviction. Tools that use it:

  • kubectl drain — evicts all Pods from a node
  • Cluster Autoscaler — evicts Pods before removing a node
  • Descheduler — moves Pods for better balance
  • Node upgrades (kubeadm) — cordons and drains nodes

kubectl delete pod does NOT go through the Eviction API — it directly deletes the Pod and ignores PDBs.

This distinction matters: if ops team uses kubectl delete pod to "drain" a node manually, PDBs won't protect you. Always use kubectl drain or the Eviction API for controlled operations.

2. PDB Configuration

A PDB targets Pods via a label selector (just like a Service) and specifies one of two constraints:

Option A: minAvailable

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-pdb
spec:
  minAvailable: 2              # At least 2 Pods must stay running
  selector:
    matchLabels:
      app: web
# If you have 3 Pods, only 1 can be disrupted at a time (3 - 2 = 1)

Option B: maxUnavailable

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-pdb
spec:
  maxUnavailable: 1            # At most 1 Pod can be down at a time
  selector:
    matchLabels:
      app: web
# If you have 3 Pods, 1 can be disrupted (same result as minAvailable: 2)

Percentage Values

spec:
  minAvailable: "80%"    # At least 80% of matched Pods must stay up
  # 10 Pods × 80% = 8 must stay → 2 can be disrupted

spec:
  maxUnavailable: "25%"  # At most 25% can be down
  # 10 Pods × 25% = 2 can be disrupted at once (rounds up)

minAvailable vs maxUnavailable

minAvailablemaxUnavailable
Semantics"Keep at least N up""Allow at most N down"
As replicas scaleFixed floor — more Pods can be disrupted as you scale upFixed disruption rate — scales proportionally
Best forQuorum systems (need minimum N for correctness)General services (tolerate proportional loss)
You can only set one: minAvailable OR maxUnavailable, never both. They're two ways to express the same constraint. Choose based on which is more natural for your application's availability requirement.

3. How PDBs Work in Practice

kubectl drain Interaction

kubectl drain node-2 (3 Pods, PDB minAvailable=2) 1. Cordon node-2 (mark unschedulable) 2. Evict Pod on node-2 (checks PDB: 3-1=2 ≥ min 2 ✓) 3. Eviction allowed ✓ Pod terminated, rescheduled elsewhere If only 2 Pods are healthy (one already down): Eviction API returns 429 Too Many Requests kubectl drain retries with backoff until Pod becomes available or --timeout is reached

Drain Behavior with PDB

# Normal drain (respects PDBs):
kubectl drain node-2 --ignore-daemonsets --delete-emptydir-data
# Waits if PDB would be violated, retries until budget allows

# Drain with timeout:
kubectl drain node-2 --timeout=300s
# Gives up after 5 minutes if PDB blocks

# Force drain (IGNORES PDBs — dangerous!):
kubectl drain node-2 --disable-eviction
# Directly deletes Pods, bypasses Eviction API entirely
During cluster upgrades, if a drain hangs because of a PDB, investigate: is the workload degraded (can't reach minAvailable even without the drain)? Common cause: another Pod already crashed, so the budget is already exhausted. Fix the unhealthy Pod first, then the drain will proceed.

PDB Status

kubectl get pdb
# NAME      MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
# web-pdb   2               N/A               1                     5d

kubectl describe pdb web-pdb
# Status:
#   Current Healthy:    3
#   Desired Healthy:    2
#   Disruptions Allowed: 1    ← how many can be evicted right now
#   Expected Pods:      3
#   Observed Generation: 1
Disruptions Allowed is the key field. It shows how many Pods can be evicted RIGHT NOW without violating the budget. If it's 0, no voluntary evictions will succeed until a Pod recovers or a new one becomes Ready.

4. Common Patterns & Gotchas

Pattern: Quorum-Based Systems

# etcd (3 nodes, needs quorum of 2):
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: etcd
# Only 1 etcd Pod can be disrupted at a time
# Guarantees quorum is always maintained

Pattern: Stateless Web Service

# Web app with 10 replicas — can lose 20%:
spec:
  maxUnavailable: "20%"
  selector:
    matchLabels:
      app: web
# 2 Pods can be evicted simultaneously
# Speeds up node drains while maintaining capacity

Anti-Pattern: minAvailable = replicas

# ⚠️ DANGEROUS:
spec:
  minAvailable: 3    # with exactly 3 replicas
# Disruptions Allowed = 0 → drain NEVER succeeds
# This blocks cluster upgrades and autoscaler!
Never set minAvailable equal to your replica count (or maxUnavailable: 0). This creates an undrainable workload — cluster operations will hang forever waiting for permission that never comes. Always allow at least 1 disruption.

Gotcha: PDB and Single-Replica Deployments

# Single replica + PDB with minAvailable: 1
spec:
  minAvailable: 1
  selector:
    matchLabels:
      app: singleton
# Disruptions Allowed = 0 (can't go below 1 if you only have 1)
# Node drains will block!
# Solution: either accept downtime or run ≥2 replicas

Gotcha: PDB Doesn't Protect During Rolling Updates

Deployment rolling updates use their own maxUnavailable parameter, NOT the PDB. The PDB only applies to external disruptions (drain, autoscaler). The Deployment controller manages its own rollout budget independently.

CKA exam: you may be asked to create a PDB. Remember: (1) it's in the policy/v1 apiVersion, (2) selector must match the Pods you want to protect, (3) specify exactly one of minAvailable or maxUnavailable.

5. Unhealthy Pod Eviction Policy (K8s 1.27+)

By default, unhealthy Pods (not Ready) still count against the PDB — they can't be evicted either. The new unhealthyPodEvictionPolicy field changes this:

PolicyBehavior
IfHealthy (default)Only evict Pods if the budget allows (unhealthy Pods block drains too)
AlwaysAllowUnhealthy Pods can always be evicted regardless of budget
spec:
  maxUnavailable: 1
  unhealthyPodEvictionPolicy: AlwaysAllow
  selector:
    matchLabels:
      app: web
# If a Pod is stuck in CrashLoopBackOff, it can be evicted
# without counting against the budget
AlwaysAllow solves the "stuck drain" problem: If a Pod is already unhealthy (CrashLoopBackOff, not Ready), it's not contributing to availability anyway. Letting it be evicted unblocks node operations without sacrificing actual availability.

Summary

ConceptKey Point
PDBLimits how many Pods can be voluntarily disrupted at once
Voluntary disruptiondrain, autoscaler, eviction API — respects PDB
Involuntary disruptionNode crash, OOMKill — ignores PDB (can't be prevented)
minAvailable"Keep at least N up" — good for quorum systems
maxUnavailable"Allow at most N down" — good for proportional tolerance
DisruptionsAllowedShows how many Pods can be evicted right now
kubectl delete podDoes NOT respect PDBs (bypasses Eviction API)
Anti-patternminAvailable = replicas → blocks all drains forever

📝 Quiz: Pod Disruption Budgets

Q1: A Deployment has 5 replicas. PDB is maxUnavailable: 2. How many Pods can be evicted simultaneously?

2 Pods. maxUnavailable: 2 means at most 2 Pods can be down at any time. With 5 replicas and all healthy, disruptionsAllowed = 2.

Q2: A node crashes, killing 2 Pods. The PDB says minAvailable: 3 and there were 5 Pods. Does the PDB prevent this?

No. Node crashes are involuntary disruptions. PDBs only protect against voluntary disruptions (eviction API, drain). The Pods are killed regardless. The PDB will prevent further voluntary evictions until Pods recover to at least 3 healthy.

Q3: You run kubectl drain node-1 but it hangs. kubectl get pdb shows ALLOWED DISRUPTIONS: 0. Why and how do you fix it?

The PDB budget is exhausted — not enough healthy Pods to allow any more evictions (e.g., a Pod on another node is already unhealthy). Fix: (1) Check Pod health: kubectl get pods -l app=web. (2) Fix the unhealthy Pod (or delete it if stuck). (3) Once a replacement becomes Ready, disruptionsAllowed goes back up and the drain proceeds.

Q4: What's the difference between kubectl drain and kubectl delete pod regarding PDBs?

kubectl drain uses the Eviction API which checks PDBs — it will wait/retry if the budget doesn't allow eviction.
kubectl delete pod bypasses the Eviction API entirely — it directly deletes the Pod regardless of any PDB. Never use delete pod for operational drains.

Q5: You have a 3-replica etcd cluster. What PDB configuration ensures quorum is always maintained during drains?

minAvailable: 2 (quorum for 3-node Raft). This ensures at least 2 etcd Pods are always up, allowing only 1 to be evicted at a time. Drains proceed one node at a time, maintaining consensus throughout.

Q6: A PDB has minAvailable: "80%" and the Deployment has 4 replicas. How many disruptions are allowed?

0 disruptions. 80% of 4 = 3.2, rounded up to 4. So minAvailable=4 with 4 replicas → no Pod can be evicted. This is the percentage gotcha — at small replica counts, 80% can effectively mean "allow zero." Better to use absolute numbers for small replica counts.