Configurando o Out-Of-Memory Killer no Linux para PostgreSQL

Configurando o Out-Of-Memory Killer no Linux para PostgreSQL

Quando um servidor de banco de dados Linux é encerrado inesperadamente, é preciso identificar a causa. Podem haver várias razões. Por exemplo, SIGSEGV — falha devido a um bug no servidor backend. Mas isso é raro. Mais frequentemente, simplesmente acaba o espaço no disco ou a memória. Se o espaço no disco acabar, a única saída é liberar espaço e reiniciar o banco de dados.

Out-Of-Memory Killer

Quando a servidor memória de um processo acaba, o Linux oferece duas soluções: derrubar todo o sistema ou encerrar o processo (aplicativo) que consome a memória. O ideal é encerrar o processo e salvar o sistema operacional de um encerramento brusco. Em resumo, o Out-Of-Memory Killer é um processo que encerra um aplicativo para salvar o núcleo de uma falha. Ele sacrifica o aplicativo para preservar o funcionamento do sistema operacional. Vamos primeiro discutir como o OOM funciona e como controlá-lo, e depois veremos como o OOM Killer decide qual aplicativo encerrar.

Uma das principais funções do Linux é alocar memória para os processos quando eles a solicitam. Normalmente, um processo ou aplicativo solicita memória ao sistema operacional, mas não a utiliza completamente. Se o sistema operacional começar a fornecer memória a todos que a solicitam, mas não a planejam usar, em breve a memória acabará, e o sistema falhará. Para evitar isso, o sistema operacional reserva memória para o processo, mas na verdade não a libera. A memória é alocada apenas quando o processo realmente pretende utilizá-la. Às vezes, o sistema operacional não tem memória livre, mas reserva memória para um processo, e quando ela é necessária, o sistema a aloca, se puder. O problema é que, às vezes, o sistema reserva a memória, mas no momento necessário não há memória livre, resultando em uma falha do sistema. O OOM desempenha um papel crucial nesse cenário e encerra processos para evitar a pânico do núcleo. Quando um processo PostgreSQL é encerrado forçadamente, aparece uma mensagem no log:

Out of Memory: Killed process 12345 (postgres).

Se a memória no sistema estiver baixa e não puder ser liberada, a função é chamada out_of_memoryNeste estágio, resta apenas uma coisa a fazer — encerrar um ou mais processos. O OOM-killer deve encerrar o processo imediatamente ou pode esperar? É evidente que, quando ocorre a situação de out_of_memory, isso está relacionado à espera de uma operação de entrada/saída ou ao swap de páginas para o disco. Portanto, o OOM-killer deve primeiro realizar verificações e, com base nelas, decidir qual processo deve ser encerrado. Se todas as verificações a seguir forem bem-sucedidas, o OOM encerrará o processo.

Seleção de processo

Quando a memória acaba, a função out_of_memory()é chamada. Ela contém a função select_bad_process(), que recebe uma pontuação da função badness().O processo mais "ruim" será escolhido. A função badness(). seleciona o processo com base em regras específicas.

  1. O núcleo precisa de uma certa quantidade mínima de memória para si mesmo.
  2. É necessário liberar uma grande quantidade de memória.
  3. Não é preciso encerrar processos que usam pouca memória.
  4. É necessário encerrar pelo menos alguns processos.
  5. Algoritmos complexos podem aumentar as chances de encerrar aqueles processos que o usuário deseja finalizar.

Após realizar todas essas verificações, o OOM analisa a pontuação (oom_score). O OOM atribui uma nota oom_score a cada processo e, em seguida, multiplica esse valor pela quantidade de memória. Processos com valores maiores têm mais chances de se tornarem vítimas do OOM Killer. Processos associados a usuários privilegiados têm pontuações mais baixas e menos chances de serem encerrados à força.

postgres=# SELECT pg_backend_pid();
pg_backend_pid
----------------
    3813
(1 row)

O identificador de processo do Postgres é 3813, portanto, em outro shell, você pode obter a pontuação usando esse parâmetro do núcleo oom_score:

vagrant@vagrant:~$ sudo cat /proc/3813/oom_score
2

Se você realmente não quiser que o OOM-Killer encerre o processo, existe outro parâmetro do núcleo: oom_score_adj. Adicione um grande valor negativo para reduzir as chances de encerramento do processo que você deseja proteger.

sudo echo -100 > /proc/3813/oom_score_adj

Para definir um valor oom_score_adj, defina OOMScoreAdjust no bloco de serviço:

[Service]
OOMScoreAdjust=-1000

Ou use oomprotect no comando rcctl.

rcctl set servicename oomprotect -1000

Encerramento forçado de processos

Quando um ou mais processos já foram selecionados, o OOM-Killer chama a função oom_kill_task().Essa função envia um sinal de encerramento ao processo. Em caso de falta de memória, oom_kill() chama essa função para enviar ao processo o sinal SIGKILL. Uma mensagem é registrada no log do núcleo.

Fora de Memória: Processo [pid] [name] foi encerrado.

Como controlar o OOM-Killer

No Linux, é possível habilitar e desabilitar o OOM-Killer (embora o último não seja recomendado). Para habilitar e desabilitar, use o parâmetro vm.oom-kill. Para ativar o OOM-Killer em tempo de execução, execute o comando sysctl.

sudo -s sysctl -w vm.oom-kill=1

Para desativar o OOM-Killer, defina o valor 0 neste mesmo comando:

sudo -s sysctl -w vm.oom-kill=0

O resultado deste comando não será permanente, apenas até o próximo reinício. Se for necessário mais permanência, adicione esta linha ao arquivo /etc/sysctl.conf:

echo vm.oom-kill=1 >> /etc/sysctl.conf

Outra forma de habilitar e desabilitar é definir a variável panic_on_oom. O valor pode ser sempre verificado em /proc.

$ cat /proc/sys/vm/panic_on_oom
0

Se definir o valor como 0, quando a memória acabar, não ocorrerá panic do kernel.

$ echo 0 > /proc/sys/vm/panic_on_oom

Se definir o valor como 1, quando a memória acabar, ocorrerá panic do kernel.

echo 1 > /proc/sys/vm/panic_on_oom

O OOM-Killer pode ser não apenas habilitado e desabilitado. Já mencionamos que o Linux pode reservar para processos mais memória do que a disponível, mas não alocar efetivamente, e esse comportamento é gerenciado pelo parâmetro do kernel Linux. Isso é controlado pela variável vm.overcommit_memory.

Para ela, podem ser definidos os seguintes valores:

0: o kernel decide automaticamente se deve reservar muita memória. Este é o valor padrão na maioria das versões do Linux.
1: o kernel sempre reservará memória excessiva. Isso é arriscado, pois a memória pode acabar, pois é provável que, eventualmente, os processos solicitem a quantidade prevista.
2: o kernel não reservará mais memória do que a especificada no parâmetro overcommit_ratio.

Neste parâmetro, você especifica a porcentagem de memória que é aceitável para sobrecarregar. Se não houver espaço para isso, a memória não será alocada, e a reserva será negada. Esta é a opção mais segura, recomendada para PostgreSQL. O OOM-Killer também é influenciado por outro elemento — a possibilidade de swap, que é controlada pela variável cat /proc/sys/vm/swappinessEsses valores indicam ao núcleo como lidar com o swap de páginas. Quanto maior o valor, menor a probabilidade de que o OOM finalize o processo, mas devido às operações de entrada e saída, isso pode impactar negativamente o banco de dados. Por outro lado, quanto menor o valor, maior a probabilidade de intervenção do OOM-Killer, mas a performance do banco de dados também será melhor. O valor padrão é 60, mas se todo o banco de dados couber na memória, é melhor definir o valor como 1.

Resultados

Não deixe que o "killer" em OOM-Killer te assuste. Nesse caso, o killer será o salvador do seu sistema. Ele "mata" os processos mais indesejáveis e salva o sistema de um desligamento acidental. Para evitar ter que usar o OOM-Killer para finalizar o PostgreSQL, defina o vm.overcommit_memory valor como 2. Isso não garante que o OOM-Killer não precise intervir, mas diminuirá a probabilidade de finalização forçada do processo PostgreSQL.

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster