,

systemd sin OOM-killer drepte de langvarige sesjonene mine

systemd sin OOM-killer drepte de langvarige sesjonene mine

En tjeneste som hadde gått lenge, med aktive sesjoner, forsvant plutselig midt i drift. Applikasjonen hadde ikke krasjet, det lå ingen feil i mine egne logger. Prosessen var rett og slett borte. Sånt lukter minnepress og kjernens OOM-håndtering lang vei, så det var der jeg begynte å lete.

Bekreft årsaken i loggen

Skjematisk diagram: systemd-oomd overvåker flere cgroups under minnepress og velger den med høyest press som drapsoffer

Ikke gjett. Sjekk om det faktisk var systemd-oomd som tok prosessen. Under minnepress går oomd gjennom cgroupene og dreper der presset er høyest, helt uavhengig av om kjernens gamle OOM-killer har rukket å slå til.

journalctl -k --grep "Out of memory|oom-kill"
journalctl -u systemd-oomd --since "-1h"
systemctl status systemd-oomd

Ser du meldinger fra systemd-oomd om at en cgroup ble drept, eller Killed process i kjerneloggen, så har du svaret. Da kan du gjøre noe presist, i stedet for å skru på grenser i blinde og håpe.

Feil fiks: bare heve grenser

Det fristende er å doble MemoryMax eller skru av swap-oppførselen. Men det flytter bare problemet et hakk lenger frem. Under ekte press må noe fortsatt vike, og uten instruksjon plukker oomd selv. Poenget er ikke å kaste mer minne på det. Poenget er å fortelle systemet hvilke prosesser som kan ofres, og hvilke som absolutt ikke kan det.

Riktig fiks: marker hva som må overleve

Skjematisk flytdiagram: ManagedOOMPreference avoid, omit og standard styrer hvilken cgroup oomd velger som offer

systemd lar deg sette en preferanse per unit. ManagedOOMPreference=avoid ber oomd om å nedprioritere akkurat denne cgroupen når et offer skal velges. Sett den på unit-en som holder de langvarige sesjonene, den du helst vil ha i fred.

[Service]
ManagedOOMPreference=avoid

Legg det i en drop-in, så overlever det når pakken oppgraderes.

systemctl edit min-tjeneste.service
# i editoren:
[Service]
ManagedOOMPreference=avoid

systemctl daemon-reload
systemctl restart min-tjeneste.service

Sjekk så at preferansen faktisk ble lest inn.

systemctl show min-tjeneste.service -p ManagedOOMPreference

Motsatt vei kan du sette ManagedOOMPreference=omit på batch-jobber og annet som gjerne kan ryke først. Da gir du kjernen og oomd nok å gå på til å velge et fornuftig offer, i stedet for å ta det på slump.

Par det med auto-resume

En preferanse er ingen garanti. Blir alt minnet spist opp, ryker det noe uansett. Derfor må du sørge for at tjenesten kommer tilbake på egen hånd.

[Service]
Restart=always
RestartSec=5

[Unit]
StartLimitIntervalSec=0

Har tjenesten sesjonstilstand som må hentes tilbake, la den lese tilstanden fra disk ved oppstart, slik at aktive sesjoner plukkes opp igjen etter en restart.

Oppsummert

  • Bekreft i journalctl at det virkelig var oomd, og ikke applikasjonen selv.
  • Marker eksplisitt hva som må overleve, med ManagedOOMPreference=avoid.
  • Merk de ofrbare prosessene med omit, så oomd har et bedre offer for hånden.
  • Par det med Restart=always og gjenoppretting av tilstand.

Å skille det som kan ofres fra det som ikke kan det, er hele poenget her. Grenser alene løser det ikke.


Trenger du hjelp med dette?

Ta kontakt for en uforpliktende prat om hvordan jeg kan hjelpe deg.

Navn