
Když na Linuxovém serveru databáze dojde k nečekanému pádu, je třeba najít příčinu. Příčin může být několik. Například, SIGSEGV — chyba v backendovém serveru. To se však stává zřídka. Častěji dochází k vyčerpání prostoru na disku nebo paměti. Pokud dojde k vyčerpání diskového prostoru, zbývá jen jediné — uvolnit místo a restartovat databázi.
Out-Of-Memory Killer
Když dojde k vyčerpání paměti u serveru nebo procesu, Linux nabízí 2 možnosti: buď shodit celý systém, nebo ukončit proces (aplikaci), která spotřebovává paměť. Lepší je samozřejmě ukončit proces a zachránit operační systém před havárií. V kostce, Out-Of-Memory Killer je proces, který ukončuje aplikaci, aby zachránil jádro před selháním. Obětuje aplikaci, aby udržel operační systém v chodu. Nejprve si povězme, jak OOM funguje a jak jej lze řídit, a poté se podíváme, jak OOM Killer rozhoduje, kterou aplikaci ukončit.
Jedním z hlavních úkolů Linuxu je přidělovat paměť procesům, když o ni žádají. Obvykle proces nebo aplikace žádají operační systém o paměť, ale ve skutečnosti ji plně nevyužívají. Pokud by operační systém přiděloval paměť všem, kdo o ni žádají, ale neplánují ji použít, velmi rychle by došla paměť a systém by selhal. Aby se tomu předešlo, operační systém rezervuje paměť pro proces, ale ve skutečnosti ji nevydává. Paměť se přiděluje pouze tehdy, když ji proces skutečně potřebuje. Někdy se stane, že operační systém nemá volnou paměť, ale rezervuje ji pro proces, a když ji proces potřebuje, operační systém ji přidělí, pokud může. Nevýhodou je, že někdy operační systém rezervuje paměť, ale v kritickém okamžiku jiná paměť není k dispozici, což způsobuje selhání systému. OOM hraje v tomto scénáři důležitou roli a ukončuje procesy, aby ochránil jádro před panikou. Když je násilně ukončen proces PostgreSQL, v logu se objeví zpráva:
Out of Memory: Killed process 12345 (postgres).Pokud je v systému nedostatek paměti a není možné ji uvolnit, je vyvolána funkce out_of_memory. V této fázi zbývá už jen jedno — dokončit jeden nebo více procesů. OOM-killer by měl okamžitě ukončit proces, nebo je možné počkat? Je zřejmé, že když se vyvolá out_of_memory, je to spojeno s čekáním na operaci I/O nebo swapování stránky na disk. Proto by OOM-killer měl nejdříve provést kontroly a na základě jejich výsledků se rozhodnout, který proces ukončit. Pokud všechny níže uvedené kontroly dají pozitivní výsledek, OOM ukončí proces.
Výběr procesu
Když dojde paměť, vyvolá se funkce out_of_memory(). Obsahuje funkci select_bad_process(), která získá hodnocení od funkce badness(). Na úkor se dostane ten "nejhorší" proces. Funkce badness() vybírá proces podle určitých pravidel.
- Jádro potřebuje určitý minimální objem paměti pro sebe.
- Je třeba uvolnit velké množství paměti.
- Není potřeba ukončovat procesy, které používají málo paměti.
- Je třeba ukončit minimálně procesy.
- Složitější algoritmy, které zvyšují šance na ukončení těch procesů, které uživatel sám chce ukončit.
Po provedení všech těchto kontrol OOM zkoumá hodnocení (oom_score). OOM přiřazuje oom_score každému procesu, a poté toto hodnotu násobí objemem paměti. Procesy s vyššími hodnotami mají větší šance stát se oběťmi OOM Killeru. Procesy spojené s privilegovaným uživatelem mají nižší hodnocení a menší šance na nedobrovolné ukončení.
postgres=# SELECT pg_backend_pid();
pg_backend_pid
----------------
3813
(1 row)Identifikátor procesu Postgres je 3813, takže v jiném shellu lze získat hodnocení pomocí tohoto parametr jádra oom_score:
vagrant@vagrant:~$ sudo cat /proc/3813/oom_score
2Pokud opravdu nechcete, aby OOM-killer ukončil proces, existuje ještě jeden parametr jádra: oom_score_adj. Přidejte velkou zápornou hodnotu, abyste snížili šance na ukončení cenného procesu.
sudo echo -100 > /proc/3813/oom_score_adjChcete-li nastavit hodnotu oom_score_adj, nastavte OOMScoreAdjust v bloku služby:
[Service]
OOMScoreAdjust=-1000Nebo použijte oomprotect v příkazu rcctl.
rcctl set servicename oomprotect -1000Nucené ukončení procesu
Když byly vybrány jeden nebo více procesů, OOM-killer vyvolává funkci oom_kill_task(). Tato funkce odešle procesu signál k ukončení. V případě nedostatku paměti oom_kill() vyvolává tuto funkci, aby odeslala procesu signál SIGKILL. Do jádrového protokolu se zapíše zpráva.
Out of Memory: Zabit proces [pid] [name].Jak ovládat OOM-Killer
V Linuxu lze OOM-Killer zapínat a vypínat (i když se to nedoporučuje). Pro zapnutí a vypnutí použijte parameter vm.oom-kill. Chcete-li povolit OOM-Killer za běhu, zadejte příkaz sysctl.
sudo -s sysctl -w vm.oom-kill = 1Pro vypnutí OOM-Killeru zadejte hodnotu 0 v tomto příkazu:
sudo -s sysctl -w vm.oom-kill = 0Výsledek tohoto příkazu se neuchová navždy, ale pouze do prvního restartu. Pokud potřebujete větší trvalost, přidejte tento řádek do souboru /etc/sysctl.conf:
echo vm.oom-kill = 1 >> /etc/sysctl.confDalší způsob zapnutí a vypnutí je napsat proměnnou panic_on_oom. Hodnotu lze vždy zkontrolovat v /proc.
$ cat /proc/sys/vm/panic_on_oom
0Pokud nastavíte hodnotu 0, když dojde paměť, nedojde k panice jádra.
$ echo 0 > /proc/sys/vm/panic_on_oomPokud nastavíte hodnotu 1, když dojde paměť, dojde k panice jádra.
echo 1 > /proc/sys/vm/panic_on_oomOOM-Killer nemusíte jen zapínat a vypínat. Už jsme mluvili o tom, že Linux může rezervovat pro procesy více paměti, než je k dispozici, ale ve skutečnosti ji nepřiděluje, a tímto chováním se řídí parametr jádra Linuxu. O to se stará proměnná vm.overcommit_memory.
Může mít následující hodnoty:
0: jádro samo rozhoduje, zda rezervovat příliš mnoho paměti. Tato hodnota je ve většině verzí Linuxu výchozí.
1: jádro vždy rezervuje přebytečnou paměť. To je riskantní, protože paměť může docházet, protože pravděpodobně jednou procesy vyžádají to, co mají.
2: jádro nebude rezervovat více paměti, než je uvedeno v parametru overcommit_ratio.
V této hodnotě zadáváte procento paměti, pro které je přebytečné rezervování povoleno. Pokud pro ni není místo, paměť nebude přidělena a rezervace bude zamítnuta. To je nejbezpečnější možnost doporučená pro PostgreSQL. Na OOM-Killer má vliv také jeden další prvek - možnost swapování, kterou ovládá proměnná cat /proc/sys/vm/swappiness. Tyto hodnoty řídí jádro, jak zpracovávat swapování stránek. Čím vyšší hodnota, tím menší pravděpodobnost, že OOM ukončí proces, ale kvůli operacím vstupu/výstupu to negativně ovlivňuje databázi. A naopak - čím nižší hodnota, tím vyšší pravděpodobnost zásahu OOM-Killera, ale výkon databáze je také vyšší. Výchozí hodnota je 60, ale pokud se celá databáze vejde do paměti, je lepší nastavit hodnotu 1.
Závěry
Neděste se slova „killer“ v OOM-Killer. V tomto případě bude killer zachráncem vašeho systému. „Zabíjí“ ty nejproblematičtější procesy a chrání systém před havarijním ukončením. Abyste nemuseli používat OOM-Killer k ukončení PostgreSQL, nastavte pro vm.overcommit_memory hodnotu 2. To nezaručuje, že nebude potřeba, aby OOM-Killer zasáhl, ale sníží pravděpodobnost donuceného ukončení procesu PostgreSQL.
Zdroj: habr.com
