Configurarea Out-Of-Memory Killer în Linux pentru PostgreSQL

Configurarea Out-Of-Memory Killer în Linux pentru PostgreSQL

Când un server de baze de date se închide în mod neașteptat în Linux, trebuie să găsiți motivul. Pot exista mai multe motive. De exemplu, SIGSEGV — eșec din cauza unei erori în serverul backend. Dar acest lucru este rar. Cel mai adesea, pur și simplu rămâneți fără spațiu pe disc sau memorie. Dacă rămâneți fără spațiu pe disc, există o singură cale de ieșire - eliberați spațiu și reporniți baza de date.

Ucigașul fără memorie

Când un server sau un proces rămâne fără memorie, Linux oferă 2 soluții: blocarea întregului sistem sau terminarea procesului (aplicația) care consumă memorie. Desigur, este mai bine să încheiați procesul și să salvați sistemul de operare de la prăbușire. Pe scurt, Out-Of-Memory Killer este un proces care omoara o aplicație pentru a salva nucleul de la blocarea. Sacrifică aplicația pentru a menține sistemul de operare în funcțiune. Să discutăm mai întâi cum funcționează OOM și cum să-l controlăm, apoi să vedem cum OOM Killer decide ce aplicație să încheie.

Una dintre sarcinile principale ale Linux este să aloce memorie proceselor atunci când acestea o solicită. De obicei, un proces sau o aplicație solicită memorie de la sistemul de operare, dar nu o folosește pe deplin. Dacă sistemul de operare oferă memorie tuturor celor care o solicită, dar nu intenționează să o folosească, foarte curând memoria se va epuiza și sistemul va eșua. Pentru a evita acest lucru, sistemul de operare își rezervă memorie pentru proces, dar nu o eliberează de fapt. Memoria este alocată numai atunci când un proces o va folosi efectiv. Se întâmplă ca sistemul de operare să nu aibă memorie liberă, dar atribuie memorie unui proces, iar atunci când un proces are nevoie, sistemul de operare o alocă dacă poate. Dezavantajul este că uneori sistemul de operare își rezervă memorie, dar la momentul potrivit nu există memorie liberă, iar sistemul se blochează. OOM joacă un rol important în acest scenariu și încheie procesele pentru a preveni panicarea nucleului. Când un proces PostgreSQL este forțat să se termine, în jurnal apare un mesaj:

Out of Memory: Killed process 12345 (postgres).

Dacă sistemul are memorie scăzută și nu poate fi eliberat, funcția este apelată out_of_memory. În această etapă, ea mai are un singur lucru de făcut - să finalizeze unul sau mai multe procese. OOM-killer ar trebui să încheie imediat procesul sau poate aștepta? Evident, atunci când este apelat out_of_memory, se datorează așteptării unei operațiuni I/O sau paginare pe disc. Prin urmare, criminalul OOM trebuie mai întâi să efectueze verificări și, pe baza acestora, să decidă că procesul trebuie să fie încheiat. Dacă toate verificările de mai jos sunt pozitive, OOM va încheia procesul.

Selecția procesului

Când memoria se epuizează, funcția este apelată out_of_memory(). Are o funcție select_bad_process(), care primește o evaluare de la funcție badness(). Cel mai „prost” proces va fi vizat. Funcţie badness() selectează un proces după anumite reguli.

  1. Nucleul are nevoie de o memorie minimă pentru el însuși.
  2. Trebuie să eliberați multă memorie.
  3. Nu este nevoie să terminați procesele care folosesc puțină memorie.
  4. Procesele minime trebuie finalizate.
  5. Algoritmi complecși care măresc șansele de finalizare pentru acele procese pe care utilizatorul însuși dorește să le finalizeze.

După ce a finalizat toate aceste verificări, OOM examinează scorul (oom_score). OOM numește oom_score fiecare proces și apoi înmulțește această valoare cu cantitatea de memorie. Procesele cu valori mai mari au mai multe șanse să cadă victimele OOM Killer. Procesele asociate cu utilizatorul root au un scor mai mic și sunt mai puțin probabil să fie forțate să se încheie.

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

ID-ul procesului Postgres este 3813, așa că într-un alt shell este posibil să obțineți scorul folosind acest parametru de kernel oom_score:

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

Dacă nu doriți ca OOM-Killer să oprească deloc procesul, există o altă opțiune de kernel: oom_score_adj. Adăugați o valoare negativă mare pentru a reduce șansele de a finaliza un proces pe care îl apreciați.

sudo echo -100 > /proc/3813/oom_score_adj

Pentru a seta o valoare oom_score_adj, setați OOMScoreAdjust în blocul de servicii:

[Service]
OOMScoreAdjust=-1000

Sau folosiți oomprotect într-o echipă rcctl.

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

Forțare încetarea unui proces

Când unul sau mai multe procese sunt deja selectate, OOM-Killer apelează funcția oom_kill_task(). Această funcție trimite procesului un semnal de terminare. În caz de lipsă de memorie oom_kill() Apelează această funcție pentru a trimite un semnal SIGKILL către proces. Un mesaj este scris în jurnalul kernelului.

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

Cum să controlezi OOM-Killer

Pe Linux, puteți activa sau dezactiva OOM-Killer (deși acesta din urmă nu este recomandat). Pentru a activa sau dezactiva folosiți parametrul vm.oom-kill. Pentru a activa OOM-Killer în timpul execuției, executați comanda sysctl.

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

Pentru a dezactiva OOM-Killer, specificați valoarea 0 în aceeași comandă:

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

Rezultatul acestei comenzi nu va fi salvat pentru totdeauna, ci doar până la prima repornire. Dacă aveți nevoie de mai multă persistență, adăugați această linie la fișier /etc/sysctl.conf:

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

O altă modalitate de a activa și de a dezactiva este să scrieți o variabilă panic_on_oom. Valoarea poate fi întotdeauna verificată /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Dacă setați valoarea la 0, atunci când memoria se epuizează, nu va exista nicio panică a nucleului.

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

Dacă setați valoarea la 1, atunci când memoria se epuizează, va apărea o panică a nucleului.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer nu poate fi doar pornit și oprit. Am spus deja că Linux poate rezerva mai multă memorie pentru procese decât este disponibilă fără a o aloca efectiv, iar acest comportament este controlat de un parametru al nucleului Linux. Variabila este responsabilă pentru acest lucru vm.overcommit_memory.

Puteți specifica următoarele valori pentru acesta:

0: Nucleul însuși decide dacă rezerve prea multă memorie. Acesta este implicit pentru majoritatea versiunilor de Linux.
1: Nucleul va rezerva întotdeauna memorie suplimentară. Acest lucru este riscant, deoarece memoria se poate epuiza, pentru că, cel mai probabil, într-o zi procesele o vor cere.
2: nucleul nu va rezerva mai multă memorie decât cea specificată în parametru overcommit_ratio.

Cu acest parametru, specificați procentul de memorie care poate fi suprarezervat. Dacă nu există loc pentru el, nu se alocă memorie și rezervarea va fi refuzată. Aceasta este cea mai sigură opțiune recomandată pentru PostgreSQL. OOM-Killer este afectat de un alt element - capacitatea de schimb, care este controlată de variabilă cat /proc/sys/vm/swappiness. Aceste valori îi spun nucleului cum să gestioneze paginarea. Cu cât valoarea este mai mare, cu atât este mai puțin probabil ca OOM să încheie procesul, dar din cauza operațiunilor I/O are un impact negativ asupra bazei de date. Și invers - cu cât valoarea este mai mică, cu atât este mai mare probabilitatea intervenției OOM-Killer, dar și performanța bazei de date este mai mare. Valoarea implicită este 60, dar dacă întreaga bază de date încape în memorie, este mai bine să setați valoarea la 1.

Rezultatele

Nu lăsa „ucigașul” din OOM-Killer să te sperie. În acest caz, ucigașul va fi salvatorul sistemului tău. „Ucide” cele mai rele procese și salvează sistemul de la prăbușire. Pentru a evita utilizarea OOM-Killer pentru a termina PostgreSQL, setați la vm.overcommit_memory valoarea 2. Acest lucru nu garantează că OOM-Killer nu va trebui să intervină, dar va reduce probabilitatea de a forța procesul PostgreSQL să se termine.

Sursa: www.habr.com

Adauga un comentariu