Configurando Out-Of-Memory Killer en Linux para PostgreSQL

Configurando Out-Of-Memory Killer en Linux para PostgreSQL

Cuando un servidor de base de datos se cierra inesperadamente en Linux, es necesario encontrar el motivo. Puede haber varias razones. Por ejemplo, SIGSEGV — falla debido a un error en el servidor backend. Pero esto es raro. La mayoría de las veces, simplemente te quedas sin espacio en disco o sin memoria. Si se queda sin espacio en el disco, solo hay una salida: liberar espacio y reiniciar la base de datos.

Asesino sin memoria

Cuando un servidor o proceso se queda sin memoria, Linux ofrece 2 soluciones: bloquear todo el sistema o finalizar el proceso (aplicación) que está consumiendo memoria. Por supuesto, es mejor finalizar el proceso y evitar que el sistema operativo falle. En pocas palabras, Out-Of-Memory Killer es un proceso que mata una aplicación para evitar que el kernel falle. Sacrifica la aplicación para mantener el sistema operativo en funcionamiento. Primero analicemos cómo funciona OOM y cómo controlarlo, y luego veamos cómo OOM Killer decide qué aplicación finalizar.

Una de las principales tareas de Linux es asignar memoria a los procesos cuando estos la solicitan. Normalmente, un proceso o aplicación solicita memoria del sistema operativo, pero no la utiliza por completo. Si el sistema operativo entrega memoria a todos los que la solicitan pero no planean usarla, muy pronto la memoria se agotará y el sistema fallará. Para evitar esto, el sistema operativo reserva memoria para el proceso, pero en realidad no la libera. La memoria se asigna sólo cuando un proceso realmente la va a utilizar. Sucede que el SO no tiene memoria libre, pero le asigna memoria a un proceso, y cuando un proceso la necesita, el SO se la asigna si puede. La desventaja es que a veces el sistema operativo reserva memoria, pero en el momento adecuado no queda memoria libre y el sistema falla. OOM juega un papel importante en este escenario y finaliza los procesos para evitar que el kernel entre en pánico. Cuando se fuerza la finalización de un proceso de PostgreSQL, aparece un mensaje en el registro:

Out of Memory: Killed process 12345 (postgres).

Si el sistema tiene poca memoria y no se puede liberar, se llama a la función out_of_memory. En esta etapa, sólo le queda una cosa por hacer: completar uno o más procesos. ¿Debería OOM-killer finalizar el proceso inmediatamente o puede esperar? Obviamente, cuando se llama a out_of_memory, se debe a que se espera una operación de E/S o una paginación en el disco. Por lo tanto, el asesino de OOM primero debe realizar comprobaciones y, en función de ellas, decidir que es necesario finalizar el proceso. Si todas las comprobaciones siguientes son positivas, OOM finalizará el proceso.

Selección de proceso

Cuando se agota la memoria, se llama a la función. out_of_memory(). tiene una funcion select_bad_process(), que recibe una evaluación de la función badness(). El “peor” proceso será el objetivo. Función badness() selecciona un proceso de acuerdo con ciertas reglas.

  1. El núcleo necesita una memoria mínima para sí mismo.
  2. Necesitas liberar mucha memoria.
  3. No es necesario finalizar procesos que utilizan poca memoria.
  4. Es necesario completar procesos mínimos.
  5. Algoritmos complejos que aumentan las posibilidades de finalización de aquellos procesos que el propio usuario quiere completar.

Una vez completadas todas estas comprobaciones, OOM examina la puntuación (oom_score). OOM asigna oom_score cada proceso y luego multiplica este valor por la cantidad de memoria. Los procesos con valores mayores tienen más probabilidades de ser víctimas del OOM Killer. Los procesos asociados con el usuario root tienen una puntuación más baja y es menos probable que se vean obligados a finalizar.

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

El ID del proceso de Postgres es 3813, por lo que en otro shell es posible obtener la puntuación utilizando este parámetro del kernel. oom_score:

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

Si no desea que OOM-Killer finalice el proceso en absoluto, existe otra opción del kernel: oom_score_adj. Agregue un valor negativo grande para reducir las posibilidades de completar un proceso que valora.

sudo echo -100 > /proc/3813/oom_score_adj

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

[Service]
OOMScoreAdjust=-1000

O usar oomprotect en un equipo rcctl.

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

Forzar la terminación de un proceso

Cuando uno o más procesos ya están seleccionados, OOM-Killer llama a la función oom_kill_task(). Esta función envía una señal de terminación al proceso. En caso de escasez de memoria oom_kill() Llama a esta función para enviar una señal SIGKILL al proceso. Se escribe un mensaje en el registro del kernel.

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

Cómo controlar OOM-Killer

En Linux, puede habilitar o deshabilitar OOM-Killer (aunque no se recomienda esto último). Para habilitar o deshabilitar use el parámetro vm.oom-kill. Para habilitar OOM-Killer en tiempo de ejecución, ejecute el comando sysctl.

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

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

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

El resultado de este comando no se guardará para siempre, sino sólo hasta el primer reinicio. Si necesita más persistencia, agregue esta línea al archivo /etc/sysctl.conf:

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

Otra forma de habilitar y deshabilitar es escribir una variable panic_on_oom. El valor siempre se puede comprobar /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Si establece el valor en 0, cuando se agote la memoria, no habrá pánico en el kernel.

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

Si establece el valor en 1, cuando se agote la memoria, se producirá un pánico en el kernel.

echo 1 > /proc/sys/vm/panic_on_oom

OOM-Killer no sólo se puede activar y desactivar. Ya hemos dicho que Linux puede reservar más memoria para procesos de la que está disponible sin asignarla realmente, y este comportamiento está controlado por un parámetro del kernel de Linux. La variable es responsable de esto. vm.overcommit_memory.

Puede especificar los siguientes valores para ello:

0: El propio núcleo decide si reservar demasiada memoria. Este es el valor predeterminado en la mayoría de las versiones de Linux.
1: El kernel siempre reservará memoria extra. Esto es arriesgado, porque la memoria puede agotarse, porque, lo más probable es que algún día los procesos la requieran.
2: el kernel no reservará más memoria de la especificada en el parámetro overcommit_ratio.

Con este parámetro, usted especifica el porcentaje de memoria que se permite reservar en exceso. Si no hay espacio para ello no se asigna memoria y se deniega la reserva. Esta es la opción más segura recomendada para PostgreSQL. OOM-Killer se ve afectado por otro elemento: la capacidad de intercambio, que está controlada por la variable cat /proc/sys/vm/swappiness. Estos valores le dicen al kernel cómo manejar la paginación. Cuanto mayor sea el valor, menos probable será que OOM finalice el proceso, pero debido a las operaciones de E/S tiene un impacto negativo en la base de datos. Y viceversa: cuanto menor sea el valor, mayor será la probabilidad de que intervenga OOM-Killer, pero el rendimiento de la base de datos también es mayor. El valor predeterminado es 60, pero si toda la base de datos cabe en la memoria, es mejor establecer el valor en 1.

resultados

No dejes que el "asesino" de OOM-Killer te asuste. En este caso, el asesino será el salvador de su sistema. "Mata" los peores procesos y evita que el sistema falle. Para evitar tener que usar OOM-Killer para terminar PostgreSQL, configúrelo en vm.overcommit_memory valor 2. Esto no garantiza que OOM-Killer no tenga que intervenir, pero reducirá la probabilidad de forzar la finalización del proceso PostgreSQL.

Fuente: habr.com

Añadir un comentario