KubernetesXIII · Kubernetes QoS ClassesKubernetes QoS classes
Eviction order and QoS — node pressure and pod survival
What you'll learn
- Explain the kubelet's eviction algorithm under node pressure
- Identify the eviction signals (memory, disk, inodes, PIDs)
- Tune eviction thresholds to match the workload
- Reason about QoS-based eviction and its limits
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
The kubelet’s eviction algorithm is what protects nodes from running out of memory, disk, or PIDs. This lesson covers the algorithm, the eviction signals, and how to tune thresholds to match production workloads.
The eviction algorithm
flowchart TD
Monitor[Kubelet monitors node resources] --> Threshold{Threshold crossed?}
Threshold -- no --> Monitor
Threshold -- yes --> Soft{Soft threshold?}
Soft -- yes --> Grace[Wait grace period]
Soft -- no --> Act[Act immediately]
Grace --> Persistent{Pressure persists?}
Persistent -- no --> Reset[Reset; no eviction]
Persistent -- yes --> Act
Act --> Sort[Sort Pods by QoS + usage]
Sort --> Evict[Evict Pods until pressure relieved]
Evict --> Monitor
The kubelet:
- Monitors node resources (memory, disk, inodes, imagefs, PIDs).
- Detects when a resource crosses an eviction threshold.
- For soft thresholds, waits the grace period to see if pressure resolves.
- Sorts Pods by QoS class and usage vs request.
- Evicts Pods one at a time until pressure is relieved.
- Repeats until resource is above threshold.
The pressure relief loop is important: the kubelet evicts the minimum number of Pods needed to bring the resource above threshold.
Eviction signals
The kubelet watches these signals:
| Signal | Description |
|---|---|
memory.available | Memory available for new allocations |
nodefs.available | Filesystem space available on the node’s root disk |
nodefs.inodesFree | Inodes free on the root disk |
imagefs.available | Filesystem space on the image filesystem (containerd/CRI-O) |
imagefs.inodesFree | Inodes free on the image filesystem |
pid.available | PIDs available on the node |
evictionHard:
memory.available: 500Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
imagefs.available: 15%
pid.available: 10%
The eviction order: QoS first
Within the eviction loop, Pods are sorted by:
- QoS class: BestEffort first, Burstable second, Guaranteed last.
- Within Burstable: Pods with the highest
usage / requestratio are evicted first. - Within Guaranteed: same logic, but Guaranteed Pods are evicted last overall.
flowchart TD
Sort[Sort Pods] --> Q1{QoS?}
Q1 -- BestEffort --> S1[Sort by absolute usage descending]
Q1 -- Burstable --> S2[Sort by usage/request ratio descending]
Q1 -- Guaranteed --> S3[Sort by usage/request ratio descending]
S1 --> Evict[Evict in order]
S2 --> Evict
S3 --> Evict
For a node with 30% memory pressure:
- All BestEffort Pods are evicted first (regardless of usage).
- Then Burstable Pods with the highest usage-vs-request ratio.
- If still under pressure, Guaranteed Pods with the highest ratio.
Hard vs soft thresholds
Two threshold types:
- Hard (
evictionHard): when the threshold is crossed, the kubelet evicts immediately. No grace period. - Soft (
evictionSoft): when the threshold is crossed, the kubelet waits the grace period. If pressure resolves during the grace period, no eviction. If not, eviction proceeds.
evictionHard:
memory.available: 500Mi
evictionSoft:
memory.available: 1Gi
evictionSoftGracePeriod:
memory.available: 30s
The pattern:
- Hard threshold: the safety net. When memory is critically low, evict immediately.
- Soft threshold: early warning. When memory is getting low, give the workload 30s to recover (e.g., a garbage collection cycle).
Tuning eviction thresholds
Production discipline:
- Memory hard threshold: 500Mi-1Gi. Lower means earlier eviction but more Pods lost; higher means later eviction but more risk of OOMKill.
- Memory soft threshold: 1-2Gi. Earlier warning with grace period.
- Disk hard threshold: 10-15%. Lower means earlier
eviction when
emptyDirfills. - Imagefs hard threshold: 15-20%. The image filesystem fills up with cached image layers; eviction cleans the cache.
evictionHard:
memory.available: 500Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
imagefs.available: 15%
pid.available: 10%
evictionSoft:
memory.available: 1Gi
nodefs.available: 15%
evictionSoftGracePeriod:
memory.available: 30s
nodefs.available: 30s
Eviction signals in alerts
# Node has memory pressure condition
kube_node_status_condition{condition="MemoryPressure",status="true"} == 1
# Node has disk pressure condition
kube_node_status_condition{condition="DiskPressure",status="true"} == 1
# Pods evicted in last hour
increase(kube_pod_container_status_last_terminated_reason{reason="Evicted"}[1h])
Production discipline: alert on MemoryPressure and DiskPressure conditions; track eviction rates per node.
The kubelet eviction manager
The eviction manager runs as part of the kubelet:
- Reads the kubelet config for thresholds.
- Polls node resources (memory.available, nodefs.available, etc.).
- Triggers eviction when thresholds are crossed.
- Logs each eviction with the reason and the Pod’s QoS.
journalctl -u kubelet | grep -i evict
# I0815 12:00:00.123 ... eviction manager: must evict pod(s) to reclaim memory
# I0815 12:00:01.456 ... eviction manager: pod web-7c8 (QoS: Burstable) is evicted
The kubelet logs are the ground truth for what was evicted and why.
Production patterns
Set eviction thresholds in the kubelet config:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
evictionHard:
memory.available: 500Mi
nodefs.available: 10%
evictionSoft:
memory.available: 1Gi
evictionSoftGracePeriod:
memory.available: 30s
Use node-level alerts:
- alert: NodeMemoryPressure
expr: kube_node_status_condition{condition="MemoryPressure",status="true"} == 1
for: 5m
labels:
severity: warning
- alert: HighEvictionRate
expr: increase(kube_pod_container_status_last_terminated_reason{reason="Evicted"}[1h]) > 5
labels:
severity: warning
Investigate evicted Pods:
kubectl get pods -A --field-selector=status.reason=Evicted
# Identify Pods that were evicted; check their QoS and usage
Cross-course references
- The Linux course part
XXXVII-Linux-Resourcescovers cgroup OOM and node memory pressure; eviction is the cluster-level equivalent. - The Ansible course part
XXXV-Ansible-Scriptingcovers service priority; QoS-based eviction is the cluster-level equivalent. - The Observability course part
LXXXIV-Kubernetes-CapacityPlanningcovers capacity planning; eviction is the response to capacity planning failures.
Quiz
Knowledge check · 4 questions
Q1. Under sustained memory pressure, in what order does the kubelet evict Pods?
Q2. Soft eviction thresholds give the workload a grace period to recover before eviction proceeds.
Q3. A team's cluster has multiple Burstable Pods that all burst to 4Gi memory. The kubelet evicts them under memory pressure. Walk through the diagnosis and the fix.
Cluster: 5 nodes, each with 16Gi memory. 50 Burstable Pods, each with `requests.memory: 1Gi, limits.memory: 4Gi`. Under traffic, all 50 burst to 4Gi (200Gi total demand). Nodes have 16Gi each but only 5-6Gi allocatable per node after reservations. Memory pressure triggers eviction.
Q4. How do you decide on the right value for `evictionHard.memory.available`?
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Set both hard and soft eviction thresholds. Soft gives grace periods; hard is the safety net.
- Tune thresholds to match workload peak. Memory threshold must be below the workload’s peak burst.
- Monitor MemoryPressure and DiskPressure conditions. These signal that the kubelet has begun eviction.
- Track eviction rates per node. High eviction rates indicate over-commitment or workload issues.
- Plan capacity so Guaranteed Pods are not at risk. QoS is the order, not a guarantee.