Configure Pod Disruption Budgets to ensure application availability during cluster maintenance and scaling operations. Learn to implement PDB policies, test disruption scenarios, and maintain service continuity in Kubernetes.
Prerequisites
- Kubernetes cluster with kubectl access
- Administrative privileges on the cluster
- At least 2 worker nodes for testing
What this solves
Pod Disruption Budgets (PDBs) protect your applications from voluntary disruptions during cluster maintenance, node drains, and scaling operations. Without PDBs, Kubernetes may terminate all replicas of a service simultaneously, causing downtime during routine operations like cluster upgrades or node maintenance.
Understanding Pod Disruption Budgets
A Pod Disruption Budget defines the minimum number or percentage of pods that must remain available during voluntary disruptions. Kubernetes respects these constraints when performing operations like node drains, ensuring your applications maintain availability.
PDBs only protect against voluntary disruptions (maintenance, scaling) not involuntary ones (node failures, hardware issues). They work by preventing the eviction API from removing pods below your specified threshold.
Step-by-step configuration
Verify kubectl access
Confirm you have administrative access to your Kubernetes cluster.
kubectl cluster-info
kubectl get nodes
Create a sample application
Deploy a multi-replica application to demonstrate PDB functionality.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
namespace: default
spec:
replicas: 4
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: web-app-service
spec:
selector:
app: web-app
ports:
- port: 80
targetPort: 80
type: ClusterIP
Apply the deployment
Create the application deployment and service.
kubectl apply -f web-app-deployment.yaml
kubectl get pods -l app=web-app
Create a Pod Disruption Budget with minimum available
Configure a PDB ensuring at least 2 pods remain available during disruptions.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-app-pdb-min
namespace: default
spec:
minAvailable: 2
selector:
matchLabels:
app: web-app
Create a Pod Disruption Budget with maximum unavailable
Alternative PDB configuration limiting disruptions to 50% of pods.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-app-pdb-max
namespace: default
spec:
maxUnavailable: 50%
selector:
matchLabels:
app: web-app
Apply the Pod Disruption Budget
Choose one PDB configuration and apply it to your cluster.
kubectl apply -f web-app-pdb-min.yaml
kubectl get pdb
Create PDB for critical system components
Configure PDBs for essential services like DNS and ingress controllers.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: coredns-pdb
namespace: kube-system
spec:
minAvailable: 1
selector:
matchLabels:
k8s-app: kube-dns
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: ingress-nginx-pdb
namespace: ingress-nginx
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
Apply system PDBs
Protect critical cluster components with disruption budgets.
kubectl apply -f system-pdbs.yaml
kubectl get pdb --all-namespaces
Testing PDB behavior
Test node drain with PDB protection
Simulate maintenance by draining a node to observe PDB enforcement.
# Identify node with your pods
kubectl get pods -l app=web-app -o wide
Drain the node (replace NODE_NAME)
kubectl drain NODE_NAME --ignore-daemonsets --delete-emptydir-data
Monitor pod evictions in another terminal
kubectl get pods -l app=web-app -w
Verify PDB status during drain
Check PDB status to see how it prevents excessive pod evictions.
kubectl get pdb web-app-pdb-min -o yaml
kubectl describe pdb web-app-pdb-min
Test manual pod eviction
Attempt to evict pods manually to verify PDB protection.
# Get pod name
POD_NAME=$(kubectl get pods -l app=web-app -o jsonpath='{.items[0].metadata.name}')
Try to evict the pod
kubectl delete pod $POD_NAME
Check remaining pods
kubectl get pods -l app=web-app
Restore node availability
Uncordon the drained node to restore normal scheduling.
kubectl uncordon NODE_NAME
kubectl get nodes
Advanced PDB configurations
Create PDB with unhealthy pod handling
Configure PDB behavior when pods are unhealthy or not ready.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-app-advanced-pdb
namespace: default
spec:
minAvailable: 2
selector:
matchLabels:
app: web-app
unhealthyPodEvictionPolicy: AlwaysAllow
Create namespace-scoped PDB
Configure PDBs for specific namespaces to organize policies.
# Create production namespace
kubectl create namespace production
Create PDB for production namespace
kubectl apply -f - <
Configure PDB with label selectors
Use complex label selectors for precise pod targeting.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: multi-tier-pdb
namespace: default
spec:
minAvailable: 1
selector:
matchExpressions:
- key: tier
operator: In
values:
- frontend
- backend
- key: environment
operator: NotIn
values:
- development
Monitoring and alerting
Create PDB monitoring script
Monitor PDB violations and disruption events with a monitoring script.
#!/bin/bash
echo "=== Pod Disruption Budget Status ==="
kubectl get pdb --all-namespaces -o wide
echo "\n=== PDB Details ==="
for pdb in $(kubectl get pdb --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{"\n"}{end}'); do
namespace=$(echo $pdb | cut -d' ' -f1)
name=$(echo $pdb | cut -d' ' -f2)
echo "\nPDB: $namespace/$name"
kubectl get pdb $name -n $namespace -o jsonpath='{"Allowed Disruptions: "}{.status.disruptionsAllowed}{"\n"}'
kubectl get pdb $name -n $namespace -o jsonpath='{"Current Healthy: "}{.status.currentHealthy}{"\n"}'
kubectl get pdb $name -n $namespace -o jsonpath='{"Desired Healthy: "}{.status.desiredHealthy}{"\n"}'
done
echo "\n=== Recent Events ==="
kubectl get events --sort-by=.metadata.creationTimestamp | grep -i disruption
Make monitoring script executable
Set proper permissions and test the monitoring script.
chmod +x monitor-pdb.sh
./monitor-pdb.sh
Verify your setup
# Check all PDBs
kubectl get pdb --all-namespaces
Verify PDB status
kubectl describe pdb web-app-pdb-min
Check pod distribution
kubectl get pods -l app=web-app -o wide
Verify node status
kubectl get nodes
Test PDB API
kubectl get pdb -o json | jq '.items[].status'
Common issues
| Symptom | Cause | Fix |
|---|---|---|
| PDB shows 0 allowed disruptions | Not enough healthy pods | Check pod status: kubectl get pods -l app=web-app |
| Node drain hangs indefinitely | PDB preventing eviction | Scale up replicas or adjust PDB: kubectl scale deployment web-app --replicas=6 |
| PDB not selecting any pods | Incorrect label selector | Verify labels match: kubectl get pods --show-labels |
| Pods evicted despite PDB | Involuntary disruption | Check node status and events: kubectl describe node NODE_NAME |
| PDB conflicts with other PDBs | Overlapping selectors | Review all PDBs: kubectl get pdb -o yaml |
Next steps
- Configure Kubernetes vertical pod autoscaler for resource optimization and cost management
- Configure Kubernetes cluster autoscaler with mixed instance types for cost optimization
- Configure Kubernetes resource quotas and limit ranges for namespace-level resource management
- Implement Kubernetes deployment strategies with blue-green and canary releases
- Configure Kubernetes cluster monitoring with Prometheus Operator and Grafana