Kubernetes e kswapd0 são um casal malvado?

Kubernetes e kswapd0 são um casal malvado?

Eu construo um cluster kubernetes bare-metal (nada pesado, apenas três servidores) com kubeadm no Debian 9. Como solicitado pelo Kubernetes, desativo o SWAP:

  • troca -a
  • removendo a linha SWAP em/etc/fstab
  • Adicionando vm.swappiness = 0a/etc/sysctl.conf

Portanto, não há mais SWAP em meus servidores.

$ free
              total        used        free      shared  buff/cache   available
Mem:        5082668     3679500      117200       59100     1285968     1050376
Swap:             0           0           0

Um nó é usado para executar alguns microsserviços. Quando começo a brincar com todos os microsserviços, eles usam 10% de RAM cada. E o processo kswapd0 começa a usar muita CPU.

Se eu enfatizar um pouco os microsserviços eles param de responder porque o kswapd0 usa toda a CPU. Tento esperar que kswapd0 interrompa seu trabalho, mas isso nunca aconteceu. Mesmo depois das 10h.

Li muita coisa mas não encontrei nenhuma solução.

Posso aumentar a quantidade de RAM, mas isso não resolverá meu problema.

Como os Mestres do Kubernetes lidam com esse tipo de problema?

Mais detalhes:

  • Kubernetes versão 1.15
  • Calico versão 3.8
  • Debian versão 9.6

Desde já, obrigado pela sua preciosa ajuda.

- Editar 1 -

Conforme solicitado por @john-mahowald

$ cat /proc/meminfo
MemTotal:        4050468 kB
MemFree:          108628 kB
MemAvailable:      75156 kB
Buffers:            5824 kB
Cached:           179840 kB
SwapCached:            0 kB
Active:          3576176 kB
Inactive:          81264 kB
Active(anon):    3509020 kB
Inactive(anon):    22688 kB
Active(file):      67156 kB
Inactive(file):    58576 kB
Unevictable:          92 kB
Mlocked:              92 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:       3472080 kB
Mapped:           116180 kB
Shmem:             59720 kB
Slab:             171592 kB
SReclaimable:      48716 kB
SUnreclaim:       122876 kB
KernelStack:       30688 kB
PageTables:        38076 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     2025232 kB
Committed_AS:   11247656 kB
VmallocTotal:   34359738367 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:      106352 kB
DirectMap2M:     4087808 kB

Responder1

Esse comportamento do kswapd0 é intencional e é explicável.

Embora você tenha desabilitado e removido o arquivo de troca e definido a troca como zero, o kswapd está de olho na memória disponível. Ele permite que você consuma quase toda a memória sem realizar nenhuma ação. Mas assim que a memória disponível cai para um valor criticamente baixo (páginas baixas para a zona Normal em /proc/zoneinfocerca de 4.000 páginas de 4K em meu servidor de teste), o kswapd entra em ação.

Você pode reproduzir o problema e investigá-lo mais profundamente da seguinte maneira. Você precisará de uma ferramenta que permita consumir memória de forma controlada, como um script, oferecido por Roman Evstifeev:ramhog.py

O script preenche a memória com pedaços de 100 MB do código ASCII de “Z”. Para a justiça do experimento, o script é lançado no host Kubernetes, não no pod, para que os k8s não sejam envolvidos. Este script deve ser executado em Python3. Ele é um pouco modificado para:

  • ser compatível com versões do Python anteriores à 3.6;
  • defina o bloco de alocação de memória menor que 4.000 páginas de memória (páginas baixas para a zona Normal em /proc/zoneinfo; defino 10 MB) para que a degradação do desempenho do sistema seja mais visível no final.
from time import sleep

print('Press ctrl-c to exit; Press Enter to hog 10MB more')

one = b'Z' * 1024 * 1024  # 1MB hog = []

while True:
    hog.append(one * 10)  # allocate 10MB
    free = ';\t'.join(open('/proc/meminfo').read().split('\n')[1:3])
    print("{}\tPress Enter to hog 10MB more".format(free), end='')
    input()
    sleep(0.1)

Você pode estabelecer três conexões de terminal com o sistema de teste para observar o que está acontecendo:

  • execute o script;
  • execute o comando superior;
  • busque o /proc/zoneinfo

Execute o script:

$ python3 ramhog.py

Depois de algumas digitações na tecla Enter (causadas pelo pequeno pedaço de alocação de memória que definimos (10 MB)), você notará que

o MemAvailableestá ficando baixo e seu sistema está se tornando cada vez menos responsivo:Saída ramhog.py

saída ramhog.pu

As páginas gratuitas ficarão abaixo da marca d’água baixa:páginas gratuitas

informações da zona

Consequentemente, o kswapd será ativado, assim como os processos k8s, e a utilização da CPU aumentará em até 100%:principal

saída do comando superior

Observe que o script está sendo executado separadamente do k8s e o SWAP está desabilitado. Conseqüentemente, tanto o Kubernetes quanto o kswapd0 estavam inativos no início do teste. Os pods em execução não foram tocados. Mesmo assim, com o tempo, a falta de memória disponível causada pelo terceiro aplicativo causa alta utilização da CPU: não apenas pelo kswapd, mas também pelo k8s. Isso significa que a causa raiz é a memória insuficiente, mas não o próprio k8s ou kswapd.

Como você pode ver pelo que /proc/meminfovocê forneceu, MemAvailableestá ficando muito baixo, fazendo com que o kswapd seja ativado. Por favor, verifique /proc/zoneinfotambém o seu servidor.

Na verdade, a causa raiz não está no conflito ou incompatibilidade entre k8s e kswap0, mas na contradição entre a troca desabilitada e a falta de memória que por sua vez causa a ativação do kswapd. A reinicialização do sistema resolverá temporariamente o problema, mas adicionar mais RAM é realmente recomendado.

Uma boa explicação do comportamento do kswapd está aqui: kswapd está usando muitos ciclos de CPU

Responder2

Kubernetes nos permite definir quanta RAM devemos manter para o sistema Linux usando o evictionHard.memory.availableparâmetro. Este parâmetro é definido em um ConfigMap chamado kubelet-config-1.XX. Se a RAM exceder o nível permitido pela configuração, o Kubernertes começa a eliminar os pods para reduzir seu uso.

No meu caso o evictionHard.memory.availableparâmetro foi definido muito baixo (100Mi). Portanto, não há espaço de RAM suficiente para o sistema Linux, então kswapd0 começa a bagunçar quando o uso de RAM é muito alto.

Após alguns testes, para evitar o aumento do kswapd0, configurei evictionHard.memory.availablepara 800Mi. O processo kswapd0 não atrapalhou mais.

informação relacionada