Configurando Out-Of-Memory Killer en Linux para PostgreSQL

Configurando Out-Of-Memory Killer en Linux para PostgreSQL

Cando un servidor de bases de datos se pecha de forma inesperada en Linux, cómpre atopar o motivo. Pode haber varias razóns. Por exemplo, SIGSEGV — fallo debido a un erro no servidor backend. Pero isto é raro. Na maioría das veces, simplemente queda sen espazo en disco ou memoria. Se queda sen espazo no disco, só hai unha saída: liberar espazo e reiniciar a base de datos.

Asasino sen memoria

Cando un servidor ou proceso queda sen memoria, Linux ofrece 2 solucións: bloquear todo o sistema ou finalizar o proceso (a aplicación) que está consumindo memoria. É mellor, por suposto, rematar o proceso e salvar o sistema operativo de falla. En poucas palabras, Out-Of-Memory Killer é un proceso que mata unha aplicación para salvar o núcleo de falla. Sacrifica a aplicación para manter o SO funcionando. Imos primeiro discutir como funciona OOM e como controlalo, e despois vexamos como OOM Killer decide que aplicación finalizar.

Unha das principais tarefas de Linux é asignar memoria aos procesos cando a pidan. Normalmente, un proceso ou aplicación solicita memoria do SO, pero non a utiliza completamente. Se o sistema operativo dá memoria a todos os que a solicitan pero non teñen pensado usala, moi pronto a memoria esgotarase e o sistema fallará. Para evitalo, o sistema operativo reserva memoria para o proceso, pero non a libera. A memoria atribúese só cando un proceso realmente vai usala. Acontece que o SO non ten memoria libre, pero atribúe memoria a un proceso e, cando un proceso o necesita, o sistema operativo asígnaa se pode. A desvantaxe é que ás veces o sistema operativo reserva memoria, pero no momento adecuado non hai memoria libre e o sistema falla. OOM xoga un papel importante neste escenario e remata os procesos para evitar que o núcleo entre en pánico. Cando se obriga a finalizar un proceso PostgreSQL, aparece unha mensaxe no rexistro:

Out of Memory: Killed process 12345 (postgres).

Se o sistema ten pouca memoria e non se pode liberar, chámase a función out_of_memory. Nesta fase, só lle queda unha cousa por facer: completar un ou máis procesos. OOM-killer debería finalizar o proceso inmediatamente ou pode esperar? Obviamente, cando se chama out_of_memory, débese á espera dunha operación de E/S ou de paginación no disco. Polo tanto, o asasino de OOM debe realizar primeiro comprobacións e, en función delas, decidir que o proceso debe rematar. Se todas as comprobacións seguintes son positivas, OOM finalizará o proceso.

Proceso de selección

Cando se esgota a memoria, chámase a función out_of_memory(). Ten unha función select_bad_process(), que recibe unha avaliación da función badness(). O "peor" proceso será dirixido. Función badness() selecciona un proceso segundo determinadas regras.

  1. O núcleo necesita un mínimo de memoria para si mesmo.
  2. Necesitas liberar moita memoria.
  3. Non hai necesidade de finalizar procesos que usan pouca memoria.
  4. Hai que completar uns procesos mínimos.
  5. Algoritmos complexos que aumentan as posibilidades de finalización daqueles procesos que o propio usuario quere completar.

Despois de completar todas estas comprobacións, OOM examina a puntuación (oom_score). OOM asigna oom_score cada proceso e, a continuación, multiplica este valor pola cantidade de memoria. Os procesos con valores maiores teñen máis probabilidades de ser vítimas do asasino OOM. Os procesos asociados co usuario root teñen unha puntuación máis baixa e é menos probable que se vexan obrigados a finalizar.

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

O ID do proceso de Postgres é 3813, polo que noutro shell é posible obter a puntuación usando este parámetro do núcleo oom_score:

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

Se non queres que OOM-Killer mate o proceso en absoluto, hai outra opción do núcleo: oom_score_adj. Engade un gran valor negativo para reducir as posibilidades de completar un proceso que valoras.

sudo echo -100 > /proc/3813/oom_score_adj

Para establecer un valor oom_score_adj, establece OOMScoreAdjust no bloque de servizo:

[Service]
OOMScoreAdjust=-1000

Ou use oomprotect nun equipo rcctl.

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

Forzar a terminación dun proceso

Cando xa están seleccionados un ou máis procesos, OOM-Killer chama a función oom_kill_task(). Esta función envía un sinal de terminación ao proceso. En caso de escaseza de memoria oom_kill() Chama a esta función para enviar un sinal SIGKILL ao proceso. Escríbese unha mensaxe no rexistro do núcleo.

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

Como controlar OOM-Killer

En Linux, pode activar ou desactivar OOM-Killer (aínda que este último non é recomendable). Para activar ou desactivar use o parámetro vm.oom-kill. Para activar OOM-Killer no tempo de execución, execute o comando sysctl.

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

Para desactivar OOM-Killer, especifique o valor 0 no mesmo comando:

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

O resultado deste comando non se gardará para sempre, senón só ata o primeiro reinicio. Se necesitas máis persistencia, engade esta liña ao ficheiro /etc/sysctl.conf:

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

Outra forma de activar e desactivar é escribir unha variable panic_on_oom. O valor sempre se pode rexistrar /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Se estableces o valor en 0, cando se esgote a memoria, non haberá pánico no núcleo.

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

Se estableces o valor en 1, cando a memoria se esgota, producirase un pánico no núcleo.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer non só se pode activar e desactivar. Xa dixemos que Linux pode reservar máis memoria para os procesos da que está dispoñible sen asignala realmente, e este comportamento está controlado por un parámetro do núcleo de Linux. A variable é responsable disto vm.overcommit_memory.

Podes especificar os seguintes valores para iso:

0: O propio núcleo decide se se reserva demasiada memoria. Este é o predeterminado na maioría das versións de Linux.
1: O núcleo sempre reservará memoria extra. Isto é arriscado, porque a memoria pode esgotarse, porque, moi probablemente, algún día os procesos o requiran.
2: o núcleo non reservará máis memoria da especificada no parámetro overcommit_ratio.

Con este parámetro, especifica a porcentaxe de memoria que se permite reservar en exceso. Se non hai espazo para iso, non se asigna memoria e denegarase a reserva. Esta é a opción máis segura recomendada para PostgreSQL. OOM-Killer vese afectado por outro elemento: a capacidade de intercambio, que está controlada pola variable cat /proc/sys/vm/swappiness. Estes valores indican ao núcleo como xestionar a paginación. Canto maior sexa o valor, menos probable é que OOM remate o proceso, pero debido ás operacións de E/S ten un impacto negativo na base de datos. E viceversa: canto menor sexa o valor, maior é a probabilidade de intervención OOM-Killer, pero o rendemento da base de datos tamén é maior. O valor predeterminado é 60, pero se toda a base de datos cabe na memoria, é mellor establecer o valor en 1.

Resultados de

Non deixes que o "asasino" en OOM-Killer te asuste. Neste caso, o asasino será o salvador do teu sistema. "Mata" os peores procesos e salva o sistema de falla. Para evitar ter que usar OOM-Killer para finalizar PostgreSQL, configure en vm.overcommit_memory valor 2. Isto non garante que OOM-Killer non teña que intervir, pero reducirá a probabilidade de forzar a terminación do proceso PostgreSQL.

Fonte: www.habr.com

Engadir un comentario