Linux > Como evitar que serviço seja finalizado pelo OOM Killer

4546 Views
Tempo de leitura: 4 Minutos 
Atualizado em:

O OOM Killer é um recurso do Linux Kernel que, em situações de sobrecarga de memória, é chamado pelo Kernel para finalizar serviços que demandem maior consumo do recurso. É tipo um carrasco.

Ele possui um conceito chamado Heurística de Maldade que, a partir de determinadas regras, calcula a maldade de um PID quanto ao consumo de memória.

Sabemos que cada PID representa parte ou a totalidade de um serviço em execução no sistema, mas para o OOM Killer tudo é PID. Não existe serviço importante. Se é ofensor, pode ser morto.

OOM-Killer significa Out-of-Memory Killer, ou Assassino de Esgotadores de Memória. OOM-Killer não tem amigos, e ele te odeia. Ele odeia todo mundo. Me odeia tb.

O OOM incrementa uma pontuação para cada PID durante o tempo de vida desses PIDs. Essa pontuação vai de 0 à 1000.

Se um PID consumir toda memória permitida à ele, a pontuação dele será 1000. Se consumir metade da memória permitida, será 500.

O fato de um serviço chegar ao limite de memória permitida não é determinante para o seu encerramento através do OOM Killer, mas se faltar memória para o sistema com certeza será.

Quando o OOM-Killer entra em ação?

Em determinadas situações, principalmente quando ocorrem sobrecargas no consumo de memória, o OOM Killer detecta os PIDs com maiores pontuação e senta o aço. Sem dó. Pode ser um Webserver, Banco de Dados, etc, seja o que for, vai ser encerrado.

Contudo, é possível impedir que determinados PIDs sejam finalizados pelo OOM decrementando a pontuação dos PIDs desse serviço, mantendo a Heurística de Maldade com valor negativo para esses PIDs ou no máximo zerada.

Problemas que o OOM Killer pode causar

Dentro das regras de negócios, determinados serviços são cruciais para o Core Business das empresas, e é muito importante garantir que esses serviços estejam sempre no ar.

Um banco de dados como o MySQL ou PostgreSQL que esteja transacionando dados e que seja subitamente encerrado pelo OOM Killer pode ter tabelas corrompidas. Alguns engines como o InnoDB do MySQL possuem recursos para recuperação automática, mas esse não é o tipo de coisa que você deseja precisar.

Além do básico, que é otimizar serviços importantes e o próprio sistema operacional com tunings e hardenings a fim de evitar sobrecargas, é preciso, decrementar a pontuação desses serviços para garantir que o OOM Killer os desconsidere.

Evitando que o OOM Killer encerre serviços

Enrolei, mas aqui está. Veremos a seguir como evitar que o OOM Killer finalize serviços importantes.

Primeiro, saibamos que todo PID possui um arquivo como este:

cat /proc/1234/oom_score_adj
678
O valor 678 deste exemplo é a pontuação do PID número 1234.

Para definir que esse PID esteja fora do OOM-Killer, basta setar um valor entre -1000 e 1000. Pode-se fazer isso da seguinte forma:

echo -1000 > /proc/1234/oom_score_adj

Ao setar -1000, mesmo que o PID consuma todo o limite de memória permitida à ele, o que o deixaria com valor 1000 na Heurística de Maldade uma vez que o OOM-Killer continuará incrementando sua pontuação, o valor máximo de pontuação que esse PID chegará será 0 (Zero).

Automatizando a retirada de serviços do OOM-Killer

Observe que aplicar -1000 para um PID não o faz completamente excluído do OOM-Killer, pois a pontuação desse PID pode chegar a zero. O OOM-Killer encontrará outros PIDs para matar, mas se seu serviço for o real ofensor do sistema e a sobrecarga persistir, uma hora ou outra, sob certas circunstâncias, o OOM-Killer poderá finalizar seu serviço.

Para evitar que isso ocorra é importante manter o valor -1000 no(s) PID(s) que se deseja deixar fora do OOM. Para isso um Cronjob rodando de tempos em tempos reaplicando o valor -1000 é uma boa solução.

Para isso seria preciso:

    01 – Identificar todos PIDs necessários;
    02 – Colocá-los em um looping com for ou while;
    03 – Schedular no Crontab.

Vejamos passo a passo:

01 – Identificar todos PIDs necessários:

Alguns serviços possuem somente 1 PID. Outros são compostos por diversos PIDs. Sabemos que precisamos aplicar valor -1000 para cada PID que compõe o serviço, sendo um ou vários.

Vamos obter o PID com pgrep

pgrep mysql
12345

Agora com ps aux:

ps aux | grep mysql | grep -v grep | awk '{print$2}'
759
1567
1568

Veja qual o atende mais apropriadamente e o utilize.

Usei o MySQL como exemplo, mas você deve trocar o MySQL pelo serviço que deseja retirar do OOM-Killer.

02 – Colocar em um looping;

Usando o comando acima, podemos fazer laços com for ou while como nos exemplos destacados a seguir:

Usando for:

for PID in $(pgrep mysql); do echo -1000 > /proc/${PID}/oom_score_adj; done

Usando while:

pgrep mysql | while read PID; do echo -1000 > /proc/${PID}/oom_score_adj; done

03 – Schedular no Crontab

Com posse de um single-line funcional como esses laços, basta schedular um job no Crontab. Aqui no Blog há um artigo bem legal sobre Crontab. Segue o link:

https://www.blogporta80.com.br/2014/12/28/artigos-trabalhando-com-crontab-2

Considerações finais

Não entenda o OOM-Killer como um vilão. Muito pelo contrário, ele é um aliado do sistema operacional Linux. O fato de ele entrar em ação nos mostra que nossos ambientes estão com algum tipo de problema, e que precisamos intervir para diagnosticar e resolver na raiz.

Retirar serviços importantes do OOM-Killer é uma boa prática, com toda certeza, mas entender por que o sistema está sobrecarregando é fundamental

Espero ter ajudado de alguma forma. E se chegou até aqui, curte o post, um abraço e até a próxima.

17 - 0

Thank You For Your Vote!

Sorry You have Already Voted!