Pongámonos en la situación teórica de que tenemos un equipo con OS basado en Linux (independientemente de la distribución) con una alta carga de memoria RAM y múltiples servicios en marcha. De repente, el equipo tiene que realizar tareas que le suponen un mayor esfuerzo en términos de memoria y esto hace que al poco tiempo tengamos errores, tales como aplicaciones que misteriosamente se han cerrado solas, o errores más graves; como, por ejemplo, que una base de datos, haya entrado en modo “recovery mode”. ¿Por qué ha ocurrido esto? Este fenómeno proviene del concepto OOM Killer.
OOM Killer, se trata de un mecanismo que posee el kernel para liberar memoria RAM de forma abrupta para evitar el colapso del sistema; es decir que se trata de un mecanismo usado para evitar situaciones críticas, el cual, generalmente, previene de forma adecuada cualquier tipo de saturación del sistema y evita el bloqueo total del equipo/servidor. Desgraciadamente, en equipos con altas cargas de trabajo que poseen algunos servicios críticos (como puede ser PostgreSQL, MySQL o Apache), este mecanismo puede resultar fatal… Para entenderlo, primero hay que saber cómo funciona este mecanismo; o mejor dicho, qué prioridades tiene éste.
Las prioridades de OOM por defecto serían:
- Mantener un mínimo de memoria RAM libre para que el Kernel pueda funcionar correctamente
- Elimina el mínimo número de procesos posibles
- Priorizar procesos que consuman mucha memoria
- No eliminar procesos que consuman poca memoria
- Mediante múltiples algoritmos internos dictaminar qué servicio con mucha memoria eliminar en caso de tener varios para elegir.
Además de esto, OOM revisa el oom_score (puntuación OOM), que revisa si el proceso tiene una mayor o menor prioridad para ser eliminado. Por defecto la mayoría de los procesos tienen una puntuación de 0, es decir que son servicios que ni tienen la prioridad de ser eliminados, ni tampoco tienen ninguna “protección” que les impida ser eliminados. Dicha puntuación se puede ajustar asignarle un valor que puede oscilar entre -1000 y 1000, siendo -1000 el valor que haría que un proceso, jamás se eliminase, y 1000 el valor que haría que dicho proceso fuese eliminado el primero.
Para revisar la puntuación por defecto de un proceso concreto habría que realizar el comando:
cat /proc/numero_proceso/oom_score
Ejemplo:
cat /proc/1032/oom_score0
Si deseásemos ajustar la puntuación de dicho proceso, habría que modificar el fichero /proc/numero_proceso/oom_score_adj, asignándole un valor entre -1000 y 1000, según conveniencia nuestra…
echo -100 > /proc/1032/oom_score_adj
El problema que tiene este método es que es un método de ajuste “en vivo”, es decir que si bien ajustaría la puntuación del proceso, solamente sería valido mientras el proceso estuviese activo; si dicho proceso se parase/reiniciase por cualquier motivo, la puntuación volvería a ser la misma que se tenía originalmente…
Afortunadamente, puede modificar de forma permanente, accediendo servicio de arranque del proceso deseado… Presuponiendo que estemos usando un sistema basado en Systemd, simplemente habría que ir a la ruta /etc/systemd/system/ o a /run/systemd/generator.late/ (dependiendo del servicio) y editar el servicio que deseemos modificar.
Dentro del fichero que estemos editando, habrá diferentes secciones, entre las cuales se encontrará la sección “service”; dentro de dicha sección habría que añadir la línea OOMScoreAdjust= Valor_deseado. Pongamos como ejemplo el servicio apache2.service
[Service]Type=forkingRestart=noTimeoutSec=5minIgnoreSIGPIPE=noKillMode=processGuessMainPID=noRemainAfterExit=yesExecStart=/etc/init.d/apache2 startExecStop=/etc/init.d/apache2 stopExecReload=/etc/init.d/apache2 reload
[Service]OOMScoreAdjust=-100Type=forkingRestart=noTimeoutSec=5minIgnoreSIGPIPE=noKillMode=processGuessMainPID=noRemainAfterExit=yesExecStart=/etc/init.d/apache2 startExecStop=/etc/init.d/apache2 stopExecReload=/etc/init.d/apache2 reload
echo 1 > /proc/sys/vm/panic_on_oom
echo vm.oom-kill = 1 >> /etc/sysctl.conf
Buen post
ResponderEliminar