Späť na blog

Ephemeral-storage evictions v Kubernetes: logová búrka, ktorá vyhodila zdravé pody

Ak ste to ešte nezažili, znie to ako bug:

  • pody restartujú s dôvodom Evicted
  • správa hovorí “node was low on resource: ephemeral-storage”
  • prihlásite sa na node, df -h a… disk vyzerá voľný

Prvýkrát som si myslel, že kubelet je pokazený. Nebol. Boli sme to my.

Toto je runbook, ktorý mi vtedy chýbal: nodefs vs imagefs, rast logov, kubelet garbage collection a ephemeral-storage ako kontrakt.

Testované na: Kubernetes 1.29–1.31, containerd 1.7, Linux 6.1–6.6, mix nodefs/imagefs setupov.

Incident (anonymizovaný)

Počas produkčného incidentu som zapol veľmi verbose logging v jednej službe, aby som chytil raritný edge case. Incident skončil. Debug logging nie.

O pár hodín:

  • kontajner logy narástli na desiatky GB na časti nodov
  • kubelet nastavil DiskPressure
  • začali evictions — aj na úplne nesúvisiacich službách
  • rollouty boli noisy, lebo evictions vyzerali ako “random restarty”

Blast radius: viacero služieb malo vyšší error rate kvôli restartom a cold cache.

Constraint: nemohli sme odstaviť node pool. Potrebovali sme zastaviť krvácanie a pridať guardrails, aby sa “debug logging” už nikdy nezmenil na cluster incident.

Timeline

  • T-0: alerty: rastú restarty podov naprieč namespace.
  • T+10m: kubectl describe pod ukáže Evicted a “low on ephemeral-storage”.
  • T+20m: kubectl describe node ukáže DiskPressure=True na rovnakých nodoch.
  • T+30m: na node du odhalí, že /var/log/containers dominuje rast.
  • T+40m: mitigácia: znížiť verbosity + reštart noisy podov + drain najhorších nodov.
  • T+2h: DiskPressure zmizne; evictions prestanú.
  • T+1d: vynútime log rotáciu v kubelete + per-pod ephemeral-storage limity + alerty.

Mechanizmus: prečo “disk vyzerá voľný”, ale kubelet evictuje

Kubelet evictuje podľa thresholdov, nie až pri 100% plnosti

Eviction sa spúšťa pri prekročení/priblížení sa ku thresholdom (evictionHard, evictionSoft) a sleduje konkrétne filesystemy:

  • nodefs (root FS; často tu žijú logy a emptyDir)
  • imagefs (images/snapshots; môže byť samostatná partícia)

Takže môžete mať:

  • voľno na /, ale imagefs je plný
  • alebo naopak
  • alebo “voľno celkovo”, ale pod hard thresholdom kubeletu

Container logy sú ephemeral-storage

Logy žijú na node (typicky /var/log/containers a /var/log/pods). Bez kubelet-level rotácie vám jeden chatty kontajner zožerie disk až do DiskPressure a evictionov.

Evictions nie sú “graceful”, ak ste ich nenavrhovali

Pod dostane SIGTERM. Ak nemáte graceful shutdown, uvidíte:

  • user-visible chyby
  • connection storm po restartoch
  • nestabilné rollouty

Runbook: diagnostika a zastavenie evictionov

Čo skontrolovať ako prvé

  1. Potvrdiť dôvod
kubectl -n <ns> describe pod <pod>

Hľadajte:

  • Reason: Evicted
  • “low on resource: ephemeral-storage”
  • niekedy aj usage per container
  1. Nájsť node a node condition
kubectl get pod -n <ns> <pod> -o wide
kubectl describe node <node> | grep -n "DiskPressure" -n
  1. Rozlíšiť nodefs vs imagefs Na node (alebo cez kubectl debug node/...):
df -h
df -h /var/log
df -h /var/lib/containerd

Ako potvrdiť hypotézu (rýchla forenzika disku)

A. Čo žerie nodefs (logy, emptyDir, tmp)

sudo du -xh /var/log | sort -h | tail -n 20
sudo du -xh /var/log/containers | sort -h | tail -n 20
sudo du -xh /var/log/pods | sort -h | tail -n 20

B. Čo žerie imagefs (images/snapshots)

sudo du -xh /var/lib/containerd | sort -h | tail -n 20

C. Namapovať veľký log na konkrétny pod Súbor v /var/log/containers typicky obsahuje názov podu v názve.

Bezpečné mitigácie

  1. Vypnúť log firehose
  • revert debug logging
  • obmedziť per-request logovanie
  • znížiť log volume na zdroji
  1. Drain najhorších nodov Je to často bezpečnejšie než “ručné mazanie” v containerd.
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
  1. Zapnúť log rotáciu v kubelete Toto je reálna oprava.

  2. Pridať ephemeral-storage requests/limits Aby jeden pod nemohol ticho zožrať disk.

Rizikové mitigácie

  • ručné mazanie v /var/lib/containerd bez pochopenia containerd GC
  • “rm -rf” snapshot/overlay adresárov
  • náhodný restart containerd na horúcom node (vie spustiť ďalšiu vlnu problémov)

Čo sme zmenili (konkrétne)

1) Vynútená kubelet log rotácia

KubeletConfiguration snippet:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
containerLogMaxSize: "50Mi"
containerLogMaxFiles: 5

2) Ephemeral-storage ako kontrakt pre noisy službu

Predtým (bez budgetu):

resources:
  requests:
    cpu: "200m"
    memory: "256Mi"
  limits:
    cpu: "1"
    memory: "512Mi"

Potom:

resources:
  requests:
    cpu: "200m"
    memory: "256Mi"
    ephemeral-storage: "512Mi"
  limits:
    cpu: "1"
    memory: "512Mi"
    ephemeral-storage: "2Gi"

3) Guardrail proti “debug logging navždy”

  • debug režim auto-expiruje po čase
  • CI check failne build, ak je debug default v produkčných configoch

Ako verifikovať

  1. DiskPressure zmizne
kubectl describe node <node> | grep -n "DiskPressure" -n
  1. Nevznikajú nové evictions
kubectl get events -A --sort-by=.metadata.creationTimestamp | tail -n 50
  1. Log adresáre nerastú bez limitu Na node:
sudo du -sh /var/log/containers
  1. Workload sa stabilizuje
  • restarty späť na baseline
  • SLO bez periodických spikes

Prevencia / guardrails

  • Ephemeral-storage budgety
    • definovať pre kritické workloady
    • vynucovať (šablóny, policy, review)
  • Alerty na disk
    • nodefs a imagefs utilization
    • growth rate alerty sú praktickejšie než absolútne %
  • Logging budgety
    • max logov na request
    • sampling v produkcii
  • Graceful shutdown
    • aj pri eviction má byť dopad na užívateľa minimálny

Súvisiace čítanie

Súvisiace články

Citujte tento článok

Ak na článok odkazujete, pridajte pôvodnú URL a uveďte autora.

Michal Drozd. "Ephemeral-storage evictions v Kubernetes: logová búrka, ktorá vyhodila zdravé pody". https://www.michal-drozd.com/sk/blog/kubernetes-ephemeral-storage-eviction-logova-burka/ (Publikované 18. novembra 2025).