CKA — Drain & Cordon Nodes

1 minute read

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

  1. Node is marked SchedulingDisabled (cordoned)
  2. All Pods on the node (except DaemonSets) are evicted
  3. Pods managed by Deployments/ReplicaSets are rescheduled on other nodes
  4. Standalone Pods (not managed by a controller) are deleted (lost unless --force is 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 ->

Updated: