Node Pressure and Pod Evictions
Introduction¶
A Kubernetes node has finite memory, disk, and process slots. When one gets scarce, the kubelet proactively evicts pods to reclaim it before the whole node falls over. Understanding the mechanism lets you protect what matters.
The signals¶
The kubelet watches:
| Signal | Default hard threshold | Reclaims by |
|---|---|---|
memory.available |
< 100Mi |
evicting pods |
nodefs.available |
< 10% |
evicting pods, deleting images/containers |
nodefs.inodesFree |
< 5% |
same |
imagefs.available |
< 15% |
deleting unused images first, then evicting |
pid.available |
configurable | evicting pods |
Soft thresholds add an eviction-soft-grace-period (gentle, respects pod
grace period). Hard thresholds evict immediately (grace period 0). Config is
in the kubelet (--eviction-hard, --eviction-soft, or the KubeletConfiguration).
Eviction order¶
Under memory pressure, the kubelet ranks pods by:
- Whether the pod exceeds its memory requests — pods using more than they requested go first.
- Pod Priority (
priorityClassName) — lower priority first. - How much the pod exceeds requests — biggest offender first.
Practical consequence of QoS:
- BestEffort (no requests/limits) — evicted first, always over "request".
- Burstable — evicted when using more than requested.
- Guaranteed (requests == limits) — evicted last, only under extreme pressure or if exceeding limits (which for Guaranteed means OOMKill anyway).
Disk pressure is different: it first deletes dead containers and unused images, then evicts pods (ranked by local disk usage vs requests, then priority).
Eviction vs OOMKill¶
- Eviction — the kubelet removes the pod gracefully-ish; the pod object
gets
status.reason: Evictedand stays around (a tombstone) until cleaned up. A controller reschedules it elsewhere. - OOMKill — the Linux kernel kills a process because a cgroup hit its memory limit. Just that container, restarted in place.
You can hit both: node memory pressure evicts pods; a single pod exceeding its limit gets OOMKilled without any node pressure.
Preventing the wrong evictions¶
- Set requests on everything. A pod with no memory request is BestEffort and first to die, even if it's important.
- Set memory request == limit for critical workloads (Guaranteed QoS).
- PriorityClasses — give system/critical workloads a high
priorityClassName;system-cluster-critical/system-node-criticalexist for add-ons. - Reserve resources for the system:
--system-reserved/--kube-reservedso the kubelet's math leaves headroom for the OS and container runtime. - Pod Disruption Budgets don't stop node-pressure evictions (those are involuntary) but do protect against voluntary disruptions like drains.
- Right-size so nodes aren't chronically near the threshold.
Verification and troubleshooting¶
kubectl describe node node-1 | grep -A10 Conditions # MemoryPressure/DiskPressure/PIDPressure
kubectl get events -A --field-selector reason=Evicted
kubectl get pods -A --field-selector status.phase=Failed | grep Evicted
kubectl describe pod evicted-pod | grep -A3 Status
journalctl -u kubelet | grep -i evict # on the node
df -h /var/lib/containerd /var/lib/kubelet # disk pressure source
- Pods repeatedly evicted and rescheduled onto the same node — the node is chronically over-committed; the replacement lands there and gets evicted too. Fix requests, cordon and investigate, or add capacity.
DiskPressurewith plenty ofdfspace — inodes (df -i), or it'simagefs(a separate filesystem for images) that's full, notnodefs.- Lots of
Evictedtombstone pods piling up — kubelet doesn't garbage collect them by default below a threshold.kubectl delete pod --field-selector status.phase=Failed -A, or set--pod-eviction-timeout/ a cleanup job. - Critical add-on (CNI, CSI) evicted — it lacks a
system-node-criticalpriority class. Add one. - Node flaps
NotReadyunder load — pressure so severe the kubelet itself is starved; increase--kube-reserved/--system-reservedand lower the max pods per node. - Eviction storm across the cluster — a memory leak in a DaemonSet hits every node at once. Roll it back; the fix isn't in eviction config.
Related tools and reading¶
- On-site: YAML validator.
- Related posts: Requests vs limits and OOMKilled, Disk full but df says otherwise.
Stuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.More in Docker & Kubernetes
StatefulSets Explained
StatefulSets give pods sticky names, sticky storage, and ordered operations — what databases and clustered apps need. Here's how each guarantee works.
October 24, 2026Persistent Volumes and Claims, Explained
PVC is a request, PV is the fulfilled storage, StorageClass is the factory. Most 'Pending PVC' problems are an access-mode or provisioner mismatch.
October 24, 2026Kubernetes Jobs and CronJobs
A Job runs pods until they succeed; a CronJob creates Jobs on a schedule. Here's parallelism, retry limits, the missed-schedule trap, and history cleanup.
October 24, 2026