Konfiguracja Out-Of-Memory Killer w Linux dla PostgreSQL

Konfiguracja Out-Of-Memory Killer w Linux dla PostgreSQL

Kiedy serwer bazy danych Linuxa niespodziewanie się wyłącza, należy znaleźć przyczynę. Przyczyn może być kilka. Na przykład, SIGSEGV — błąd spowodowany wadą w serwerze zaplecza. To jednak jest rzadkością. Najczęściej po prostu kończy się przestrzeń na dysku lub pamięć. Jeśli skończy się miejsce na dysku, jedynym rozwiązaniem jest zwolnienie miejsca i ponowne uruchomienie bazy danych.

Out-Of-Memory Killer

Kiedy serwera lub procesowi kończy się pamięć, Linux oferuje 2 możliwości rozwiązania: załamać cały system lub zakończyć proces (aplikację), która zajmuje pamięć. Lepiej jest oczywiście zakończyć proces i ocalić system operacyjny przed awaryjnym wyłączeniem. W skrócie, Out-Of-Memory Killer to proces, który kończy aplikację, aby uratować jądro przed awarią. Poświęca aplikację, aby zachować funkcjonowanie systemu operacyjnego. Najpierw omówmy, jak działa OOM i jak można nim zarządzać, a następnie przyjrzyjmy się, jak OOM Killer decyduje, którą aplikację zakończyć.

Jednym z głównych zadań Linuxa jest przydzielanie pamięci procesom, kiedy o to proszą. Zwykle proces lub aplikacja żądają pamięci od systemu operacyjnego, ale nie wykorzystują jej całkowicie. Jeśli system operacyjny będzie przydzielał pamięć wszystkim, którzy o nią proszą, ale nie planują jej używać, wkrótce pamięć się skończy, a system odmówi działania. Aby temu zapobiec, system operacyjny rezerwuje pamięć na rzecz procesu, ale faktycznie jej nie przydziela. Pamięć jest przydzielana tylko wtedy, gdy proces rzeczywiście zamierza jej użyć. Czasami zdarza się, że system operacyjny nie ma wolnej pamięci, ale rezerwuje pamięć na rzecz procesu, a gdy proces jej potrzebuje, system operacyjny przydziela ją, jeśli może. Wadą jest to, że czasami system operacyjny rezerwuje pamięć, ale w odpowiednim momencie nie ma wolnej pamięci, co może doprowadzić do awarii systemu. OOM odgrywa kluczową rolę w tym scenariuszu i kończy procesy, aby uchronić jądro przed paniką. Kiedy proces PostgreSQL jest wymuszony do zakończenia, w logach pojawia się komunikat:

Out of Memory: Zakończono proces 12345 (postgres).

Jeśli w systemie jest mało pamięci i nie można jej uwolnić, wywoływana jest funkcja out_of_memoryNa tym etapie pozostało jej tylko jedno — zakończyć jeden lub kilka procesów. Czy OOM-killer powinien natychmiast zakończyć proces, czy można poczekać? Oczywiście, że gdy wywoływana jest sytuacja out_of_memory, wiąże się to z oczekiwaną operacją we/wy lub wymianą stron na dysk. Dlatego OOM-killer powinien najpierw wykonać kontrole i na ich podstawie zdecydować, który proces zakończyć. Jeśli wszystkie poniższe kontrole zakończą się pozytywnie, OOM zakończy proces.

Wybór procesu

Gdy kończy się pamięć, wywoływana jest funkcja out_of_memory(). Zawiera ona funkcję select_bad_process(), która otrzymuje ocenę od funkcji badness(). Najbardziej „zły” proces zostanie zakończony. Funkcja ta badness() wybiera proces według określonych zasad.

  1. Jądro potrzebuje minimum pamięci dla siebie.
  2. Należy zwolnić dużo pamięci.
  3. Nie warto kończyć procesów, które wykorzystują mało pamięci.
  4. Należy zakończyć przynajmniej kilka procesów.
  5. Skomplikowane algorytmy, które zwiększają szanse na zakończenie dla tych procesów, które użytkownik chce zakończyć.

Po wykonaniu wszystkich tych kontroli OOM analizuje ocenę (oom_score). OOM przypisuje oom_score każdemu procesowi, a następnie mnoży tę wartość przez ilość pamięci. Procesy z wyższymi wartościami mają większe szanse stać się ofiarami OOM Killer. Procesy związane z uprzywilejowanym użytkownikiem mają niższą ocenę i mniejsze szanse na wymuszone zakończenie.

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

Identyfikator procesu Postgres — 3813, dlatego w innym powłoce można uzyskać ocenę, używając tego parametru jądra oom_score:

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

Jeśli nie chcesz, aby OOM-Killer zakończył proces, jest jeszcze jeden parametr jądra: oom_score_adj. Dodaj dużą wartość ujemną, aby zmniejszyć szanse na zakończenie procesu, który jest dla Ciebie cenny.

sudo echo -100 > /proc/3813/oom_score_adj

Aby ustawić wartość oom_score_adj, ustaw OOMScoreAdjust w bloku usługi:

[Service]
OOMScoreAdjust=-1000

Lub użyj oomprotect w komendzie rcctl.

rcctl set servicename oomprotect -1000

Wymuszone zakończenie procesu

Gdy jeden lub więcej procesów już zostało wybranych, OOM-Killer wywołuje funkcję oom_kill_task(). Ta funkcja wysyła procesowi sygnał zakończenia. W przypadku braku pamięci oom_kill() wywołuje tę funkcję, aby wysłać procesowi sygnał SIGKILL. W logach jądra zapisywana jest wiadomość.

Brak pamięci: Zakończono proces [pid] [name].

Jak kontrolować OOM-Killera

W systemie Linux można włączać i wyłączać OOM-Killera (choć ostatnie z nich nie jest zalecane). Aby włączyć lub wyłączyć, użyj parametru vm.oom-kill. Aby włączyć OOM-Killera w środowisku wykonawczym, wykonaj polecenie sysctl.

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

Aby wyłączyć OOM-Killera, ustaw wartość 0 w tym samym poleceniu:

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

Wynik tego polecenia nie będzie zapisany na stałe, a jedynie do pierwszego ponownego uruchomienia. Jeśli potrzebujesz większej trwałości, dodaj ten wiersz do pliku /etc/sysctl.conf:

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

Innym sposobem włączania i wyłączania jest zapisanie zmiennej panic_on_oom. Wartość zawsze można sprawdzić w /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Jeśli ustawisz wartość 0, to gdy braknie pamięci, nie wystąpi kernel panic.

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

Jeśli ustawisz wartość 1, to gdy braknie pamięci, wystąpi kernel panic.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killera można nie tylko włączać i wyłączać. Już mówiliśmy, że Linux może zarezerwować dla procesów więcej pamięci, niż jest dostępna, ale nie przydzielać jej na stałe, a to zachowanie kontroluje parametr jądra Linux. Odpowiada za to zmienna vm.overcommit_memory.

Można dla niej ustawić następujące wartości:

0: jądro samo decyduje, czy warto rezerwować zbyt dużo pamięci. To wartość domyślna w większości wersji Linuxa.
1: jądro zawsze będzie rezerwować nadmiarową pamięć. To ryzykowne, ponieważ pamięć może się skończyć, gdyż najprawdopodobniej kiedyś procesy zażądają przysługującej.
2: jądro nie będzie rezerwować więcej pamięci, niż wskazuje parametr overcommit_ratio.

W tym parametrze podajesz procent pamięci, dla którego dopuszczalne jest nadmierne rezerwowanie. Jeśli nie ma dla niego miejsca, pamięć nie jest przydzielana, a rezerwacja jest odrzucana. To najbezpieczniejsza opcja, zalecana dla PostgreSQL. Na OOM-Killera wpływa także inny element - możliwość wymiany, którą kontroluje zmienna cat /proc/sys/vm/swappinessTe wartości wskazują rdzeniowi, jak obsługiwać stronę swap. Im wyższa wartość, tym mniejsze prawdopodobieństwo, że OOM zakończy proces, ale przez operacje I/O negatywnie wpłynie to na bazę danych. I odwrotnie — im niższa wartość, tym większe prawdopodobieństwo ingerencji OOM-Killera, ale wydajność bazy danych również jest wyższa. Wartość domyślna to 60, ale jeśli cała baza danych mieści się w pamięci, lepiej ustawić wartość na 1.

Podsumowanie

Nie pozwól, aby "killer" w OOM-Killer cię przerażał. W tym przypadku killer będzie zbawieniem twojego systemu. "Zabija" najgorsze procesy i ratuje system przed awaryjnym zakończeniem. Aby uniknąć konieczności używania OOM-Killera do zakończenia PostgreSQL, ustaw vm.overcommit_memory wartość na 2. Nie gwarantuje to, że OOM-Killer nie będzie musiał ingerować, ale zmniejszy prawdopodobieństwo przymusowego zakończenia procesu PostgreSQL.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster