Konfigurowanie narzędzia Out-Of-Memory Killer w systemie Linux dla PostgreSQL

Konfigurowanie narzędzia Out-Of-Memory Killer w systemie Linux dla PostgreSQL

Kiedy serwer bazy danych w systemie Linux nieoczekiwanie kończy działanie, należy znaleźć przyczynę. Powodów może być kilka. Na przykład, SIGSEGV — awaria spowodowana błędem na serwerze zaplecza. Ale to jest rzadkie. Najczęściej po prostu brakuje Ci miejsca na dysku lub pamięci. Jeśli zabraknie Ci miejsca na dysku, jest tylko jedno wyjście - zwolnij miejsce i zrestartuj bazę danych.

Zabójca bez pamięci

Gdy w serwerze lub procesie zabraknie pamięci, Linux oferuje 2 rozwiązania: awarię całego systemu lub zakończenie procesu (aplikacji), który pochłania pamięć. Lepiej oczywiście zakończyć proces i uchronić system operacyjny przed awarią. W skrócie Out-Of-Memory Killer to proces, który zabija aplikację, aby uchronić jądro przed awarią. Poświęca aplikację, aby utrzymać działanie systemu operacyjnego. Omówmy najpierw, jak działa OOM i jak nim sterować, a następnie zobaczmy, jak OOM Killer decyduje, którą aplikację zakończyć.

Jednym z głównych zadań Linuksa jest przydzielanie pamięci procesom, gdy o to proszą. Zwykle proces lub aplikacja żąda pamięci od systemu operacyjnego, ale nie wykorzystuje jej w pełni. Jeśli system operacyjny udostępni pamięć każdemu, kto o nią poprosi, ale nie planuje jej używać, wkrótce pamięć się skończy i system ulegnie awarii. Aby tego uniknąć, system operacyjny rezerwuje pamięć dla procesu, ale tak naprawdę jej nie zwalnia. Pamięć jest przydzielana tylko wtedy, gdy proces faktycznie będzie z niej korzystał. Zdarza się, że system operacyjny nie ma wolnej pamięci, ale przydziela ją procesowi, a gdy proces jej potrzebuje, system operacyjny przydziela ją, jeśli może. Minusem jest to, że czasami system operacyjny rezerwuje pamięć, ale we właściwym czasie nie ma wolnej pamięci i system ulega awarii. OOM odgrywa ważną rolę w tym scenariuszu i kończy procesy, aby zapobiec panice jądra. Kiedy proces PostgreSQL zostanie zmuszony do zakończenia, w dzienniku pojawia się komunikat:

Out of Memory: Killed process 12345 (postgres).

Jeżeli w systemie brakuje pamięci i nie można jej zwolnić, funkcja jest wywoływana out_of_memory. Na tym etapie pozostaje jej już tylko jedno – ukończyć jeden lub więcej procesów. Czy OOM-killer powinien natychmiast zakończyć proces, czy może poczekać? Oczywiście wywołanie out_of_memory wynika z oczekiwania na operację we/wy lub stronicowanie na dysk. Dlatego też zabójca OOM musi najpierw przeprowadzić kontrole i na ich podstawie podjąć decyzję o konieczności zakończenia procesu. Jeśli wszystkie poniższe kontrole wypadną pozytywnie, OOM zakończy proces.

Wybór procesu

Gdy skończy się pamięć, funkcja zostanie wywołana out_of_memory(). Ma funkcję select_bad_process(), który otrzymuje ocenę od funkcji badness(). Celem będzie „najgorszy” proces. Funkcjonować badness() wybiera proces według określonych reguł.

  1. Jądro potrzebuje dla siebie minimalnej ilości pamięci.
  2. Musisz zwolnić dużo pamięci.
  3. Nie ma potrzeby kończenia procesów, które zużywają mało pamięci.
  4. Należy ukończyć minimalne procesy.
  5. Złożone algorytmy zwiększające szanse na realizację procesów, które sam użytkownik chce zakończyć.

Po zakończeniu wszystkich tych kontroli OOM sprawdza wynik (oom_score). OOM przydziela oom_score każdego procesu, a następnie mnoży tę wartość przez ilość pamięci. Procesy o większych wartościach częściej padają ofiarą OOM Killera. Procesy powiązane z użytkownikiem root mają niższy wynik i jest mniej prawdopodobne, że zostaną zmuszone do zakończenia.

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

Identyfikator procesu Postgres to 3813, więc w innej powłoce można uzyskać wynik za pomocą tego parametru jądra oom_score:

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

Jeśli nie chcesz, aby OOM-Killer w ogóle zakończył proces, istnieje inna opcja jądra: oom_score_adj. Dodaj dużą wartość ujemną, aby zmniejszyć szanse na zakończenie cenionego procesu.

sudo echo -100 > /proc/3813/oom_score_adj

Aby ustawić wartość oom_score_adj, ustaw OOMScoreAdjust w bloku serwisowym:

[Service]
OOMScoreAdjust=-1000

Albo użyj oomprotect w zespole rcctl.

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

Wymuś zakończenie procesu

Gdy jeden lub więcej procesów jest już wybranych, OOM-Killer wywołuje tę funkcję oom_kill_task(). Funkcja ta wysyła do procesu sygnał zakończenia. W przypadku braku pamięci oom_kill() Wywołuje tę funkcję, aby wysłać do procesu sygnał SIGKILL. Komunikat jest zapisywany w dzienniku jądra.

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

Jak kontrolować OOM-Killer

W systemie Linux możesz włączyć lub wyłączyć OOM-Killer (chociaż to drugie nie jest zalecane). Aby włączyć lub wyłączyć, użyj parametru vm.oom-kill. Aby włączyć OOM-Killer w czasie wykonywania, uruchom polecenie sysctl.

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

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

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

Wynik tego polecenia nie zostanie zapisany na zawsze, ale tylko do pierwszego ponownego uruchomienia. Jeśli potrzebujesz większej trwałości, dodaj tę linię do pliku /etc/sysctl.conf:

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

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

$ cat /proc/sys/vm/panic_on_oom
0

Jeśli ustawisz wartość na 0, to gdy skończy się pamięć, nie będzie paniki jądra.

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

Jeśli ustawisz wartość na 1, gdy skończy się pamięć, nastąpi panika jądra.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer można nie tylko włączać i wyłączać. Powiedzieliśmy już, że Linux może zarezerwować dla procesów więcej pamięci niż jest dostępna, bez jej faktycznego przydzielania, a zachowanie to jest kontrolowane przez parametr jądra Linuksa. Zmienna jest za to odpowiedzialna vm.overcommit_memory.

Możesz określić dla niego następujące wartości:

0: Jądro samo decyduje, czy zarezerwować zbyt dużo pamięci. Jest to ustawienie domyślne w większości wersji Linuksa.
1: Jądro zawsze rezerwuje dodatkową pamięć. Jest to ryzykowne, ponieważ może zabraknąć pamięci, bo najprawdopodobniej pewnego dnia procesy będą jej potrzebować.
2: jądro nie zarezerwuje więcej pamięci niż określono w parametrze overcommit_ratio.

Za pomocą tego parametru określa się procent pamięci, która może zostać nadmiernie zarezerwowana. Jeśli nie będzie na to miejsca, pamięć nie zostanie przydzielona, ​​a rezerwacja zostanie odrzucona. Jest to najbezpieczniejsza opcja zalecana dla PostgreSQL. Na OOM-Killer wpływa jeszcze jeden element – ​​możliwość zamiany, która jest kontrolowana przez zmienną cat /proc/sys/vm/swappiness. Wartości te mówią jądru, jak obsługiwać stronicowanie. Im wyższa wartość, tym mniejsze prawdopodobieństwo, że OOM zakończy proces, ale ze względu na operacje we/wy ma to negatywny wpływ na bazę danych. I odwrotnie – im niższa wartość, tym większe prawdopodobieństwo interwencji OOM-Killer, ale wydajność bazy danych też 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.

Wyniki

Nie pozwól, aby „zabójca” w OOM-Killer Cię przestraszył. W tym przypadku zabójca będzie zbawicielem Twojego systemu. „Zabija” najgorsze procesy i chroni system przed awarią. Aby uniknąć konieczności używania OOM-Killer do zakończenia PostgreSQL, ustaw na vm.overcommit_memory wartość 2. Nie gwarantuje to, że OOM-Killer nie będzie musiał interweniować, ale zmniejszy prawdopodobieństwo wymuszenia zakończenia procesu PostgreSQL.

Źródło: www.habr.com

Dodaj komentarz