# kubectl drain: Evict Pods Before Node Work

> kubectl drain cordons a node and evicts its pods for maintenance. Reference for --ignore-daemonsets, --delete-emptydir-data, --force, and the PDB block error.

Source: https://latchkey.dev/learn/command-reference/kubectl-drain-node-ci  
Updated: 2026-06-30

kubectl drain marks a node unschedulable and evicts its pods so the node can be upgraded or removed safely.

Before patching or terminating a node, drain moves the workloads off it, honoring PodDisruptionBudgets so availability is preserved.

## What it does

kubectl drain first cordons the node (no new pods schedule there), then evicts the running pods via the Eviction API, which respects PodDisruptionBudgets. DaemonSet pods and bare (unmanaged) pods need explicit flags because drain refuses to evict them by default.

## Common usage

```Terminal
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data
# include unmanaged pods and set a timeout
kubectl drain node-1 --ignore-daemonsets --force --timeout=120s
# put it back in service afterward
kubectl uncordon node-1
```

## Options

| Flag | What it does |
| --- | --- |
| --ignore-daemonsets | Proceed even though DaemonSet pods stay |
| --delete-emptydir-data | Allow evicting pods that use emptyDir volumes |
| --force | Evict pods not managed by a controller |
| --grace-period=<s> | Override pod termination grace period |
| --timeout=<dur> | Give up if eviction is not done in time |
| --disable-eviction | Delete pods directly, bypassing the Eviction API/PDBs |

## In CI

Use `--timeout` so an undrainable node fails the automation instead of hanging forever. Avoid `--disable-eviction` in shared clusters; it ignores PodDisruptionBudgets and can take a service below its minimum. Always pair drain with `kubectl uncordon` on success or rollback.

## Common errors in CI

"error: cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore)" is the most common; add the flag. "Cannot evict pod as it would violate the pod\'s disruption budget" means a PDB has no allowed disruptions right now; wait, scale up first, or rethink the budget. "cannot delete Pods with local storage (use --delete-emptydir-data ...)" means emptyDir pods need that flag.

## Using this in CI

A runner has no kubeconfig, no cached context, and no interactive auth. Every kubectl invocation in CI needs the context supplied explicitly, and most confusing CI failures here are the command running against the wrong cluster or no cluster at all.

```Terminal
# never rely on the ambient context on a runner
kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" get pods

# confirm what you are actually connected to before mutating anything
kubectl config current-context
kubectl cluster-info

# fail fast instead of hanging on an unreachable API server
kubectl --request-timeout=30s get nodes
```

> Always set `--request-timeout` in CI. Without it an unreachable API server hangs until the job times out, which turns a thirty-second failure into a twenty-minute one.

## FAQ

### kubectl drain: Evict Pods Before Node Work?

Before patching or terminating a node, drain moves the workloads off it, honoring PodDisruptionBudgets so availability is preserved.

### What it does?

kubectl drain first cordons the node (no new pods schedule there), then evicts the running pods via the Eviction API, which respects PodDisruptionBudgets. DaemonSet pods and bare (unmanaged) pods need explicit flags because drain refuses to evict them by default.

### In CI?

Use --timeout so an undrainable node fails the automation instead of hanging forever. Avoid --disable-eviction in shared clusters; it ignores PodDisruptionBudgets and can take a service below its minimum. Always pair drain with kubectl uncordon on success or rollback.

### Common errors in CI?

"error: cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore)" is the most common; add the flag. "Cannot evict pod as it would violate the pod\'s disruption budget" means a PDB has no allowed disruptions right now; wait, scale up first, or rethink the budget.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
