Como configurar o Out-of-Memory Killer do Linux

por Robert Chase
Publicado em fevereiro de 2013

Este artigo descreve o Linux out-of-memory (OOM) killer e como descobrir por que ele encerrou um determinado processo. Ele também fornece métodos para configurar o OOM killer para melhor atender às necessidades de muitos ambientes diferentes.

Sobre o OOM Killer

Quando um servidor que oferece suporte a um banco de dados ou a um servidor de aplicativos fica inativo, geralmente é uma corrida para obter serviços essenciais de volta em funcionamento, especialmente se for um sistema de produção importante. Ao tentar determinar a causa raiz após a triagem inicial, geralmente é um mistério o motivo pelo qual o aplicativo ou banco de dados parou de funcionar repentinamente. Em certas situações, a causa raiz do problema pode ser rastreada até o sistema com pouca memória e interromper um processo importante para permanecer operacional.

O kernel do Linux aloca memória sob demanda dos aplicativos em execução no sistema. Como muitos aplicativos alocam sua memória antecipadamente e geralmente não utilizam a memória alocada, o kernel foi projetado com a capacidade de confirmar excessivamente a memória para tornar seu uso mais eficiente. Esse modelo de confirmação excessiva permite que o kernel aloque mais memória do que realmente tem disponível fisicamente. Se um processo realmente utiliza a memória que foi alocada, o kernel fornece esses recursos ao aplicativo. Quando muitos aplicativos começam a utilizar a memória em que eles foram alocados, o modelo de superalocação às vezes se torna problemático e o kernel deve começar a interromper os processos para permanecer operacional. O mecanismo que o kernel usa para recuperar memória no sistema é conhecido como out-of-memory killer ou OOM killer.

Como descobrir por que um processo foi encerrado

Ao solucionar um problema em que uma aplicação foi encerrada pelo OOM killer, há várias dicas que podem esclarecer como e por que o processo foi encerrado. No exemplo a seguir, vamos analisar nosso syslog descobrir se podemos determinar a causa do problema. O processo oracle oi encerrado pelo OOM killer devido à falta de memória. A letra maiúscula K no Killed indica que o processo foi encerrado com um sinal -9, e isso geralmente é um bom sinal de que o OOM killer pode ser o culpado.




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


Também podemos examinar o status do uso de memória alta e baixa em um sistema. É importante observar que esses valores são em tempo real e mudam dependendo da carga de trabalho do sistema; portanto, eles devem ser observados com frequência antes que ocorra pressão da memória. Analisar esses valores após a interrupção de um processo não será muito perspicaz e, portanto, não pode realmente ajudar na investigação de 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


Nesta máquina virtual de teste, temos 498 MB de pouca memória livre. O sistema não tem uso de troca. A opção -l mostra estatísticas de memória alta e baixa, e a opção -m coloca a saída em megabytes para facilitar a leitura.




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

Os mesmos dados podem ser obtidos examinando /proc/memory e observando especificamente os valores altos e baixos. No entanto, com esse método, não obtemos informações de troca da saída e a saída está em kilobytes.

Pouca memória é a memória à qual o kernel tem acesso físico direto. Memória alta é a memória na qual o kernel não possui um endereço físico direto e, portanto, deve ser mapeado através de um endereço virtual. Em sistemas mais antigos de 32 bits, você verá pouca memória e muita memória devido à maneira como ela é mapeada para um endereço virtual. Em plataformas de 64 bits, o espaço de endereço virtual não é necessário e toda a memória do sistema será mostrada como pouca memória.

Embora olhar para /proc/memory e usar o comando free seja útil para saber "neste momento" qual é o uso de memória, há situações nas quais queremos observar o uso de memória por um período mais longo. O comando vmstat é bastante útil para isso.

No exemplo da Listagem 1, estamos usando o comando vmstat para examinar nossos recursos 10 vezes a cada 45 segundos. A opção -S mostra nossos dados em uma tabela e a opção -M mostra a saída em megabytes para facilitar a leitura. Como você pode ver, algo está consumindo nossa memória livre, mas ainda não estamos trocando neste exemplo.




[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


Listagem 1

A saída do vmstat pode ser redirecionada para um arquivo usando o comando a seguir. Podemos até ajustar a duração e o número de vezes para monitorar por mais tempo. Enquanto o comando está em execução, podemos olhar o arquivo de saída a qualquer momento para ver os resultados.

No exemplo a seguir, examinamos a memória a cada 120 segundos 1000 vezes. O & no final da linha permite executar como um processo e recuperar o nosso terminal.

vmstat -SM 120 1000 > memoryusage.out &

Para referência, a Listagem 2 mostra uma seção da página do manual do vmstat que fornece informações adicionais sobre a saída do comando. Esta é apenas a informação relacionada à memória; o comando fornece informações sobre E/S de disco e uso da CPU também.




   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).

Listagem 2

Existem várias outras ferramentas disponíveis para monitorar a memória e o desempenho do sistema para investigar problemas dessa natureza. Ferramentas como sar (System Activity Reporter) e dtrace (Dynamic Tracing) são bastante úteis para coletar dados específicos sobre o desempenho de sistema no decorrer do tempo. Para obter ainda mais visibilidade, as investigações de estabilidade e estabilidade dos dados de dtrace têm até um gatilho para condições OOM que será acionado se o kernel encerrar um processo devido a um incidente de OOM. Obtenha mais informações sobre dtrace e sar na seção "Veja também" deste artigo.

Há várias coisas que podem fazer um evento OOM diferente do sistema ficar sem memória RAM e espaço de troca disponível devido à carga de trabalho. O kernel pode não ser capaz de utilizar o espaço de troca da melhor maneira devido ao tipo de carga de trabalho no sistema. As aplicações que utilizam mlock() ou HugePages têm memória que não pode ser liberada para o disco quando o sistema está com pouca memória física. As estruturas de dados do kernel também podem ocupar muito espaço, esgotando a memória do sistema e causando uma situação de OOM. Muitos sistemas baseados na arquitetura NUMA podem enfrentar condições de OOM devido a um nó ficar sem memória acionando um OOM no kernel enquanto resta bastante memória nos nós restantes. Mais informações sobre as condições de OOM em máquinas que possuem a arquitetura NUMA podem ser encontradas na seção "Veja Também" deste artigo.

Configuração do OOM Killer

O OOM killer no Linux possui várias opções de configuração que permitem aos desenvolvedores escolher como o sistema deve se comportar em caso de memória insuficiente. Essas configurações e opções variam de acordo com o ambiente e os aplicativos que o sistema configurou nele.

Observação: É recomendável que testes e ajustes sejam realizados em um ambiente de desenvolvimento antes de fazer alterações nos sistemas de produção.

Em alguns ambientes, quando um sistema executa uma única tarefa crítica, a reinicialização quando um sistema executa uma condição de OOM pode ser uma opção viável para retornar o sistema ao status operacional rapidamente sem intervenção do administrador. Embora não seja uma abordagem ideal, a lógica por trás disso é que, se nosso aplicativo não puder operar devido a ter sido encerrado pelo OOM killer, uma reinicialização do sistema restaurará a aplicação se ele iniciar com o sistema no momento da inicialização. Se o aplicativo for iniciado manualmente por um administrador, essa opção não será benéfica.

As configurações a seguir farão com que o sistema entre em pânico e reinicie em uma condição de falta de memória. Os comandos sysctl definirão isso em tempo real, e anexar as configurações ao sysctl.conf permitirá que essas especificações sejam mantidas após reinicializações. O X de kernel.panic é o número de segundos antes da reinicialização do sistema. Essa configuração deve ser ajustada para atender às necessidades do seu ambiente.




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


Também podemos ajustar a maneira como o OOM killer lida com condições de OOM com determinados processos. Por exemplo, o processo oracle 2592 que foi encerrado anteriormente. Se quisermos tornar o processo oracle menos suscetível a ser encerrado pelo OOM killer, podemos fazer o seguinte.

echo -15 > /proc/2592/oom_adj

Podemos fazer com que o OOM killer tenha mais probabilidade de encerrar o processo oracle fazendo o seguinte.

echo 10 > /proc/2592/oom_adj

Se quisermos excluir o processo oracle do OOM killer, podemos fazer o seguinte para excluir completamente o processo do recurso OOM killer. É importante observar que isso pode causar um comportamento inesperado, dependendo dos recursos e da configuração do sistema. Se o kernel não conseguir encerrar um processo que esteja usando uma grande quantidade de memória, ele passará para outros processos disponíveis. Alguns desses processos podem ser processos importantes do sistema operacional que, em última análise, podem causar a inatividade do sistema.

echo -17 > /proc/2592/oom_adj

Podemos definir intervalos válidos para oom_adj de -16 para +15, e uma configuração de -17 removerá completamente um processo do OOM killer. Quanto maior o número, maior a probabilidade de nosso processo ser selecionado para finalização se o sistema encontrar uma condição de OOM. O conteúdo de /proc/2592/oom_score também pode ser visualizado para determinar a probabilidade de um processo ser eliminado pelo OOM killer. A pontuação 0 indica que o processo foi removido do recurso OOM killer. Quanto maior a pontuação OOM, maior a probabilidade de um processo ser encerrado em uma condição OOM.

O OOM killer pode ser completamente desativado com o seguinte comando. Isso não é recomendado para ambientes de produção, porque se uma condição de falta de memória se apresentar, poderá haver um comportamento inesperado, dependendo dos recursos e da configuração do sistema disponíveis. Esse comportamento inesperado pode ser qualquer coisa, desde o pânico do kernel até a interrupção, dependendo dos recursos disponíveis para o kernel no momento da condição de OOM.




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

Para alguns ambientes, essas opções de configuração não são ideais e podem ser necessários ajustes adicionais. A configuração de HugePages para seu kernel pode ajudar com problemas de OOM, dependendo das necessidades dos aplicativos em execução no sistema.

Veja Também

Confira alguns recursos adicionais sobre HugePages, dtrace, sar e OOM para arquiteturas NUMA:

Sobre o Autor

Robert Chase é membro da equipe de gerenciamento de produtos do Oracle Linux. Ele está envolvido com Linux e software de código aberto desde 1996. Trabalhou com sistemas tão pequenos quanto dispositivos incorporados e com grandes hardwares da classe supercomputador.

Revision 1.0, 02/19/2013