Configuración del cancelador de procesos por falta de memoria de Linux

por Robert Chase
Publicado en febrero de 2013

En este artículo se describe el cancelador de procesos por falta de memoria de Linux, o cancelador OOM (out-of-memory), y se explica cómo se puede averiguar por qué canceló un proceso concretó. También se proporcionan métodos para configurar el cancelador OOM de forma que se adapte mejor a las necesidades de muchos entornos diferentes.

Acerca del cancelador OOM

Cuando se bloquea un servidor que respalda a un servidor de base de datos o de aplicaciones, hay que volver a poner en marcha rápidamente los servicios esenciales, especialmente si se trata de un sistema de producción importante. Al intentar determinar la causa raíz después de la evaluación inicial, suele ser un misterio por qué la aplicación o la base de datos dejaron de funcionar súbitamente. En algunas situaciones, la causa raíz del problema puede deberse a que el sistema tuviera poca memoria disponible y eso llevara a la cancelación de un proceso importante para mantener el sistema en funcionamiento.

El kernel de Linux asigna memoria según la demanda de las aplicaciones que se ejecutan en el sistema. Dado que muchas aplicaciones asignan su memoria por adelantado y, a menudo, no utilizan la memoria asignada, se diseñó el kernel con la capacidad de confirmar más memoria de la necesaria (confirmación en exceso), para que el uso de la memoria sea más eficiente. Este modelo de confirmación en exceso permite que el kernel asigne más memoria de la que realmente tiene físicamente disponible. Si un proceso utiliza realmente la memoria que le fue asignada, el kernel proporciona estos recursos a la aplicación. Cuando demasiadas aplicaciones empiezan a utilizar la memoria que se les asignó, el modelo de confirmación en exceso se vuelve problemático, y el kernel tiene que empezar a cancelar procesos para mantenerse operativo. El mecanismo que el kernel utiliza para recuperar memoria en el sistema se conoce como cancelador de procesos por falta de memoria o, en forma abreviada, Cancelador OOM (de Out-of-Memory).

Determinar por qué se canceló un proceso

Al solucionar un problema relacionado con una aplicación cancelada por el cancelador OOM, hay varias pistas que puede ayudar a entender cómo y por qué se canceló el proceso. En el siguiente ejemplo, vamos a echar un vistazo al registro del sistema (syslog) para tratar de localizar el origen del problema. El cancelador OOM canceló el proceso oracle por falta de memoria. La K mayúscula de Killed indica que el proceso finalizó con una señal -9, y esta suele ser una buena indicación de que el culpable es el cancelador OOM.




grep -i kill /var/log/messages*
host kernel: Out of Memory: Killed process 2592 (oracle).


También podemos examinar el estado de uso de la memoria alta y la memoria baja en un sistema. Es importante tener en cuenta que estos valores se obtienen en tiempo real y cambian según la carga de trabajo del sistema, por lo que deberían observarse con frecuencia antes de que se llegue a la situación de falta de memoria. Mirar estos valores después de que se haya eliminado un proceso no es muy esclarecedor, por lo que en realidad no es de gran ayuda a la ahora de investigar problemas de OOM.




[root@test-sys1 ~]# free -lm
             total       used       free     shared    buffers     cached
Mem:           498         93        405          0         15         32
Low:           498         93        405
High:            0          0          0
-/+ buffers/cache:         44        453
Swap:         1023          0       1023


En esta máquina virtual de prueba hay tan solo 498 MB de memoria libre. El sistema no usa intercambio. El conmutador -l muestra estadísticas de memoria alta y baja, y el conmutador -m muestra la salida en megabytes, para facilitar su lectura.




[root@test-sys1 ~]# egrep 'High|Low' /proc/meminfo
HighTotal:             0 kB
HighFree:              0 kB
LowTotal:         510444 kB
LowFree:          414768 kB

Se pueden obtener los mismos datos examinando /proc/memory y buscando concretamente los valores altos y bajos. Sin embargo, con este método no obtenemos información de intercambio de la salida y, por otra parte, la salida se muestra en kilobytes.

La memoria baja es la zona de la memoria a la que el kernel tiene acceso físico directo. La memoria alta es una zona de la memoria para la que el kernel no tiene una dirección de acceso físico, por lo que se asigna mediante una dirección virtual. En los sistemas antiguos de 32 bits reconocerá la memoria baja y la memoria alta por la forma en que se asigna la memoria a una dirección virtual. En plataformas de 64 bits, el espacio de direcciones virtuales no es necesario. Toda la memoria del sistema se mostrará como memoria baja.

Aunque examinar /proc/memory y utilizar el comando free son formas útiles de saber cuál es el uso "en ese momento" de la memoria, a veces queremos ver el uso de la memoria durante un período de tiempo. Para esto es muy útil el comando vmstat.

En el ejemplo del Listado 1 utilizamos el comando vmstat para mirar nuestros recursos 10 veces cada 45 segundos. El conmutador -S muestra los datos en una tabla y el conmutador -M muestra la salida en megabytes, para facilitar su lectura. Como se puede ver, hay algo que consume la memoria disponible, pero en este ejemplo aún no se utiliza el intercambio.




[root@localhost ~]# vmstat -SM 45 10
procs -----------memory-------- ---swap-- -----io-- --system-- ----cpu---------
 r  b   swpd  free  buff  cache  si   so   bi   bo   in    cs us  sy  id  wa st
 1  0      0   221   125     42   0    0    0    0   70     4  0   0  100  0  0
 2  0      0   192   133     43   0    0  192   78  432  1809  1  15   81   2 0
 2  1      0    85   161     43   0    0  624  418 1456  8407  7  73    0  21 0
 0  0      0    65   168     43   0    0  158  237  648  5655  3  28   65   4 0
 3  0      0    64   168     43   0    0    0    2 1115 13178  9  69   22   0 0
 7  0      0    60   168     43   0    0    0    5 1319 15509 13  87    0   0 0
 4  0      0    60   168     43   0    0    0    1 1387 15613 14  86    0   0 0
 7  0      0    61   168     43   0    0    0    0 1375 15574 14  86    0   0 0
 2  0      0    64   168     43   0    0    0    0 1355 15722 13  87    0   0 0
 0  0      0    71   168     43   0    0    0    6  215  1895  1   8   91   0 0


Listado 1

La salida de vmstat se puede redirigir a un archivo mediante el siguiente comando. Incluso se puede ajustar la duración y el número de veces para supervisar por más tiempo. Mientras se ejecuta el comando, podemos abrir el archivo de salida siempre que queramos para ver los resultados.

En el siguiente ejemplo vemos la memoria 1000 veces cada 120 segundos. El signo & al final de la línea nos permite ejecutar esto como un proceso y recuperar el control del terminal.

vmstat -SM 120 1000 > memoryusage.out &

Como referencia, el Listado 2 muestra una sección de la página de manual de vmstat que proporciona información adicional sobre el resultado del comando. Es únicamente la información relacionada con la memoria; el comando proporciona además información sobre el uso de E/S de disco y CPU.




   Memory
       swpd: the amount of virtual memory used.
       free: the amount of idle memory.
       buff: the amount of memory used as buffers.
       cache: the amount of memory used as cache.
       inact: the amount of inactive memory. (-a option)
       active: the amount of active memory. (-a option)

   Swap
       si: Amount of memory swapped in from disk (/s).
       so: Amount of memory swapped to disk (/s).

Listado 2

Están disponibles otras herramientas de supervisión de la memoria y el rendimiento del sistema para investigar problemas de este tipo. Herramientas como sar (System Activity Reporter) y dtrace (Dynamic Tracing) son muy útiles para recopilar datos específicos sobre el rendimiento del sistema a lo largo del tiempo. Para conseguir mayor visibilidad, puede usar las sondas de estabilidad y de estabilidad de datos de dtrace, que incluyen un desencadenador para condiciones OOM que se activan cuando el kernel cancela un proceso por falta de memoria. Se incluye más información sobre dtrace y sar en la sección "Véase también" de este artículo.

Hay varios factores que pueden provocar un evento OOM, además de que el sistema se esté quedando sin memoria RAM y sin espacio de intercambio disponible debido a la carga de trabajo. Es posible que el kernel no pueda utilizar el espacio de intercambio de forma óptima debido al tipo de carga de trabajo en el sistema. Las aplicaciones que utilizan mlock() o HugePages tienen memoria que no se puede intercambiar con el disco cuando el sistema empieza a quedarse sin memoria física. Las estructuras de datos del kernel también pueden ocupar demasiado espacio, agotando la memoria del sistema y provocando una situación OOM. Muchos sistemas basados en la arquitectura NUMA pueden experimentar condiciones OOM cuando un nodo se queda sin memoria y activa un alerta de OOM en el kernel, aunque quede mucha memoria en los nodos restantes. Encontrará más información sobre las condiciones OOM en equipos con arquitectura NUMA en la sección "Véase también" de este artículo.

Configuración del cancelador OOM

El cancelador OOM de Linux tiene varias opciones de configuración que permiten a los desarrolladores elegir cómo se comportará el sistema cuando se enfrente a una situación de falta de memoria. Estas opciones de configuración y selecciones varían según el entorno y las aplicaciones que el sistema tenga configuradas.

Nota: se recomienda hacer las pruebas y el ajuste en un entorno de desarrollo antes de realizar cambios en sistemas de producción importantes.

En algunos entornos, cuando un sistema ejecuta una única tarea esencial, reiniciar cuando se produce una situación OOM en el sistema puede ser una opción viable para restablecer rápidamente el estado operativo del sistema, sin intervención del administrador. Aunque no es un enfoque óptimo, la lógica subyacente es que si nuestra aplicación no puede funcionar porque fue cancelada por el cancelador OOM, entonces un reinicio del sistema restablecerá la aplicación si se inicia con el sistema en el momento de arranque. Si un administrador inicia manualmente la aplicación, esta opción no ofrece ninguna ventaja.

Las siguientes opciones de configuración harán que, ante una situación de falta de memoria, se produzca un error irrecuperable del sistema y se reinicie. Los comandos sysctl lo establecerán en tiempo real. Si se anexa la configuración a sysctl.conf, estas opciones persistirán al reiniciar. La X de kernel.panic indica el número de segundos que deben transcurrir antes de que se reinicie el sistema. Se debe ajustar esta configuración en función de las necesidades del entorno.




sysctl vm.panic_on_oom=1
sysctl kernel.panic=X
echo "vm.panic_on_oom=1" >> /etc/sysctl.conf
echo "kernel.panic=X" >> /etc/sysctl.conf


También podemos ajustar la forma en que el cancelador OOM gestiona las situaciones de OOM con determinados procesos. Veamos, por ejemplo, el proceso oracle 2592 que se canceló anteriormente. Si queremos que sea menos probable que el cancelador OOM cancele el proceso oracle, podemos hacer lo siguiente.

echo -15 > /proc/2592/oom_adj

Podemos hacer que sea más probable que el cancelador OOM cancele el proceso oracle. Para ello, hacemos lo siguiente.

echo 10 > /proc/2592/oom_adj

Si queremos excluir el proceso oracle del cancelador OOM, podemos hacer lo siguiente para excluirlo por completo del cancelador OOM. Es importante tener en cuenta que esto puede causar un comportamiento inesperado, en función de los recursos y la configuración del sistema. Si el kernel no puede cancelar un proceso que consume una gran cantidad de memoria, cancelará otros procesos disponibles. Algunos de esos procesos pueden ser procesos importantes del sistema operativo y, en última instancia, su cancelación puede hacer que el sistema se bloquee.

echo -17 > /proc/2592/oom_adj

Podemos establecer intervalos válidos para oom_adj desde -16 hasta +15. Una configuración -17 exime completamente a un proceso de la acción del cancelador OOM. Cuanto mayor sea el número, más probable será que se seleccione el proceso para su cancelación si el sistema se encuentra en una situación de falta de memoria. También se puede examinar el contenido de /proc/2592/oom_score para determinar la probabilidad de que el cancelador OOM cancele un proceso. Una puntuación de 0 es una indicación de que el proceso no puede ser cancelado por el cancelador OOM. Cuanto mayor sea la puntuación de OOM, más probable será la cancelación del proceso en una situación de falta de memoria.

El cancelador OOM se puede desactivar por completo con el siguiente comando. Esto no se recomienda para entornos de producción. Si se presenta una situación de falta de memoria, puede producirse un comportamiento inesperado en función de los recursos del sistema disponibles y de la configuración. Este comportamiento inesperado puede ser cualquier cosa, desde un error irrecuperable del kernel hasta un bloqueo, en función de los recursos disponibles para el kernel en el momento de la situación de falta de memoria.




sysctl vm.overcommit_memory=2
echo "vm.overcommit_memory=2" >> /etc/sysctl.conf

Para algunos entornos, estas opciones de configuración no son óptimas y es posible que sea necesario realizar cambios y ajustes. La configuración de HugePages para el kernel puede ayudar con los problemas de falta de memoria según las necesidades de las aplicaciones que se ejecutan en el sistema.

Véase también

Estos son algunos recursos adicionales sobre HugePages, dtrace, sar y OOM para arquitecturas NUMA:

Acerca del Autor

Robert Chase es miembro del equipo de gestión del producto Oracle Linux. Es un miembro activo de la comunidad Linux y de software de código abierto desde 1996. Ha trabajado con sistemas tan pequeños como dispositivos integrados y con hardware de grandes dimensiones, como supercomputadoras.

Revision 1.0, 02/19/2013