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:
Información de HugePages en My Oracle Support (requiere registro): HugePages en Linux: qué es... y qué no es... [ID 361323.1]
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