db.dobo.sk

Postgres – všetko, čo si chcel vedieť, ale bál sa spýtať svojho seniora, aby si nevypadal ako jelito 15. OOM killer.

bez komentára

OOM killer je štandardná linuxová vec v managemente pamäte. Vzhľadom na to, že linux používa virtual memory a má necnosť, že dovoľuje alokovať aplikácii viac pamäte, než má k dispozícii (overcommit), občas je nutné nejaký proces odstreliť, keď pamäť dôjde. Ovšem postgres má tú vlastnosť, že ak sa odstrelí čo jen 1 process SIGKILLom (napr. nejaký enormný dotaz), tak sa porúča celý cluster, ktorý nevie, v akom stave sú datové buffers. Ergo OOM killer na postgres je veľký špatný…

Overcommit

Overcomitovanie pamäte je výsledkom “dobrej praxe”, že aplikácie si po sebe dobre upratajú a málokedy dôjde k súbežnému vyžraniu pamäte viecerými procesmi. No, ale keď k tomu dôjde, tak OOM killer. Overcommitovanie je nastaviteľné a to parametrom v /proc/sys/vm/overcommit_memory

Hodnoty:

  • 0 = kernel má voľnú ruku v rozhodovaní, či bude overcommitovať. Default.
  • 1 = kernel bude vždy overcommitovať
  • 2 = kernel nikdy nebude overcommitovať cez threshold definovaný v /proc/sys/vm/overcommit_ratio. Doporučené pre postgresový stroj.

Ako OOM killer vlastne pracuje

  • Keď je systém out of memory, tak kernel volá funkciu out_of_memory() a tá v rámci reťaze rozhodovania funkciu badness(). Táto funkcia rozhodne, ktorý proces si zaslúži byť položený na oltár uvoľnenia pamäte a to na základe počítania skóre (čím vyššie, tým je proces lepší adept na odstrel):
  • bude uprednostneny proces non-privileged usera
  • vyber proces, kde sa jedným odstrelom zvýši čo najviac pamäte
  • prednosť na popravisko má proces spustený nedávno
  • atď…

Oom_score sa dá ľahko vylistovať (cat /proc/PID/oom_score/). Čím vyššie skóre, tým pravdepodobnejší zostrel. Po vyrátaní “badness” sa spustí funkcia oom_kill() a je hotovo…

Ako znížiť OOM skóre a “imunizovať” proces

1. OOM killer sa dá úplne vypnúť (nedoporučuje sa, pamäť pôjde do swapu a potom buch celý stroj):
sysctl -w vm.oom-kill = 0 (resp. echo vm.oom-kill = 0 >>/etc/sysctl.conf)

2. Umelo znížiť oom skóre flagom v /proc/PID/oom_score_adj (čím zápornejšia hodnota, tým lepšia imunizácia), ale to je dosť nepohodlné, pretože apriori nevieme, aký PID bude mať napr. postgres.

3. Zakázať overcommit (ansible yaml):
– name: create /etc/sysctl.d/memory_overcommit.conf
template:
src: memory_overcommit.conf.j2
dest: /etc/sysctl.d/memory_overcommit.conf
notify: memory overcommit customization
tags: postgres_memory_overcommit

a odpovedajúca džindža:

vm.overcommit_memory = 2

Ako nájsť v logoch, že OOM killer zapracoval

OOM killer je kernelová vec (skús lsof /dev/kmsg, kto načúva), takže bude najčastešie niekde v /var/log/kern.log (grep -i “kill”). Pokiaľ sa naň príde rýchlo, skôr než sa zaplní kruhový buffer kernelu, tak v dmesg.

Pre journald/journalctl doporučujem tento krátky postup.

píše: ďobo

February 15th, 2022 o 3:36 pm

chlievik: linux

okomentuj