From requests and limits, Kubernetes 5,150 files every Pod into a QoS class, recorded in status.qosClass:
| Class | Rule | Under memory pressure |
|---|---|---|
| Guaranteed | Every container's CPU and memory limits equal its requests | Evicted last |
| Burstable | Some request or limit, but not Guaranteed | By usage above request |
| BestEffort | No requests or limits at all | Evicted first |
If the kernel's OOM killer strikes before the kubelet evicts, the class still steers it, through oom_score_adj:
kubectl apply -f - <<'EOF' >/dev/null
apiVersion: v1
kind: Pod
metadata: { name: guaranteed }
spec:
containers:
- { name: c, image: localhost:33500/booknest-api:1.4, command: [sleep, infinity],
resources: { limits: { cpu: 250m, memory: 64Mi } } }
EOF
kubectl wait --for=condition=Ready pod/guaranteed >/dev/null
A=$(kubectl get pod -l tier=api -o jsonpath='{.items[0].metadata.name}')
for p in guaranteed $A postgres-0; do
echo "$p $(kubectl get pod $p -o jsonpath='{.status.qosClass}')" \
"$(kubectl exec $p -- cat /proc/1/oom_score_adj)"
doneOutput
guaranteed Guaranteed -997 api-776c666c56-28p22 Burstable 999 postgres-0 BestEffort 1000
The test Pod's limits became its requests too. PostgreSQL 1,289 , with no resources, is first to go; Tuning Probes fixes that.