Configurando el Out-Of-Memory Killer en Linux para PostgreSQL

Configurando el Out-Of-Memory Killer en Linux para PostgreSQL

Cuando un servidor de base de datos en Linux se cierra inesperadamente, es necesario encontrar la causa. Puede haber varias razones. Por ejemplo, SIGSEGV — un fallo debido a un error en el servidor backend. Pero esto es poco común. La mayoría de las veces, simplemente se agota el espacio en disco o la memoria. Si se acaba el espacio en disco, la única salida es liberar espacio y reiniciar la base de datos.

Out-Of-Memory Killer

Cuando el servidores o proceso se queda sin memoria, Linux ofrece 2 soluciones: colapsar todo el sistema o terminar el proceso (aplicación) que está consumiendo memoria. Es mejor, por supuesto, terminar el proceso y salvar el sistema operativo de un cierre inesperado. En pocas palabras, el Out-Of-Memory Killer es un proceso que finaliza una aplicación para proteger el núcleo de un fallo. Sacrifica la aplicación para preservar el funcionamiento del sistema operativo. Primero, discutamos cómo funciona el OOM y cómo controlarlo, y luego veamos cómo el OOM Killer decide qué aplicación terminar.

Una de las principales tareas de Linux es asignar memoria a los procesos cuando la solicitan. Normalmente, un proceso o aplicación pide memoria al SO, pero no siempre la utiliza por completo. Si el SO empieza a otorgar memoria a todos los que la piden, pero no planean usarla, pronto se agotará la memoria y el sistema fallará. Para evitar esto, el SO reserva memoria para el proceso, pero en realidad no la otorga. La memoria se asigna solo cuando el proceso realmente está a punto de usarla. Ocurre que el SO no tiene memoria libre, pero reserva memoria para el proceso y cuando este la necesita, el SO la asigna, si puede. El inconveniente es que a veces el SO reserva memoria, pero en el momento necesario no hay memoria libre, y el sistema falla. El OOM juega un papel importante en este escenario y termina procesos para proteger el núcleo de un estado de pánico. Cuando se finaliza forzosamente un proceso de PostgreSQL, aparece el siguiente mensaje en el registro:

Fuera de Memoria: Proceso 12345 (postgres) finalizado.

Si hay poca memoria en el sistema y no se puede liberar, se invoca la función out_of_memory. En esta etapa, solo queda una opción: finalizar uno o varios procesos. ¿Deben ser terminados de inmediato por el OOM-killer o se puede esperar? Es obvio que, cuando se invoca out_of_memory, está relacionado con una operación de entrada/salida esperada o con el intercambio de páginas en disco. Por lo tanto, el OOM-killer primero debe realizar verificaciones y, en función de ellas, decidir qué proceso finalizar. Si todas las verificaciones a continuación son positivas, OOM finalizará el proceso.

Selección de proceso

Cuando se acaba la memoria, se llama a la función out_of_memory(). Dentro de ella hay una función select_bad_process(), que recibe una evaluación de la función badness(). Se seleccionará el proceso más "malo". La función badness() elige un proceso según ciertas reglas.

  1. El núcleo necesita un mínimo de memoria para sí mismo.
  2. Es necesario liberar mucha memoria.
  3. No se deben finalizar procesos que utilizan poca memoria.
  4. Es necesario finalizar al menos un par de procesos.
  5. Algoritmos complejos que aumentan las probabilidades de finalizar los procesos que el usuario desea cerrar.

Tras realizar todas estas verificaciones, OOM analiza la evaluación (oom_score). OOM asigna oom_score a cada proceso, y luego multiplica este valor por la cantidad de memoria. Los procesos con valores más altos tienen una mayor probabilidad de convertirse en víctimas del OOM Killer. Los procesos asociados a un usuario privilegiado tienen una evaluación más baja y menos posibilidades de ser finalizados.

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

El identificador del proceso de Postgres es 3813, por lo que en otra terminal se puede obtener la evaluación usando este parámetro del núcleo oom_score:

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

Si realmente no quieres que el OOM-Killer finalice el proceso, hay otro parámetro del núcleo: oom_score_adj. Agrega un valor negativo grande para reducir las posibilidades de que finalicen el proceso que te interesa.

sudo echo -100 > /proc/3813/oom_score_adj

Para establecer el valor oom_score_adj, configura OOMScoreAdjust en el bloque de servicio:

[Service]
OOMScoreAdjust=-1000

O utiliza oomprotect en el comando rcctl.

rcctl set servicename oomprotect -1000

Finalización forzada del proceso

Cuando uno o varios procesos ya han sido seleccionados, el OOM-Killer llama a la función oom_kill_task(). Esta función envía una señal de finalización al proceso. En caso de falta de memoria, oom_kill() llama a esta función para enviar al proceso la señal SIGKILL. Se registra un mensaje en el log del núcleo.

Out of Memory: Proceso terminado [pid] [nombre].

Cómo controlar OOM-Killer

En Linux, OOM-Killer puede ser habilitado y deshabilitado (aunque no se recomienda esto último). Para habilitar y deshabilitar, utiliza el parámetro vm.oom-kill. Para habilitar OOM-Killer en tiempo de ejecución, ejecuta el comando sysctl.

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

Para desactivar OOM-Killer, especifica el valor 0 en este mismo comando:

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

El resultado de este comando no se guardará de manera permanente, solo hasta el primer reinicio. Si necesitas más persistencia, agrega esta línea al archivo /etc/sysctl.conf:

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

Otra forma de habilitar y deshabilitar es escribir la variable panic_on_oom. El valor siempre se puede verificar en /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Si configuras el valor 0, cuando se agote la memoria, no habrá un kernel panic.

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

Si configuras el valor 1, cuando se agote la memoria, ocurrirá un kernel panic.

echo 1 > /proc/sys/vm/panic_on_oom

No solo se puede habilitar y deshabilitar OOM-Killer. Ya hemos mencionado que Linux puede reservar más memoria para los procesos de la que realmente hay, pero no asignarla efectivamente, y este comportamiento es controlado por un parámetro del kernel de Linux. Esto es gestionado por la variable vm.overcommit_memory.

Para esta variable, se pueden especificar los siguientes valores:

0: el kernel decide por sí mismo si se debe reservar demasiada memoria. Este es el valor predeterminado en la mayoría de las versiones de Linux.
1: el kernel siempre reservará memoria adicional. Esto es arriesgado, ya que la memoria puede agotarse, pues es probable que en algún momento los procesos requieran lo que tienen asignado.
2: el kernel no reservará más memoria de la que se especifica en el parámetro overcommit_ratio.

En este parámetro, indicas el porcentaje de memoria para el que se permite la sobre-reserva. Si no hay espacio para ello, no se asignará memoria, y se rechazará la reserva. Esta es la opción más segura, recomendada para PostgreSQL. OOM-Killer también se ve afectado por otro elemento: la posibilidad de intercambio, que es controlada por la variable cat /proc/sys/vm/swappinessEstos valores indican al núcleo cómo manejar el intercambio de páginas. Cuanto mayor sea el valor, menor será la probabilidad de que OOM termine el proceso, pero esto afecta negativamente a la base de datos debido a las operaciones de entrada y salida. Por el contrario, cuanto menor sea el valor, mayor será la probabilidad de que intervenga OOM-Killer, pero también la productividad de la base de datos será mayor. El valor por defecto es 60, pero si toda la base de datos cabe en la memoria, es mejor establecer el valor en 1.

Resultados

No dejes que te asuste el "asesino" en OOM-Killer. En este caso, el asesino será el salvador de tu sistema. Él "mata" los procesos más problemáticos y salva al sistema de un cierre inesperado. Para no tener que utilizar OOM-Killer para terminar PostgreSQL, establece para vm.overcommit_memory el valor 2. Esto no garantiza que OOM-Killer no deba intervenir, pero disminuye la probabilidad de que el proceso PostgreSQL se termine de forma forzada.

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster