Prometheus WAL replay peklo: pomalý štart a chýbajúce alerty
Symptómy sú monitoring nočná mora:
- Prometheus pod je Running, ale nie Ready veľmi dlho.
- Alerty stíchnu (nie preto, že je všetko OK, ale preto, že sa nevyhodnocujú).
- Restart (node drain, upgrade, eviction) spraví 30–90 minút “blind spot”.
- V logoch je niečo ako “replaying WAL”.
Keď sa to deje, často to nie je sieť ani CPU. Je to startup práca TSDB: replay WAL, aby sa rebuildol in-memory head.
Testované na: Prometheus 2.48–2.53, Kubernetes 1.29–1.31, PV storage (rýchle SSD aj pomalšie network disky), high-churn clustre s remote_write.
Incident (anonymizovaný)
Mali sme plánovanú rotáciu nodov. Prometheus bol evictnutý a naschedulovaný inde. Pod nabehol rýchlo… a potom ostal NotReady.
V logoch WAL replay postupoval pomaly. Disk IO bolo pinned. Po 20 minútach prišlo OOMKilled a cyklus sa opakoval.
Root cause nebol “bug v Prometheovi”. Bola to kombinácia:
- veľký WAL (ingestion spike + churn)
- pomalý PV (vysoká IO latencia)
- príliš nízky memory limit na head rebuild počas replay
Constraint: potrebovali sme monitoring späť rýchlo, ale nechceli sme “fix” cez slepé mazanie dát a stratu dôkazov.
Timeline
- T-0: Prometheus restart počas node rotácie.
- T+5m: pod Running, ale NotReady; alerty sa nevyhodnocujú.
- T+10m: logy jasne ukazujú, že WAL replay dominuje štartu.
- T+20m: WAL adresár je obrovský; disk je saturovaný; pamäť rastie.
- T+30m: mitigácia: dočasne zvýšiť pamäť a znížiť ingestion tlak.
- T+60m: Prometheus je Ready; alerting sa vráti.
- T+1d: prevencia: ohraničiť churn, alerty na WAL size a restart duration, “time-to-ready” ako SLO.
Mechanizmus: prečo WAL replay dominuje štartu
Prometheus TSDB zapisuje recent samples do WAL. Pri štarte WAL segmenty replayuje, aby zrekonštruoval:
- aktívne series metadata
- in-memory chunk-y (head)
Je to pomalé alebo nestabilné, keď:
- WAL je obrovský
- disk je pomalý alebo saturuje
- churn je vysoký (veľa nových series)
- pamäťové limity sú príliš tesné
Nebezpečný loop:
- restart
- replay začne, pamäť rastie
- OOMKilled počas replay
- restart
- WAL stále veľký, repeat
Runbook: diagnostika WAL replay a bezpečné zotavenie
1) Potvrď, že je to WAL replay (nehádaj)
kubectl -n monitoring logs pod/<prometheus-pod> --since=60m | \
rg -n "WAL|replay|TSDB|corrupt|repair|head" | tail -n 200
Hľadáš:
- “replaying WAL”
- progres, ktorý sa skoro nehýbe
- OOM / corruption správy
2) Zmeraj veľkosť WAL
kubectl -n monitoring exec -it <prometheus-pod> -- sh -lc \
"du -sh /prometheus/wal /prometheus 2>/dev/null || true; ls -1 /prometheus/wal 2>/dev/null | wc -l || true"
Operatívne sú dôležité dva signály:
- WAL veľkosť
- počet segmentov
3) IO-bound vs memory-bound
Praktické heuristiky:
- IO-bound: replay ide pomaly, CPU nie je vysoké, IO latencia je vysoká
- memory-bound: RSS rastie a končí to OOMKilled
Ak máš prístup na node:
iostat -x 1 10
Ak nie, inferuj z typu PV a z OOM cyklov.
4) Prečo WAL narástol (skutočný root cause)
Najčastejšie je to niečo z tohto:
- high churn metriky (new series/min)
- kardinalita explózia (label blowup)
- remote_write backpressure a amplifikácia ingestionu
- pomalý disk, ktorý nestíha truncation/compaction
WAL je v praxi “daňový doklad” na tvoj monitoring budget.
Bezpečné mitigácie (vyber najmenej invazívnu)
1) Dočasne zvýš memory limity
WAL replay potrebuje headroom nad steady-state. Ak sizing robíš len na steady-state, replay bude padať.
Reprezentatívny bump:
resources:
requests:
memory: "4Gi"
limits:
memory: "6Gi"
2) Dočasne zníž ingestion
Ak je WAL obrovský a replay pomalý, niekedy musíš znížiť load, aby to dobehlo:
- zvýšiť scrape interval pre noisiest joby
- dočasne vypnúť najhorších vinníkov
- drop low-value metriky cez relabeling (najmä high-churn labely)
3) TSDB na rýchlejší storage (plánovaný fix)
Ak je replay IO-bound, je to storage problém. Rýchly disk je rozdiel minúty vs hodiny.
4) Last resort: zmazať WAL
Zmazanie WAL dokáže Prometheus postaviť rýchlo, ale je to data loss by design.
Ak to musíš spraviť:
- ak sa dá, sprav snapshot TSDB dir
- zdokumentuj presne, čo si zmazal a prečo
Čo sme zmenili (konkrétne)
1) “Time-to-ready” ako SLO
Napísali sme kontrakt:
- po restarte musí byť Prometheus Ready do N minút
Keď to poruší, je to incident (monitoring je produkčná závislosť).
2) Zníženie churnu pri zdroji
Label budgety a churn kontrola znížili:
- WAL growth rate
- replay memory footprint
- variabilitu štartu
3) Headroom pre replay peaks
Zvýšili sme pamäťový headroom a vyhli sa “tesným limitom” na tej inštancii, ktorá sa musí rýchlo zotaviť.
4) Alerty ešte predtým, než sme slepí
Guardrails, ktoré reálne používame:
- “Prometheus NotReady viac než X minút”
- WAL size nad threshold
- new series/min nad threshold
Ako verifikovať
- Prometheus je Ready v budgete po kontrolovanom restarte.
- WAL size je bounded v steady-state.
- Počas node drainov nie je alerting slepý dlhé okná.
Súvisiace čítanie
- Prometheus remote_write backpressure: keď monitoring zaplní disk a ešte aj stratí dáta
- Prometheus Kardinalita Explózia: Detekcia, Prevencia a Obnova
- Cardinality Contracts: sprav z Prometheus labelov API s budgetom
- Dash Contracts v Go: CI kompilator pre Grafana dashboardy a Prometheus alerty
- Linux Page Cache Thrashing v Kontajneroch: Keď Voľná Pamäť Nie Je Voľná
- Structured Logging Performance: Keď Sa Logger Stane Bottleneckom
Súvisiace články
Prometheus native histogramy v produkcii: rollout plán, budgety a failure módy
Prometheus native histogramy vedia odpáliť pamäť, WAL aj remote_write. Návod na postupné nasadenie, budgety a konkrétne queries na verifikáciu.
eBPF Off-CPU Analýza: Nájdenie Latencie Ktorú Metriky Nevidia
CPU je na 20% ale latencia je 500ms. Štandardné profilery neukazujú nič. Appka čaká, nepočíta. Ukážem ako použiť eBPF na nájdenie na čo čaká.
Prometheus Kardinalita Explózia: Detekcia, Prevencia a Obnova
Jeden developer pridal user_id label. Prometheus dostal OOM. Ukážem ako detekovať high-cardinality metriky skôr než zabiajú monitoring, s relabel configami na ich drop.
tcpdump vidí SYN, ale služba timeoutuje: pasca listen backlogu
Klienti timeoutujú, tcpdump ukazuje SYN (niekedy aj SYN-ACK), ale aplikácia nič neloguje. Častý vinník: Linux listen/accept fronty, ktoré sa pri load-e alebo CPU starvation preplnia.
Citujte tento článok
Ak na článok odkazujete, pridajte pôvodnú URL a uveďte autora.