Kubernetes pods "Evicted": find the pressure on the node, and stop it from coming back
Fix Kubernetes pods with status Evicted: read why with describe, handle DiskPressure and MemoryPressure on the node, clean up, set requests and limits, delete old pods.
by OhSudo ··
Not sure this is your cause?Find it step by step: Pod not running →Find it step by step: Disk full or out of memory →
Part of a learning path:Kubernetes: debugging pods
$ kubectl get podsNAME READY STATUS RESTARTS AGEmyapp-7d9f8b6c4-x2k9p 0/1 Evicted 0 2hmyapp-7d9f8b6c4-b7m4q 0/1 Evicted 0 2hmyapp-7d9f8b6c4-t9n2c 1/1 Running 0 3mA node ran short of disk or memory, and the kubelet removed pods to protect the node. A Deployment simply starts replacements somewhere else, so your application may look fine, with a growing list of dead pods behind it.
Those pods aren’t the problem. The node is. Clearing them up without looking at why just means more of them later.
- Nodedisk or memory runs short(breaks here)pressure(fails)
- kubeletevicts podsleaves
- Evicted podsreplacements start elsewhere
TL;DR
1. Read why
Status: FailedReason: EvictedMessage: The node was low on resource: ephemeral-storage. Threshold quantity: 5251858022, available: 4029804Ki. Container myapp was using 4Gi, request is 0, has larger consumption of ephemeral-storage.The message says what ran short, and which container used a lot of it. The threshold is in bytes: here, the default 10% of the node’s disk. Across the namespace:
Events only last about an hour by default, while the pod’s message stays for as long as the pod does. So don’t delete them before you’ve read one.
| Message mentions | Means | Go to |
|---|---|---|
ephemeral-storage, nodefs, imagefs |
Disk | Section 2 |
memory |
Memory | Section 3 |
pid |
Too many processes | Section 4 |
No shortage named, The node had condition |
A taint or node condition | Section 5 |
2. DiskPressure
DiskPressure True KubeletHasDiskPressure kubelet has disk pressureThe kubelet’s default hard limits are nodefs.available<10% and imagefs.available<15%, among others. See what’s using the disk, on the node itself, through a debug pod:
kubectl debug node/worker-2 -it --image=ubuntuchroot /hostdf -hdu -xh --max-depth=1 /var/lib | sort -h | tailcrictl imagesThree usual causes:
Container logs. An application that writes a lot to stdout fills /var/log/pods. Limit them with containerLogMaxSize and containerLogMaxFiles in the kubelet config, and make the application less talkative.
Writable layers and emptyDir. An application writing into its own filesystem, such as temp files or caches, counts as ephemeral storage. Find the biggest:
kubectl get --raw "/api/v1/nodes/worker-2/proxy/stats/summary" | \ python3 -c 'import json,sys; [print(p["ephemeral-storage"]["usedBytes"]//1048576, "MiB", p["podRef"]["name"]) for p in json.load(sys.stdin)["pods"]]' | sort -n | tailUnused images. The kubelet cleans those itself, and sudo crictl rmi --prune does it now. A CI node that builds images needs this most.
No space left on device has more on hunting down space on a Linux machine. Then either make the disk bigger, or set limits, as in section 6.
3. MemoryPressure
kubectl describe node worker-2 | grep MemoryPressurekubectl top nodeskubectl top pods -A --sort-by=memory | head -n 15When memory’s short, the kubelet evicts in this order, roughly: pods using more than they requested go first, and among those, by priority and how far above the request they are. So a pod with no requests at all is an easy target.
Memory shortage can also bring in the kernel’s OOM killer, which ends one process rather than the pod. That shows up as OOMKilled, with exit code 137: see that article.
4. PIDPressure
Something’s creating processes without limit, often a process that doesn’t clean up its children. Find it on the node with ps -eLf | wc -l and ps aux --sort=-nlwp | head. An init process in the container, or podSpec.shareProcessNamespace, may help with zombies.
5. Other reasons pods get removed
Not everything that’s removed is evicted by pressure:
- Preempted: a higher-priority pod needed the room. The message says so.
- The API or
kubectl drain: a planned action, and it respects PodDisruptionBudgets. - Node shutdown: spot or preemptible nodes being reclaimed.
- Over its own limit: a pod exceeding its
ephemeral-storagelimit is evicted even though the node is fine, with a message such asPod ephemeral local storage usage exceeds the total limit of containers.
6. Set requests and limits
This is the lasting fix. Requests make the scheduler place pods where they fit, and lower their position in the eviction queue:
resources: requests: cpu: 100m memory: 256Mi ephemeral-storage: 1Gi limits: memory: 512Mi ephemeral-storage: 2GiSet them from real use, as seen in kubectl top, rather than guessing. The Kubernetes Manifest Generator includes CPU and memory requests by default. For temp files, limit that as well:
volumes: - name: tmp emptyDir: sizeLimit: 1GiImportant workloads can have a higher priority with a PriorityClass. And add monitoring for node disk and memory, as it’s easy not to notice pods being replaced.
7. Clean up the dead pods
Evicted pods stay around so that you can read why. They use no resources besides an API object. Remove them when you’re done:
kubectl delete pods --field-selector=status.phase=Failedkubectl delete pods -A --field-selector=status.phase=FailedThe first is for one namespace, and the second for all. Note that this removes all failed pods, including those from other failures, which you may want to look at first. Kubernetes only cleans them up by itself after a high count, 12,500 by default.
Warning
Raising the eviction thresholds, or turning them off, doesn’t add any disk or memory. Then the node itself runs out: the kubelet or the container runtime can stop working, and the node goes NotReady, taking down every pod on it. Evictions are the mild version of that failure.
Shell, we have a problem!
Similar, but different: Pending with Insufficient cpu means nothing has room for a new pod. Exit code 137 and OOMKilled mean the container hit a memory limit. NodeNotReady means the node’s stopped reporting. ImageGCFailed in events means the kubelet couldn’t free enough image space, and it comes with DiskPressure.
$ ./practice.sh
Practice this in the terminal
Open the Terminal Playground with this article’s scenario loaded. It is safe and runs in your browser.
Found this useful? Share it.
Found a mistake? Let us know at contact@ohsudo.com.