How to Implement Pod Disruption Budgets
Configure Pod Disruption Budgets (PDB) for high availability during voluntary disruptions. Ensure minimum availability during node maintenance and cluster upgrades.
How to Implement Pod Disruption Budgets
Pod Disruption Budgets protect applications from voluntary disruptions like node drains, cluster upgrades, and autoscaling. Ensure minimum availability during planned maintenance.
Understanding Disruptions
Voluntary Disruptions (PDB applies):
- Node drain for maintenance
- Cluster autoscaler scale-down
- Deployment rolling updates
- kubectl delete pod
Involuntary Disruptions (PDB doesn’t apply):
- Node crash
- VM deletion
- Kernel panic
- Out of resources
Basic PDB with minAvailable
# pdb-min-available.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-app-pdb
namespace: production
spec:
minAvailable: 2 # At least 2 pods must be available
selector:
matchLabels:
app: web-appPDB with maxUnavailable
# pdb-max-unavailable.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-server-pdb
spec:
maxUnavailable: 1 # At most 1 pod can be unavailable
selector:
matchLabels:
app: api-serverPercentage-Based PDB
# pdb-percentage.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: worker-pdb
spec:
minAvailable: "75%" # 75% must remain available
selector:
matchLabels:
app: worker
---
# Or using maxUnavailable
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: cache-pdb
spec:
maxUnavailable: "25%" # Max 25% can be unavailable
selector:
matchLabels:
app: cachePDB for StatefulSet
# statefulset-pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: database-pdb
spec:
minAvailable: 2 # Quorum for 3-node cluster
selector:
matchLabels:
app: postgres
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15Multiple PDBs for Different Components
# frontend-pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: frontend-pdb
namespace: production
spec:
minAvailable: 3
selector:
matchLabels:
tier: frontend
---
# backend-pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: backend-pdb
namespace: production
spec:
maxUnavailable: 1
selector:
matchLabels:
tier: backend
---
# cache-pdb.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: cache-pdb
namespace: production
spec:
minAvailable: "50%"
selector:
matchLabels:
tier: cachePDB with Deployment
# deployment-with-pdb.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 5
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
# Spread across nodes for better availability
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: web-app
containers:
- name: web
image: web-app:v1
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-app-pdb
spec:
minAvailable: 3 # 3 of 5 always available
selector:
matchLabels:
app: web-appUnhealthy Pod Eviction Policy
# pdb-unhealthy-policy.yaml
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: api-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: api
# Kubernetes 1.26+: Allow evicting unhealthy pods
unhealthyPodEvictionPolicy: AlwaysAllow
# Options:
# - IfHealthyBudget: Only evict unhealthy if healthy budget allows (default)
# - AlwaysAllow: Always allow evicting unhealthy podsCheck PDB Status
# List all PDBs
kubectl get pdb -A
# Describe specific PDB
kubectl describe pdb web-app-pdb
# Check disruptions allowed
kubectl get pdb web-app-pdb -o yaml
# Output shows:
# status:
# currentHealthy: 5
# desiredHealthy: 3
# disruptionsAllowed: 2
# expectedPods: 5Testing PDB During Drain
# Try to drain a node (respects PDB)
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data
# Force drain (ignores PDB - use carefully!)
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data --force
# Uncordon node after maintenance
kubectl uncordon node-1PDB Blocking Scenarios
# If drain is blocked, check PDB
kubectl get pdb -A
# Example output showing blocked drain:
# NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
# web-app-pdb 3 N/A 0 1h
# ALLOWED DISRUPTIONS = 0 means drain will be blockedBest Practices Configuration
# production-pdb.yaml
# For 5-replica deployment, allow 1 disruption
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: production-pdb
labels:
environment: production
spec:
maxUnavailable: 1
selector:
matchLabels:
app: critical-service
environment: production# staging-pdb.yaml
# For staging, be more lenient
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: staging-pdb
spec:
maxUnavailable: "50%"
selector:
matchLabels:
environment: stagingPDB Anti-Patterns to Avoid
# BAD: minAvailable equals replicas (blocks all drains)
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: bad-pdb
spec:
minAvailable: 3 # Same as replica count!
selector:
matchLabels:
app: myapp
# This blocks ALL voluntary disruptions!
# GOOD: Allow at least 1 disruption
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: good-pdb
spec:
maxUnavailable: 1
selector:
matchLabels:
app: myappMonitoring PDB Metrics
# PrometheusRule for PDB alerts
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: pdb-alerts
spec:
groups:
- name: pdb
rules:
- alert: PDBDisruptionsBlocked
expr: kube_poddisruptionbudget_status_pod_disruptions_allowed == 0
for: 15m
labels:
severity: warning
annotations:
summary: "PDB {{ $labels.poddisruptionbudget }} blocking disruptions"
description: "PDB has 0 allowed disruptions for 15 minutes"Summary
Pod Disruption Budgets ensure application availability during voluntary disruptions. Use minAvailable for critical services, maxUnavailable for flexible deployments. Always allow at least 1 disruption to prevent blocking cluster maintenance. Combine with topology spread for best availability.
📘 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.