Blogue

O Ficheiro de Swap em Falta Que Congelou os Nossos Servidores

No dia 24 de setembro, um dos nossos servidores de produção deixou de responder. O balanceador de carga marcou-o como não saudável e a nossa ferramenta de comandos remotos não o conseguia alcançar — mas nada tinha falhado e nada tinha sido morto por usar memória em excesso. O servidor estava em thrashing: sem espaço de swap e com contentores autorizados a usar mais memória do que a máquina tinha, o Linux passava o tempo a despejar e a reler os ficheiros de que precisava para correr, e quase não avançava. Acrescentar um ficheiro de swap de 2 GB em cada servidor resolveu o problema. A lição mais interessante foi sobre verificações de saúde.

Como era "bloqueado"

  • As verificações de saúde do balanceador de carga expiravam nesse servidor.
  • Os comandos enviados pelo AWS Systems Manager ficavam em "Pending" e nunca corriam.
  • Não havia nenhum kill por falta de memória nos registos. Nenhum processo tinha morrido.

Uma semana antes tínhamos movido a produção para servidores ARM mais pequenos com 2 GB de RAM cada um. O nosso servidor de staging — ainda mais pequeno — tinha congelado da mesma forma ao descompactar uma imagem de contentor durante um deploy.

Porque não houve erro de memória?

O Linux só mata um processo quando fica verdadeiramente sem memória que possa recuperar. Antes desse ponto, recupera memória da cache de páginas — as cópias de ficheiros que mantém em RAM, incluindo o código de cada programa em execução.

Nos nossos servidores, os limites de memória combinados dos contentores somavam cerca de 3,3 GB numa máquina com cerca de 1,8 GB utilizáveis. Normalmente não usam todos o limite ao mesmo tempo. Quando o faziam, o kernel continuava a despejar código de programas da cache para abrir espaço, e depois tinha de o voltar a ler do disco no momento em que esse código voltava a correr. Esse ciclo — thrashing — pode tornar uma máquina quase completamente incapaz de responder sem que tecnicamente fique sem memória. Assim, nada é morto e nada recupera.

Sem swap, o kernel não tem onde colocar memória que foi alocada mas raramente usada, por isso tem de a tirar da cache.

A correção

O script de bootstrap dos servidores cria agora um ficheiro de swap de 2 GB com uma configuração de swappiness baixa (10) sempre que um servidor arranca ou é reparado. Uma swappiness baixa significa que o kernel continua a preferir manter a memória de trabalho em RAM, mas as páginas raramente tocadas podem passar para o disco em vez de forçar o código do programa a sair da cache. Aplicámo-la ao vivo nos dois servidores de produção e no de staging, e o pipeline de deploy volta a publicar o script de bootstrap em cada deploy de produção, para que um servidor substituído também a receba.

A parte que mais nos preocupou: o servidor não saudável ficou

O nosso grupo de servidores usava verificações de saúde EC2 — "a máquina está a correr?" — e não verificações de saúde do balanceador de carga — "está a responder a pedidos?". Por isso, um servidor do qual o balanceador de carga já tinha desistido continuava saudável aos olhos do grupo. Nunca seria substituído. A produção ficaria a correr silenciosamente num só servidor até alguém dar por isso e reiniciar o outro.

Mudar o grupo para verificações de saúde do balanceador parece a correção óbvia, mas não é simples para nós: durante um deploy, os servidores respondem de propósito com erro no seu endpoint de saúde para que o balanceador os retire de serviço (vê como chegámos a zero 502 em deploys). Um grupo que substitui servidores com base nesse sinal substituí-los-ia a meio de cada deploy.

Por isso, por agora, acrescentámos um passo à nossa lista de verificação de deploy: depois de cada deploy, verificar a saúde de cada alvo no balanceador de carga, e não apenas se o job de deploy passou. Se os comandos para um servidor ficarem em "Pending", está em thrashing — reinicia-o; já está fora de rotação.

O que tirámos disto

  • "Não estar a falhar" não é "estar saudável". O thrashing não produz erro, apenas uma lentidão tão extrema que a máquina deixa de responder.
  • Servidores pequenos precisam de swap. Mesmo pouco, com swappiness baixa, dá ao kernel um sítio para colocar memória fria.
  • Limites de memória que somam mais do que a máquina são uma aposta. Às vezes perdes. Sabe quando a fizeste.
  • Sabe em que verificação de saúde confia o teu autoscaling. Uma verificação que só pergunta "a VM está ligada?" não substitui um servidor que deixou de funcionar.

Mythex · Pricing · Crie qualquer coisa com IA · Modelos de sites e apps · Mythex comparado · Glossário de criação de apps com IA · Ferramentas grátis para criar apps com IA · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)