Nastavenie nástroja Out-Of-Memory Killer v Linuxe pre PostgreSQL

Nastavenie nástroja Out-Of-Memory Killer v Linuxe pre PostgreSQL

Keď sa databázový server neočakávane ukončí v systéme Linux, musíte nájsť príčinu. Dôvodov môže byť viacero. Napríklad, SIGSEGV — zlyhanie v dôsledku chyby na backend serveri. Ale to je zriedkavé. Najčastejšie vám jednoducho dôjde miesto na disku alebo pamäť. Ak vám dôjde miesto na disku, existuje len jedna cesta von – uvoľniť miesto a reštartovať databázu.

Zabijak s nedostatkom pamäte

Keď serveri alebo procesu dôjde pamäť, Linux ponúka 2 riešenia: zrútenie celého systému alebo ukončenie procesu (aplikácie), ktorý zaberá pamäť. Je lepšie, samozrejme, ukončiť proces a zachrániť OS pred pádom. Stručne povedané, Out-Of-Memory Killer je proces, ktorý zabije aplikáciu, aby zachránil jadro pred pádom. Obetuje aplikáciu, aby udržal operačný systém v chode. Najprv si pohovorme o tom, ako OOM funguje a ako ho ovládať, a potom uvidíme, ako sa OOM Killer rozhoduje, ktorú aplikáciu ukončiť.

Jednou z hlavných úloh Linuxu je alokovať pamäť procesom, keď o to požiadajú. Proces alebo aplikácia zvyčajne vyžaduje pamäť od operačného systému, ale nevyužíva ju v plnej miere. Ak OS rozdá pamäť každému, kto o ňu požiada, ale neplánuje ju použiť, veľmi skoro sa pamäť minie a systém zlyhá. Aby sa tomu zabránilo, operačný systém vyhradí pamäť pre proces, ale v skutočnosti ju neuvoľní. Pamäť sa prideľuje iba vtedy, keď ju proces skutočne použije. Stáva sa, že OS nemá voľnú pamäť, ale priraďuje pamäť procesu a keď ju proces potrebuje, OS ju pridelí, ak môže. Nevýhodou je, že niekedy operačný systém vyhradí pamäť, ale v správnom čase nie je voľná pamäť a systém sa zrúti. OOM hrá v tomto scenári dôležitú úlohu a ukončuje procesy, aby sa zabránilo panike jadra. Keď je proces PostgreSQL nútený ukončiť, v protokole sa zobrazí správa:

Out of Memory: Killed process 12345 (postgres).

Ak má systém málo pamäte a nemožno ju uvoľniť, funkcia sa zavolá out_of_memory. V tejto fáze jej ostáva už len jedna vec – dokončiť jeden alebo viacero procesov. Mal by OOM-killer ukončiť proces okamžite alebo môže počkať? Je zrejmé, že keď sa volá out_of_memory, je to kvôli čakaniu na I/O operáciu alebo stránkovanie na disk. OOM zabijak preto musí najskôr vykonať kontroly a na ich základe rozhodnúť, že je potrebné proces ukončiť. Ak sú všetky nižšie uvedené kontroly pozitívne, OOM proces ukončí.

Výber procesu

Keď dôjde pamäť, zavolá sa funkcia out_of_memory(). Má funkciu select_bad_process(), ktorý dostáva hodnotenie od funkcie badness(). Zameria sa na „najhorší“ proces. Funkcia badness() vyberá proces podľa určitých pravidiel.

  1. Jadro potrebuje pre seba určitú minimálnu pamäť.
  2. Potrebujete uvoľniť veľa pamäte.
  3. Nie je potrebné ukončiť procesy, ktoré využívajú málo pamäte.
  4. Je potrebné dokončiť minimálne procesy.
  5. Komplexné algoritmy, ktoré zvyšujú šance na dokončenie tých procesov, ktoré chce používateľ sám dokončiť.

Po dokončení všetkých týchto kontrol OOM preskúma skóre (oom_score). OOM menuje oom_score každý proces a potom túto hodnotu vynásobí množstvom pamäte. Procesy s väčšími hodnotami sa s väčšou pravdepodobnosťou stanú obeťou OOM Killera. Procesy spojené s užívateľom root majú nižšie skóre a je menej pravdepodobné, že budú nútené ukončiť.

postgres=# SELECT pg_backend_pid();
pg_backend_pid 
----------------
    3813
(1 row)

ID procesu Postgres je 3813, takže v inom prostredí je možné získať skóre pomocou tohto parametra jadra oom_score:

vagrant@vagrant:~$ sudo cat /proc/3813/oom_score
2

Ak nechcete, aby OOM-Killer vôbec zabil proces, existuje ďalšia možnosť jadra: oom_score_adj. Pridajte veľkú zápornú hodnotu, aby ste znížili šance na dokončenie procesu, ktorý si ceníte.

sudo echo -100 > /proc/3813/oom_score_adj

Ak chcete nastaviť hodnotu oom_score_adj, nastavte OOMScoreAdjust v bloku služieb:

[Service]
OOMScoreAdjust=-1000

Alebo použite oomprotect v tíme rcctl.

rcctl set <i>servicename</i> oomprotect -1000

Vynútiť ukončenie procesu

Keď je už vybratý jeden alebo viac procesov, OOM-Killer zavolá funkciu oom_kill_task(). Táto funkcia vyšle do procesu signál ukončenia. V prípade nedostatku pamäte oom_kill() Volá túto funkciu na odoslanie signálu SIGKILL do procesu. Do protokolu jadra sa zapíše správa.

Out of Memory: Killed process [pid] [name].

Ako ovládať OOM-Killer

V systéme Linux môžete povoliť alebo zakázať OOM-Killer (hoci druhý sa neodporúča). Ak chcete povoliť alebo zakázať, použite parameter vm.oom-kill. Ak chcete povoliť OOM-Killer za behu, spustite príkaz sysctl.

sudo -s sysctl -w vm.oom-kill = 1

Ak chcete vypnúť OOM-Killer, zadajte hodnotu 0 v rovnakom príkaze:

sudo -s sysctl -w vm.oom-kill = 0

Výsledok tohto príkazu sa neuloží navždy, ale iba do prvého reštartu. Ak potrebujete väčšiu vytrvalosť, pridajte tento riadok do súboru /etc/sysctl.conf:

echo vm.oom-kill = 1 >>/etc/sysctl.conf

Ďalším spôsobom aktivácie a deaktivácie je napísanie premennej panic_on_oom. Hodnotu je možné vždy skontrolovať /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Ak nastavíte hodnotu na 0, potom keď sa minie pamäť, nedôjde k panike jadra.

$ echo 0 > /proc/sys/vm/panic_on_oom

Ak nastavíte hodnotu na 1, potom keď sa minie pamäť, dôjde k panike jadra.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer sa dá nielen zapnúť a vypnúť. Už sme povedali, že Linux dokáže vyhradiť viac pamäte pre procesy, než je k dispozícii bez toho, aby ju skutočne pridelil, a toto správanie je riadené parametrom linuxového jadra. Za to je zodpovedná premenná vm.overcommit_memory.

Môžete preň zadať nasledujúce hodnoty:

0: Samotné jadro sa rozhodne, či si vyhradí príliš veľa pamäte. Toto je predvolené nastavenie vo väčšine verzií Linuxu.
1: Jadro si vždy vyhradí dodatočnú pamäť. Je to riskantné, pretože sa môže vyčerpať pamäť, pretože s najväčšou pravdepodobnosťou to jedného dňa procesy budú vyžadovať.
2: jadro si nevyhradí viac pamäte, ako je uvedené v parametri overcommit_ratio.

Pomocou tohto parametra zadáte percento pamäte, ktorá môže byť nadmerne rezervovaná. Ak na to nie je miesto, nepridelí sa žiadna pamäť a rezervácia bude zamietnutá. Toto je najbezpečnejšia možnosť odporúčaná pre PostgreSQL. OOM-Killer je ovplyvnený ďalším prvkom - schopnosťou swapovania, ktorá je riadená premennou cat /proc/sys/vm/swappiness. Tieto hodnoty hovoria jadru, ako zaobchádzať so stránkovaním. Čím vyššia je hodnota, tým je menšia pravdepodobnosť, že OOM ukončí proces, ale kvôli I/O operáciám to má negatívny vplyv na databázu. A naopak – čím je hodnota nižšia, tým je vyššia pravdepodobnosť zásahu OOM-Killer, ale vyšší je aj výkon databázy. Predvolená hodnota je 60, ale ak sa celá databáza zmestí do pamäte, je lepšie nastaviť hodnotu na 1.

Výsledky

Nenechajte sa vystrašiť „zabijakom“ v OOM-Killer. V tomto prípade bude vrahom záchranca vášho systému. „Zabije“ najhoršie procesy a ochráni systém pred pádom. Aby ste nemuseli používať OOM-Killer na ukončenie PostgreSQL, nastavte na vm.overcommit_memory hodnota 2. To nezaručuje, že OOM-Killer nebude musieť zasiahnuť, ale zníži sa tým pravdepodobnosť vynútenia ukončenia procesu PostgreSQL.

Zdroj: hab.com

Pridať komentár