CKA — Drain & Cordon Nodes
Drain vs Cordon vs Uncordon
| Command | Effect |
|---|---|
kubectl cordon <node> |
Marks the node as unschedulable — no new Pods placed on it, existing Pods keep running |
kubectl drain <node> |
Cordons the node AND evicts all Pods (except DaemonSet Pods) |
kubectl uncordon <node> |
Marks the node as schedulable again |
Key insight: drain = cordon + evict. Always use drain before upgrading a node to safely move workloads elsewhere.
kubectl drain
kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data
Common Flags
| Flag | Purpose |
|---|---|
--ignore-daemonsets |
DaemonSet Pods cannot be evicted, so skip them |
--delete-emptydir-data |
Allow draining Pods that use emptyDir volumes |
--force |
Force drain even if Pods are not managed by a controller |
--grace-period=<seconds> |
Override Pod termination grace period |
--timeout=<duration> |
Abort drain if it takes too long |
What Happens During a Drain
- Node is marked SchedulingDisabled (cordoned)
- All Pods on the node (except DaemonSets) are evicted
- Pods managed by Deployments/ReplicaSets are rescheduled on other nodes
- Standalone Pods (not managed by a controller) are deleted (lost unless
--forceis used)
PodDisruptionBudgets (PDBs)
PDBs protect applications from having too many Pods evicted simultaneously. During a drain, Kubernetes respects PDBs.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: web
PDB Impact on Drain
| Scenario | Result |
|---|---|
| PDB satisfied (enough replicas on other nodes) | Drain succeeds immediately |
| PDB violated (would drop below minAvailable) | Drain blocks until more replicas are ready |
| No PDB exists | Drain proceeds without restriction |
Handling PDB Blocks
# Check PDBs
kubectl get pdb -A
# Options if drain is blocked:
# 1. Scale up the Deployment first
kubectl scale deployment web --replicas=5
# 2. Wait for Pods to become ready on other nodes
# 3. Use --disable-eviction (caution: bypasses PDB)
kubectl cordon
# Prevent new Pods from being scheduled on the node
kubectl cordon <node-name>
# Node shows SchedulingDisabled
kubectl get nodes
# NAME STATUS ROLES
# node1 Ready,SchedulingDisabled worker
Use cordon when you want to stop new work from landing on a node but keep existing workloads running.
kubectl uncordon
# Allow scheduling again after upgrade
kubectl uncordon <node-name>
# Node is back to Ready
kubectl get nodes
# NAME STATUS ROLES
# node1 Ready worker
Exam tip: Always uncordon the node after upgrading. Forgetting this means the node stays unschedulable and Pods cannot be placed on it.
Next: Upgrade Control Plane ->