How to Configure Pod Disruption Budgets
Protect application availability during voluntary disruptions. Configure PDBs to ensure minimum replicas during node drains, upgrades, and maintenance.
How to Configure Pod Disruption Budgets
Pod Disruption Budgets (PDBs) limit voluntary disruptions to ensure application availability during node maintenance, cluster upgrades, and autoscaling events.
Understanding Disruptions
# Voluntary disruptions (PDB applies):
# - Node drain (kubectl drain)
# - Cluster autoscaler scale-down
# - Node upgrades
# - Pod eviction API
# Involuntary disruptions (PDB does NOT apply):
# - Node failure
# - Kernel panic
# - Pod OOM killed
# - Hardware failureBasic PDB with minAvailable
# pdb-min-available.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
minAvailable: 2 # At least 2 pods must remain available
selector:
matchLabels:
app: webkubectl apply -f pdb-min-available.yaml
# Check PDB status
kubectl get pdb web-pdb
# NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
# web-pdb 2 N/A 1 1mPDB with maxUnavailable
# pdb-max-unavailable.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-pdb
spec:
maxUnavailable: 1 # At most 1 pod can be unavailable
selector:
matchLabels:
app: apiPercentage-Based PDB
# pdb-percentage.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: worker-pdb
spec:
minAvailable: "50%" # At least 50% of pods must remain
selector:
matchLabels:
app: worker
---
# Or with maxUnavailable
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: cache-pdb
spec:
maxUnavailable: "25%" # At most 25% can be unavailable
selector:
matchLabels:
app: cachePDB for StatefulSets
# statefulset-pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: database-pdb
spec:
maxUnavailable: 1
selector:
matchLabels:
app: database
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: database
spec:
replicas: 3
selector:
matchLabels:
app: database
template:
metadata:
labels:
app: database
# ...PDB for DaemonSets
# daemonset-pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: logging-pdb
spec:
maxUnavailable: "10%" # Allow 10% of nodes to drain
selector:
matchLabels:
app: fluentd
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
spec:
selector:
matchLabels:
app: fluentd
# ...Multiple PDBs for Different Components
# multi-pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: frontend-pdb
namespace: production
spec:
minAvailable: 3
selector:
matchLabels:
app: myapp
component: frontend
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: backend-pdb
namespace: production
spec:
minAvailable: 2
selector:
matchLabels:
app: myapp
component: backend
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: worker-pdb
namespace: production
spec:
maxUnavailable: "50%"
selector:
matchLabels:
app: myapp
component: workerUnhealthy Pod Eviction Policy
# unhealthy-eviction.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: app-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: myapp
unhealthyPodEvictionPolicy: AlwaysAllow
# Options:
# - IfHealthyBudget (default): Only evict unhealthy pods if budget allows
# - AlwaysAllow: Always allow evicting unhealthy podsCheck PDB Status
# List all PDBs
kubectl get pdb -A
# Detailed PDB info
kubectl describe pdb web-pdb
# Check allowed disruptions
kubectl get pdb web-pdb -o jsonpath='{.status.disruptionsAllowed}'
# Watch PDB during drain
kubectl get pdb -w
# PDB blocking drain? Check conditions
kubectl get pdb web-pdb -o yaml | grep -A 10 conditionsTest PDB Behavior
# Create deployment with 3 replicas
kubectl create deployment web --image=nginx --replicas=3
# Create PDB requiring 2 available
kubectl create pdb web-pdb --selector=app=web --min-available=2
# Try to drain node (will respect PDB)
kubectl drain node1 --ignore-daemonsets --delete-emptydir-data
# If PDB blocks drain, you'll see:
# error when evicting pods: Cannot evict pod as it would violate the pod's disruption budget
# Force drain (ignores PDB - use with caution)
kubectl drain node1 --ignore-daemonsets --delete-emptydir-data --forceCommon PDB Patterns
# High availability service (always keep majority)
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: ha-service-pdb
spec:
minAvailable: "51%"
selector:
matchLabels:
app: ha-service
---
# Single replica service (prevent all evictions)
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: singleton-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: singleton
---
# Batch jobs (allow some disruption)
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: batch-pdb
spec:
maxUnavailable: "30%"
selector:
matchLabels:
app: batch-workerPDB with Cluster Autoscaler
# Ensure autoscaler respects availability
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: critical-app-pdb
annotations:
cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
spec:
minAvailable: 2
selector:
matchLabels:
app: critical-appTroubleshooting PDB Issues
# PDB blocking all evictions?
# Check if minAvailable >= current replicas
kubectl get pdb myapp-pdb
kubectl get pods -l app=myapp
# Common issues:
# 1. minAvailable equals replica count (no room for eviction)
# 2. Unhealthy pods counting against budget
# 3. Multiple PDBs selecting same pods
# Find pods selected by PDB
kubectl get pods -l $(kubectl get pdb myapp-pdb -o jsonpath='{.spec.selector.matchLabels}' | tr -d '{}' | tr ':' '=' | tr ',' ',')
# Check if pod is covered by PDB
kubectl get pdb --selector=app=myappBest Practices
1. Always create PDBs for production workloads
- Prevents accidental full eviction
- Ensures availability during maintenance
2. Set reasonable values
- Don't set minAvailable = replicas (blocks all drains)
- Allow at least 1 disruption for upgrades
3. Use percentages for variable replica counts
- minAvailable: "50%" scales with replicas
- Easier to maintain
4. Consider unhealthy pods
- Use AlwaysAllow to evict stuck pods
- Prevents unhealthy pods blocking drains
5. Test PDBs before production
- Verify drain behavior
- Ensure upgrades can proceedSummary
Pod Disruption Budgets protect application availability during voluntary disruptions like node drains and upgrades. Use minAvailable to specify minimum running pods or maxUnavailable to limit concurrent disruptions. Percentages work well for variable replica counts. Always create PDBs for production workloads but ensure values allow some disruption for maintenance. Use unhealthyPodEvictionPolicy: AlwaysAllow to prevent unhealthy pods from blocking operations. Check PDB status with kubectl get pdb to monitor allowed disruptions.
📘 Go Further with Kubernetes Recipes
Love this recipe? There’s so much more! This is just one of 100+ hands-on recipes in our comprehensive Kubernetes Recipes book.
Inside the book, you’ll master:
- ✅ Production-ready deployment strategies
- ✅ Advanced networking and security patterns
- ✅ Observability, monitoring, and troubleshooting
- ✅ Real-world best practices from industry experts
“The practical, recipe-based approach made complex Kubernetes concepts finally click for me.”
👉 Get Your Copy Now — Start building production-grade Kubernetes skills today!
📘 Get All 100+ Recipes in One Book
Stop searching — get every production-ready pattern with detailed explanations, best practices, and copy-paste YAML.
Want More Kubernetes Recipes?
This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.