...

OOM Killer begrijpen: wanneer Linux processen beëindigt

In dit artikel wordt uitgelegd hoe de oom killer linux ingrijpt bij acute knelpunten in het werkgeheugen en waarom hij diensten geforceerd beëindigt om de server operationeel te houden. Ik laat stap voor stap zien hoe ik triggers herken, de score begrijp en met gerichte instellingen het gedrag onder geheugendruk beïnvloed.

Centrale punten

  • Trekker: OOM-gebeurtenissen treden op wanneer het RAM-geheugen vol is, de swapruimte op is en pogingen tot terugwinning mislukken.
  • Scores: De kernel wijst een oom_score en beëindigt processen die veel geheugen in beslag nemen.
  • Erkenning: Aanwijzingen zijn te vinden in dmesg met „Out of memory“ en „Killed process“.
  • BesturingssysteemMet oom_score_adj Ik rangschik diensten doelgericht op basis van belangrijkheid.
  • Preventie: Monitoring, limieten, swappstrategie en lek-analyse voorkomen harde kills.

Wat is de OOM-killer in de Linux-kernel?

De OOM Killer is de laatste Veiligheidslijn van de kernel en beëindigt processen wanneer er geen geheugenpagina’s meer beschikbaar zijn. Ik beschouw het als een gecontroleerde noodstop die een totale uitval voorkomt en onmiddellijk RAM vrijmaakt. Eerst probeert het systeem pagina’s te swappen of caches te legen, maar bij aanhoudende druk blijft alleen nog de harde afsluiting over. In logbestanden herken ik dit moment aan vermeldingen met „Out of memory“ en „Killed process“, vaak vergezeld van een SIGKILL. Deze functie is standaard ingeschakeld en wordt automatisch uitgevoerd, wat in productieomgevingen vaak voor verrassingen zorgt wanneer belangrijke diensten zonder waarschuwing verdwijnen.

Wanneer treedt het mechanisme in werking?

OOM-gebeurtenissen doen zich voor wanneer het fysieke RAM bijna volledig bezet is, de swap geen buffer meer biedt en verzoeken om nieuwe pagina’s mislukken. In deze situatie beoordeelt de kernel of er ruimte kan worden vrijgemaakt uit de Pagina cache en swapping nog helpt, en pas wanneer de situatie uitzichtloos is, wordt de killer gestart. Kortstondige pieken activeren het mechanisme niet direct; er is aanhoudende druk en tevergeefse pogingen tot vrijgave voor nodig. Voor de analyse helpt het mij om te kijken naar RSS, swapgebruik, het aandeel van de paginacache en de toewijzingen per controlegroep. Wie dieper wil begrijpen hoe cacheverdringing werkt, kan de achtergronden bij Verwijdering uit de paginacache bekijken en de effecten in het eigen systeem meten.

Hoe kiest de kernel het „slachtoffer“?

De selectie volgt een Scores, dat Linux als oom_score per proces berekend. Een groot aandeel in het totale geheugen, veel RSS en een niet-kritieke rol leiden tot een hogere score. Systeemgerelateerde processen zoals init krijgen een korting, terwijl geheugenintensieve worker-processen of caches vaak bovenaan staan. Via oom_score_adj kan ik de score doelgericht aanpassen en zo de reeks van slachtoffers sturen. Meestal beëindigt de kernel het proces met de hoogste score via SIGKILL, om in één klap zoveel mogelijk RAM vrij te maken.

Sporen herkennen: logbestanden en signalen

Na een plotselinge beëindiging van mijn dienst controleer ik eerst dmesg en de kernel-logs. Als daar „Out of memory“ en „Killed process“ verschijnen, noteer ik de PID, de procesnaam, de gebruiker en de berekende score. Vaak ontbreekt er in de applicatie zelf een foutlog, omdat SIGKILL geen opruimfase toestaat. Ik vergelijk het tijdstip met de monitoringgegevens om de toename van RAM, swap en RSS per proces te traceren. Zo identificeer ik op betrouwbare en snelle wijze geheugenlekken, te grote heaps of ontbrekende limieten.

Controle krijgen met oom_score en oom_score_adj

Elk proces heeft in /proc/[PID]/oom_score een actuele Waarde vanwege zijn risicosituatie. Met /proc/[PID]/oom_score_adj verlaag of verhoog ik de kans dat de kernel dit proces beëindigt. Kritieke diensten zoals databases bescherm ik met een negatieve Adj, onbelangrijke workers maak ik „opofferbaar“ met een positieve Adj. De wijziging treedt onmiddellijk in werking, wat vooral bij roll-outs of belastingstests van pas komt. Zo maak ik van een onvoorspelbaar noodmechanisme een hulpmiddel dat mijn prioriteiten volgt.

Typische hostingscenario's waarbij de opslagruimte onder druk staat

In omgevingen met veel containers, databases en caches kom ik de OOM-killer bijzonder vaak tegen. Een database die ongecontroleerd groeit, verdringt andere diensten uit de RAM en leidt tot ernstige crashes. Geheugenlekken in webapplicaties bouwen urenlang druk op, totdat zelfs het vrijmaken van geheugen niet meer helpt. Te ruime containerlimieten op een te kleine host verergeren de situatie nog verder. Wie deze patronen herkent, stelt tijdig waarschuwingen in en grijpt in voordat de ‘killer’ de touwtjes in handen neemt.

Beste praktijken om harde kills te voorkomen

Ik plan de opslagcapaciteit op realistische wijze, houd rekening met een buffer voor piekbelasting en stel duidelijke limieten per dienst vast. De monitoring registreert per proces RSS, swapgebruik en oom_score, zodat er waarschuwingen worden gegeven voordat er een noodsituatie ontstaat. In containeromgevingen stel ik Cgroup-limieten in, zodat afzonderlijke services de host niet domineren. Een verstandige swap-strategie vangt pieken op zonder het systeem permanent te vertragen. Voor een dieper inzicht en een betere planning maak ik gebruik van praktische handleidingen over virtueel geheugen beheren, zodat workloads voldoende ruimte hebben.

Gestructureerde aanpak bij een OOM-incident

Na het incident haal ik eerst de logregels op dmesg en kern.log en zet ze in chronologische volgorde. In de monitoring bekijk ik de grafieken voor RAM, swap, RSS en paginacache om het drukverloop te zien. Daarna controleer ik ulimits, Cgroup- en containerlimieten, evenals applicatieparameters zoals de heaps van JVM’s. Vervolgens pas ik oom_score_adj zodat het belangrijkste overblijft en het overbodige als eerste verdwijnt. Tot slot pak ik de oorzaak aan: lekken verhelpen, caches beperken, parallelliteit verminderen en capaciteiten correct afstemmen.

Bijzonderheden in VPS- en cloudomgevingen

Op virtuele machines komt daar nog een tweede niveau van beperkingen bij, bijvoorbeeld door de hypervisor of de orkestratie. Ik ben daarom bekend met de toegewezen RAM-Stel de hoeveelheid nauwkeurig in en pas de Kubernetes- of containerlimieten dienovereenkomstig aan. De Linux OOM Killer blijft werken zoals beschreven, maar mechanismen van de provider kunnen extra beperkingen activeren. Juist bij veel pods helpt een duidelijke prioritering: belangrijke deployments krijgen reserves, niet-kritieke taken draaien met minder capaciteit. Documentatie van de platformprovider en eigen tests voorkomen verrassingen tijdens de productieve werking.

Het geheugen nauwkeurig afstemmen: overcommit, swappiness en caches

Wie OOM-risico's onder controle wil houden, past de kernelparameters zorgvuldig aan en begrijpt hoe deze op elkaar inwerken. vm.overcommit_memory en vm.overcommit_ratio bepalen in hoeverre Linux virtuele toewijzingen toestaat, terwijl vm.swappiness de verhouding tussen swapping en reclaim beïnvloedt. vm.vfs_cache_druk bepaalt de agressiviteit bij het vrijgeven van inode- en dentry-caches en heeft daarmee een directe invloed op de beschikbare ruimte in de paginacache. Ik test de effecten altijd onder realistische Belasting, registreer de statistieken en breng slechts stapsgewijze wijzigingen aan. Voor achtergrondinformatie en scenario’s is het nuttig om eens te kijken naar Memory Overcommit, om de eigen standaardinstellingen op een zinvolle manier te kiezen.

Parameter/indicator Rol in het systeem Waar controleren Gebruikelijke richting
Gratis RAM Buffer tegen harde kills free, /proc/meminfo Zorg dat je voldoende reserve hebt
Gebruik van swaps Schokdempers voor pieken free, vmstat Laag tot matig
vm.overcommit_memory Virtuele toewijzing sysctl 0/2, afhankelijk van het risico
vm.overcommit_ratio Quota voor overcommit sysctl Afgestemd op de werklast
vm.swappiness Neiging tot swappen sysctl Gemiddelde in plaats van uiterste waarde
vm.vfs_cache_druk VFS-caches vrijmaken sysctl 100 als uitgangspunt

Globale OOM versus Cgroup-OOM: wat sterft er precies?

In moderne configuraties met Cgroups (v1/v2) kan een OOM-gebeurtenis lokale in een Memory-cgroup of wereldwijd op de host worden geactiveerd. Als een proces in een container met strikte geheugen.max (of limiet), beëindigt de kernel doorgaans alleen processen in deze Cgroup („memcg OOM“), terwijl het systeem als geheel blijft draaien. In dmesg Ik herken dat aan aanwijzingen zoals constraint=CONSTRAINT_MEMCG of verwijzingen naar de betreffende Cgroup. Pas wanneer geen enkele Cgroup meer RAM kan vrijgeven en het globale geheugen is uitgeput, grijpt de systeemwijd OOM Killer. Om de stabiliteit te waarborgen, vind ik het belangrijk om limieten zo in te stellen dat een dienst die zijn grenzen overschrijdt, binnen zijn eigen Cgroup vastloopt, in plaats van de hele host mee te sleuren. In Cgroups v2 kan ik bovendien met geheugen.hoog zachte begrenzingen instellen en met memory.oom.group vastleggen dat de hele groep in geval van nood wordt beëindigd – dat is netter dan een halfslachtig restproces.

Tools en statistieken in de praktijk

Om snel de oorzaak te achterhalen, verzamel ik reproduceerbare cijfers. Deze hulpmiddelen komen me regelmatig van pas:

  • Procesoverzicht: ps -eo pid,ppid,cmd,%mem,rss --sort=-rss | head geeft programma's weer die veel geheugen verbruiken.
  • Smaps-rollup: cat /proc//smaps_rollup levert RSS/PSS/Swap van een proces zonder langdurige parsing.
  • pmap: pmap -x | sort -nrk3 | head geeft een overzicht van mappings met grootte en RSS, handig voor heaps en grote segmenten.
  • Gebruik van slabs: slabtop -o toont kernel-caches die bij een hoge belasting kunnen toenemen.
  • Systeemdruk: vmstat 1 en sar -r 1 geven context over paging, swap-I/O en frees.
  • Cgroup-statistieken: In v2 controleer ik /sys/fs/cgroup/memory.current, memory.swap.current en memory.stat van de betreffende dienst.
# OOM-logs gemakkelijk lezen
dmesg -T | egrep -i 'out of memory|oom-kill|killed process'

# Topkandidaten sorteren op oom_score
for p in /proc/[0-9]*; do
  pid=${p##*/}
  [ -r "$p/oom_score" ] || continue
  printf "%6s  %5s  %-30s\n" \
    "$(cat $p/oom_score)" \
    "$(cat $p/oom_score_adj 2>/dev/null || echo 0)" \
    "$(tr -d '\0' < $p/comm)"
done | sort -nr | head -n 20

Als ik herhaaldelijk OOM's zie, leg ik de Basislijn deze waarden tijdens normaal bedrijf en vergelijk ze met het incidentvenster. Afwijkingen vallen meteen op, zoals een ongebreidelde stijging van PSS of onevenredig grote slabs.

Systemd, containers en orkestratie: gericht aansturen

In systemd stel ik de prioriteiten en limieten in aangegeven in Unit-bestanden:

[Service]
# Proces beveiligen of opofferbaar maken
OOMScoreAdjust=-900

# Harde/zachte geheugenlimieten (cgroup v2)
MemoryMax=8G
MemoryHigh=6G
# Optioneel: swap beperken
MemorySwapMax=2G

# Gedrag bij OOM onder systemd
# (bijv. herstart afdwingen)
Restart=on-failure
RestartSec=5

In containeromgevingen zorg ik voor duidelijke limieten per service. Ik vind het belangrijk om onderscheid te maken tussen Verzoek (geplande reservering) en Beperk (strikte bovengrens). Pods met passende verzoeken/limieten krijgen betere QoS-classificaties; „BestEffort“-workloads lopen het risico op OOM. Een praktisch detail: als de kernel een container afsluit vanwege Cgroup-OOM, zie ik vaak exitcode 137 en gebeurtenissen met OOMKilled; in de host‑dmesg Dat kan met elkaar in verband worden gebracht. In productieve clusters plan ik kritieke implementaties als „Guaranteed“, terwijl batch-taken bewust strakker worden gepland en daardoor als eerste plaats moeten maken.

Kernel-details: OOM Reaper, THP en fragmentatie

Na de kill grijpt de OOM Reaper: een kernel-thread ontneemt het slachtofferproces zo snel mogelijk zijn geheugenmapping, zodat het RAM-geheugen daadwerkelijk vrijkomt. Dat verklaart waarom geheugen soms pas naar de Killeintrag zichtbaar terugkomt. Tegelijkertijd kan de Compact maken van opslagruimte tegen grenzen aanlopen – als het RAM sterk gefragmenteerd is, ontbreken aaneengesloten gebieden voor grote toewijzingen (bijvoorbeeld met Transparent Huge Pages, THP). THP levert prestaties, maar kan onder druk de toewijzing bemoeilijken. Voor latentiegevoelige workloads schakel ik THP bij wijze van test uit of beperk ik het, en meet ik de effecten.

Een andere factor is Slab-caches en de paginacache: bij I/O-intensieve workloads nemen deze caches sterk toe. Met vm.vfs_cache_druk en door middel van gerichte reclaim kan hun aandeel worden beheerd; het forfaitair leegmaken (drop-caches) gebruik ik hooguit als diagnose-instrument, niet als permanente oplossing. Daarnaast let ik op NUMA: Als een geheugenknooppunt vol is, kan een proces in deze NUMA-zone mislukken, ook al is er globaal gezien nog vrij RAM beschikbaar. Hierover verschijnen ook meldingen in de kernel-logs.

Swap-strategieën verdiepen: Swappiness, ZRAM/Zswap, I/O-budget

Swap is geen kwaad, maar een Schokdempers. Het is van cruciaal belang om er verstandig gebruik van te maken. Met vm.swappiness Hiermee stel ik in hoe vroeg de kernel naar swap overschakelt. Te lage waarden zorgen ervoor dat de paginacache de overhand krijgt en kunnen eerder OOM’s veroorzaken; te hoge waarden verleggen de belasting naar swap-I/O en maken het systeem traag. Op compacte hosts gebruik ik graag ZRAM of Zswap, om een gecomprimeerde buffer te creëren die pieken opvangt zonder de schijf te overbelasten. Belangrijk is dat swap geen vervanging is voor ontbrekende capaciteit. Het wint alleen tijd, zodat de OOM-killer helemaal niet in werking hoeft te treden.

Bijzondere gevallen: mlock, RLIMITS, valkuilen bij overcommit

Sommige randvoorwaarden vergroten het risico op OOM of beïnvloeden het gedrag:

  • Geblokkeerd geheugen: Processen die via mlock() Door pagina’s vast te pinnen, onttrek je ze aan de Reclaim. Bij een hoge snelheid kan het tempo van de Reaper worden afgeremd.
  • RLimits: RLIMIT_AS en RLIMIT_RSS stellen per proces bovengrenzen vast en voorkomen dat afzonderlijke diensten uit de hand lopen – een bouwsteen in de strijd tegen OOM’s.
  • Overcommit: Te ruime overcommit-instellingen maken een grote virtuele adresruimte mogelijk die later fysiek niet kan worden gedekt. Juist toewijzingspieken bij een groot aantal threads leiden dan tegelijkertijd tot fouten en versnellen OOM-gebeurtenissen.
  • panic_on_oom: Voor zeer kritieke systemen bestaat de mogelijkheid om bij een OOM te reageren met een kernelpanic. Dit is alleen zinvol in strikt omschreven HA-scenario’s en is anders contraproductief.
  • „Onverslaanbaar“ is riskant: oom_score_adj=-1000 Het beschermt weliswaar tegen de killer, maar kan het hele systeem blokkeren. Ik gebruik dit alleen voor absoluut essentiële, kleine processen (bijv. init), niet voor serverdiensten die veel geheugen verbruiken.

Praktijk: prioriteiten stellen en veranderingen waarborgen

Ik definieer binnen het team een Ranglijst de diensten: wat moet blijven, wat mag als eerste verdwijnen? Deze volgorde vertaal ik in oom_score_adj, Cgroup-limieten en (indien beschikbaar) herstartbeleidsregels. Wijzigingen worden als code opgenomen in unit- of deployment-manifesten, vergezeld van meetpunten in de monitoring. In belastingstests simuleer ik opslagdruk: ik vergroot de gegevensvolumes, verhoog de parallelliteit, laat caches groeien – en kijk of juist de „overtollige“ processen uitvallen, terwijl de kernonderdelen online blijven. Pas als dit reproduceerbaar werkt, gaat de configuratie in productie.

Diagnosepatroon: het verschil tussen lekken, heaps en fragmentatie

Niet elke stijgende RSS-waarde is een lek. Ik maak systematisch onderscheid:

  • Lek: RSS/PSS stijgen monotoon, ook zonder toenemende belasting; smaps_rollup groeit gelijkmatig; GC-cycli (bij Managed Runtimes) helpen niet.
  • Heap-pieken: RSS stijgt bij belasting en daalt weer; de paginacache hangt samen met I/O-patronen.
  • Versnippering: Voldoende vrij RAM, maar grote toewijzingen mislukken; uit de logbestanden blijkt dat er pogingen tot compactificatie zijn ondernomen, THP-toewijzingen mislukken vaker.

Voor JVM- of Node-workloads controleer ik of de runtime de containerlimieten herkent. Te groot gedimensioneerde heaps of JIT-codecaches kunnen de limiet overschrijden en OOM’s veroorzaken, ook al lijkt er nog ruimte over te zijn. Ik stel heaps, inclusief overhead, zo in dat onder MemoryMax er nog ruimte overblijft voor native-onderdelen, thread-stacks en de paginacache.

Handleiding voor implementaties en belastingstests onder opslagdruk

  1. De uitgangswaarde meten: RSS/PSS per dienst, slab-aandelen, swap-quotum, cachegroottes, oom_score.
  2. Grenzen stellen: Geheugen hoog/max. of containerlimieten vaststellen met een realistische marge; OOMScoreAdjust op basis van prioriteit toewijzen.
  3. Stress veroorzaken: gegevensvolume, gelijktijdigheid, cachegroei; noteer de I/O- en CPU-profielen.
  4. Let op: dmesg -T, host- en cgroup-statistieken; kijk wie het eerst onder druk komt te staan.
  5. Itereren: Limieten/Adj aanpassen, Swappiness aanpassen, THP-instellingen testen, opnieuw meten.
  6. automatiseren: Checks integreren in CI/CD, waarschuwingen bij grenswaarden, herstartbeleidsregels voor getroffen diensten.

Kort samengevat: concrete maatregelen

Ik beschouw de OOM-killer als Signaal, dat mijn systeem voorheen te weinig buffer had of dat processen verkeerd waren geprioriteerd. Met monitoring, realistische limieten, een degelijke swap-strategie en een bewust gebruik van oom_score_adj Ik beperk het aantal harde afsluitingen aanzienlijk. In productieve omgevingen bescherm ik kernprocessen, maak ik randdiensten overbodig en meet ik elke wijziging. Bij containers stel ik strikte Cgroup-limieten in, zodat een dienst niet het gehele hostsysteem blokkeert. Wie deze discipline handhaaft, houdt Linux ook onder druk responsief en verkort de tijd die nodig is om de oorzaak te achterhalen aanzienlijk.

Huidige artikelen

Serverrack met Linux-systemen en gevisualiseerd geheugengebruik
Servers en virtuele machines

OOM Killer begrijpen: wanneer Linux processen beëindigt

Ontdek hoe de OOM-killer in Linux werkt bij een tekort aan geheugen, hoe hij processen beëindigt en hoe je als beheerder in hostingomgevingen out-of-memory-problemen kunt voorkomen met het trefwoord oom killer linux.

Beheerder analyseert Journalctl-logbestanden op een Linux-server in het datacenter
Administratie

Journalctl effectief inzetten: foutanalyse op Linux-servers

Leer hoe je `journalctl` kunt gebruiken voor een efficiënte foutanalyse op Linux-servers. Met filters op tijd, service en prioriteit kun je Linux-logs op een gestructureerde manier analyseren en je servertroubleshooting optimaliseren.

Linux-server met systemd-dienstbeheer in het hostingdatacenter
Administratie

Systemd in de dagelijkse hostingpraktijk: diensten efficiënt beheren

Leer hoe je met systemd en systemctl diensten in de dagelijkse hostingpraktijk efficiënt kunt beheren. Dit artikel laat aan de hand van praktijkvoorbeelden zien hoe systemd hosting stabieler maakt en hoe Linux-diensten worden geautomatiseerd.