When Kubernetes performs voluntary disruptions — node drains during upgrades, cluster autoscaler scaling down unused nodes, or administrators manually evicting pods — there’s a risk of taking down too many replicas of a critical service simultaneously. Without proper safeguards, a rolling update could leave your database with zero available pods or your API gateway completely unreachable.

Kubernetes addresses this with Pod Disruption Budgets (PDBs), which limit the number of concurrent disruptions for a set of pods. But managing PDBs effectively requires more than just writing YAML — it requires understanding disruption patterns, testing your configurations, and verifying that your applications remain available during real disruptions.

This guide covers three approaches to PDB management: Native Kubernetes PDBs (built-in API objects), Chaos Engineering Tools (for testing disruption resilience), and PDB Automation Patterns (for managing PDBs at scale across large clusters).

Understanding Pod Disruptions in Kubernetes

Kubernetes distinguishes between two types of disruptions:

Voluntary disruptions — Initiated by users or cluster components: node drains, cluster autoscaler scale-down, manual pod deletions, and rolling updates. These respect Pod Disruption Budgets.

Involuntary disruptions — Caused by failures: node crashes, kernel panics, network partitions, and hardware failures. These do NOT respect PDBs since the pod is already gone.

PDBs only protect against voluntary disruptions. For involuntary disruptions, you need proper replica counts, health checks, and potentially multi-zone deployments.

Comparison: PDB Management Approaches

FeatureNative PDBChaos Engineering (Pumba/Chaos Mesh)PDB Automation
TypeBuilt-in K8s API objectTesting/simulation toolsCustom controllers + operators
EnforcementAPI-level blockingSimulated disruptionsDynamic PDB management
Testing CapabilityNo (passive protection)Yes (active disruption testing)No (management only)
Auto-adjustmentManual YAML changesN/ACan adjust based on replica count
Disruption ScenariosEvictions onlyPod kills, network chaos, latencyEvictions + custom events
InstallationNone (built-in)Helm chart or binaryCustom deployment
ComplexityLowMediumHigh
Best ForProduction protectionPre-production testingLarge-scale cluster management

Native Kubernetes Pod Disruption Budgets

PDBs are defined as simple Kubernetes objects that specify either minAvailable (minimum pods that must remain running) or maxUnavailable (maximum pods that can be disrupted simultaneously).

Basic PDB Configuration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-server-pdb
  namespace: production
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: api-server

This configuration ensures at least 2 pods of the api-server Deployment remain running during any voluntary disruption. If the Deployment has 3 replicas, only 1 pod can be evicted at a time.

Using maxUnavailable

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-frontend-pdb
  namespace: production
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: web-frontend

For a 5-replica Deployment, this allows 1 pod to be disrupted at a time (20% max unavailable). This is generally safer for large replica counts than minAvailable, as it scales with the replica count.

Using Percentages

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: database-pdb
  namespace: production
spec:
  minAvailable: 50%
  selector:
    matchLabels:
      app: database

Percentage-based PDBs automatically scale with the Deployment’s replica count. For 4 replicas, minAvailable: 50% means at least 2 pods must stay running.

Common PDB Patterns

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Single-replica workloads (no disruption protection needed)
# Don't create PDBs for single-replica workloads — they can't be protected

# StatefulSet with 3 replicas
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: postgres-pdb
spec:
  minAvailable: 2  # Keep at least 2/3 replicas running
  selector:
    matchLabels:
      app: postgres

# Large-scale stateless service with 20 replicas
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-pdb
spec:
  maxUnavailable: 10%  # Allow 2 pods to be disrupted at once
  selector:
    matchLabels:
      app: api

# Critical infrastructure
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: coredns-pdb
  namespace: kube-system
spec:
  minAvailable: 1  # At least one CoreDNS always running
  selector:
    matchLabels:
      k8s-app: kube-dns

Testing PDB Configurations with Chaos Engineering

Writing PDBs is straightforward — verifying they actually work is where chaos engineering tools become essential. Tools like Pumba and Chaos Mesh can simulate real disruptions to validate your PDB configurations.

Pumba — Lightweight Chaos Testing

Pumba is a Go-based chaos testing tool that can kill, pause, or network-disrupt containers.

1
2
3
4
5
# Kill random pods every 60 seconds
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock   gaiaadm/pumba kill --interval 60s --random --labels "app=my-app"

# Kill pods matching a label
kubectl run pumba --image=gaiaadm/pumba --   kill --interval 30s --regexp "my-app-.*"

Chaos Mesh — Comprehensive Chaos Platform

Chaos Mesh provides a full-featured chaos engineering platform with a web UI and CRD-based configuration.

Installation

1
helm install chaos-mesh chaos-mesh/chaos-mesh   --namespace=chaos-testing --create-namespace

Pod Chaos Experiment

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
  name: test-pdb-eviction
  namespace: production
spec:
  action: pod-failure
  mode: one
  selector:
    labelSelectors:
      app: api-server
  duration: "30s"
  scheduler:
    cron: "@every 5m"

Docker Compose for Local Chaos Testing

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
version: "3.8"
services:
  chaos-dashboard:
    image: ghcr.io/chaos-mesh/chaos-dashboard:latest
    ports:
    - "23333:23333"
    volumes:
    - chaos-data:/data
    restart: unless-stopped

volumes:
  chaos-data:

Validating PDB Behavior

After deploying a chaos experiment, verify PDB enforcement:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Check PDB status
kubectl get pdb -n production

# Expected output:
# NAME              MIN AVAILABLE   MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
# api-server-pdb    2               N/A               1                     5d
# web-frontend-pdb  N/A             1                 1                     5d

# Attempt a drain (simulates voluntary disruption)
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data

# If PDB is working, drain will block when disruption limit is reached:
# error: Cannot evict pod as it would violate the pod's disruption budget.

Why Implement Pod Disruption Budgets?

Service availability during cluster maintenance — When performing node upgrades, security patches, or kernel updates, PDBs ensure that draining nodes doesn’t simultaneously take down all replicas of a critical service. This is essential for zero-downtime maintenance.

Protecting against cluster autoscaler — The cluster autoscaler removes underutilized nodes. Without PDBs, it could evict the last remaining pod of a service from a node being scaled down, causing an outage.

Safe rolling deployments — Combined with Deployment rolling update strategies, PDBs provide a safety net that prevents deployment tooling from accidentally disrupting more pods than intended.

Multi-zone resilience — PDBs work alongside pod topology spread constraints to ensure disruptions don’t concentrate in a single availability zone, maintaining cross-zone availability during voluntary disruptions.

For comprehensive disruption testing, see our Chaos Engineering guide covering Pumba, Toxiproxy, and Chaos Monkey. For policy enforcement around PDB configurations, our Kubernetes Policy Enforcement comparison shows how OPA Gatekeeper and Kyverno can enforce PDB requirements. For namespace isolation patterns, see our Kubernetes Namespace guide.

Common PDB Mistakes and How to Avoid Them

MistakeConsequenceFix
minAvailable equal to replica countNodes can never drainSet minAvailable to replica count - 1
PDB on single-replica workloadsUseless protectionDon’t create PDBs for single replicas
Conflicting PDBs (minAvailable + maxUnavailable)API rejectionUse one or the other, not both
Selector doesn’t match any podsSilent failureVerify with kubectl get pdb -w
No PDB on critical servicesUnprotected disruptionsAudit all critical workloads for PDB coverage

Choosing the Right PDB Management Approach

ScenarioRecommended Approach
Small cluster (under 20 workloads)Native PDB with manual YAML management
Pre-production testingChaos Mesh or Pumba for disruption validation
Large cluster (100+ workloads)Native PDB + GitOps management (ArgoCD/Flux)
Compliance requirementsNative PDB + OPA Gatekeeper enforcement policies
Continuous resilience testingChaos Mesh with scheduled experiments

For most teams, the optimal strategy is: deploy native PDBs for all multi-replica workloads, then use chaos engineering tools quarterly to validate that PDBs are correctly configured and that applications gracefully handle disruptions.

FAQ

What is the difference between minAvailable and maxUnavailable?

minAvailable specifies the minimum number of pods that must remain running during disruptions. maxUnavailable specifies the maximum number of pods that can be disrupted. Both achieve similar goals but from opposite directions. For small replica counts (3-5), minAvailable is more intuitive. For large replica counts (10+), maxUnavailable with a percentage is easier to manage.

Do Pod Disruption Budgets protect against node failures?

No. PDBs only protect against voluntary disruptions (node drains, manual evictions). Involuntary disruptions like node crashes or network partitions bypass PDBs entirely. For protection against involuntary disruptions, use adequate replica counts across multiple failure domains.

What happens if a PDB blocks a node drain?

The kubectl drain command will fail with an error: Cannot evict pod as it would violate the pod's disruption budget. The drain command respects PDBs and will not evict pods beyond the allowed disruption limit. You can use --force to override PDBs, but this is dangerous for production workloads.

Can I have multiple PDBs targeting the same pods?

No. Kubernetes only allows one PDB per pod. If multiple PDBs select the same pods, the behavior is undefined and can lead to unexpected disruption blocking. Each workload should have exactly one PDB.

How do I audit PDB coverage across my cluster?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# List all PDBs
kubectl get pdb --all-namespaces

# Find Deployments without PDBs
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
  for deploy in $(kubectl get deploy -n $ns -o jsonpath='{.items[*].metadata.name}'); do
    replicas=$(kubectl get deploy $deploy -n $ns -o jsonpath='{.spec.replicas}')
    if [ "$replicas" -gt 1 ]; then
      pdb=$(kubectl get pdb -n $ns --field-selector spec.selector.matchLabels.app=$(kubectl get deploy $deploy -n $ns -o jsonpath='{.spec.template.metadata.labels.app}') 2>/dev/null)
      if [ -z "$pdb" ]; then
        echo "WARNING: $ns/$deploy has $replicas replicas but no PDB"
      fi
    fi
  done
done

Should I set PDBs for system namespaces?

Yes. Critical system components like CoreDNS, kube-proxy (if not DaemonSet), and ingress controllers should have PDBs in their respective namespaces. Many managed Kubernetes distributions include default PDBs for system components.