Como Impedir que um Processo Descontrolado Bloqueie o Teu Servidor: Limites de CPU e RAM com cgroups v2 no Linux

Como Impedir que um Processo Descontrolado Bloqueie o Teu Servidor: Limites de CPU e RAM com cgroups v2 no Linux

O Pesadelo do Processo Vizinho: Como um Erro de Código Congela a Máquina

Imagina o seguinte cenário no teu servidor dedicado ou VPS de produção: tens a correr o servidor web Nginx, uma base de dados PostgreSQL, o serviço de SSH para acederes à consola e um worker em segundo plano encarregue de converter ficheiros PDF, redimensionar imagens ou importar folhas de cálculo pesadas.

Num dia aparentemente normal, um utilizador faz o envio de um ficheiro malicioso ou um programador coloca em produção um ciclo infinito while sem condição de paragem.

Em escassos segundos:

  1. Esse script passa a devorar 100% de todos os núcleos do processador.
  2. Começa a alocar gigabytes de memória RAM descontroladamente até esgotar a capacidade física da máquina.
  3. O kernel do Linux entra em desespero e começa a empurrar dados para o swap do disco, entupindo as operações de I/O.
  4. O Nginx deixa de conseguir responder e os teus sites caem com erros 502 e 504.
  5. Tentas aceder por SSH para matar o processo, mas a ligação dá timeout porque o servidor não tem sequer um bloco livre de memória para abrir a shell /bin/bash.

A CASCATA DE DESTRUIÇÃO DE UM PROCESSO LIVRE

  • O Teu Servidor (32GB de RAM Total, 8 Núcleos de CPU)
  • Serviços Vitais: [ Nginx: 500MB ] [ PostgreSQL: 4GB ] [ SSH: 10MB ]
  • O Script Fora de Controlo: Devora 27.5GB de RAM → Consome 100% de CPU → Satura o Disco!
  • O Servidor Congela por Completo! O Kernel Entra em Pânico!

Isto acontece porque, por defeito no Linux, qualquer programa tem acesso ilimitado aos recursos físicos do computador. A não ser que imponhas limites expressos, um simples script executado por um utilizador comum pode deitar abaixo todo o teu negócio.

A solução definitiva e robusta para este problema chama-se cgroups v2 (Control Groups versão 2).

No nosso serviço de alojamento gerido e nas nossas intervenções de consultoria técnica, configuramos barreiras rígidas com cgroups v2 em servidores com Debian GNU/Linux para assegurar que nenhum processo secundário consegue derrubar a infraestrutura principal.


Como Funcionam os cgroups v2: A Hierarquia Unificada do Kernel

Nas versões antigas do Linux usava-se a versão cgroups v1. Cada recurso (CPU, memória, leitura de disco) era gerido numa pasta diferente sem comunicação entre si. Isto gerava erros bizarros: o sistema de memória não conseguia avisar o sistema de disco sobre quem era o dono dos ficheiros temporários em cache.

Para corrigir estas falhas, os cgroups v2 organizaram todos os processos do servidor numa árvore unificada:

ÁRVORE UNIFICADA DOS CGROUPS V2 NO LINUX

  • /sys/fs/cgroup (Raiz do Sistema) system.slice/ (Serviços Vitais do Sistema Operativo) nginx.service (CPU Garantido, Memória Rápida) postgresql.service (Protegido contra o OOM Killer) ssh.service (Canal Seguro para Entrares por SSH Sempre)
  • user.slice/ (Sessões Interativas de Utilizadores)
  • background.slice/ (ÁREA RESTRITA PARA TAREFAS PESADAS) worker-pdf.service → Teto de RAM: Máximo 2GB (memory.max) worker-media.service → Quota de CPU: Máximo 1.5 Núcleos (cpu.max)

Com esta organização em árvore:

  • Cada processo pertence a um único grupo.
  • As regras herdam-se em cascata: Se definires um limite para a fatia (slice), nenhum serviço dentro dela consegue furar essa regra.
  • O OOM Killer fica isolado: Se a tarefa de converter imagens estourar a memória autorizada, o kernel abate apenas esse processo. A tua base de dados e o servidor web continuam a funcionar sem qualquer interrupção.

Implementação Prática: Como Criar Slices com o Systemd

No teu Debian 12 não deves criar ficheiros manuais na pasta /sys/fs/cgroup/. A forma elegante e oficial de controlar recursos é através do systemd.

Vamos criar uma fatia isolada para processos pesados de segundo plano.

1. Criar o Ficheiro de Slice: /etc/systemd/system/workers-restritos.slice

Cria este ficheiro com os limites máximos que autorizas para essas tarefas:

[Unit]
Description=Fatia Restrita para Workers Pesados de Segundo Plano
Before=slices.target

[Slice]
# Teto Absoluto de Memória: Nunca autoriza mais de 2GB de RAM
MemoryMax=2G

# Aviso Suave: Começa a limpar a cache do processo aos 1.7GB
MemoryHigh=1700M

# Quota de CPU: Limita todos os processos somados a 150% (1 núcleo e meio)
CPUQuota=150%

# Prioridade de CPU: Peso baixo em caso de concorrência (escala 1-10000)
CPUWeight=50

# Prioridade de Disco: Dá preferência a outros serviços no acesso a ficheiros
IOWeight=50

# Impede a criação de mais de 100 processos ou threads em paralelo
TasksMax=100

2. Associar o Teu Serviço à Nova Fatia

No ficheiro de serviço do teu worker (por exemplo, /etc/systemd/system/processar-imagens.service), indica a fatia que criaste:

[Unit]
Description=Serviço de Otimização de Imagens
After=network.target

[Service]
Type=simple
User=worker
Slice=workers-restritos.slice
ExecStart=/usr/bin/node /opt/workers/processador.mjs
Restart=on-failure

[Install]
WantedBy=multi-user.target

Aplica as novas definições no teu servidor:

systemctl daemon-reload
systemctl restart workers-restritos.slice
systemctl restart processar-imagens.service

O ISOLAMENTO REAL DE RECURSOS EM FUNCIONAMENTO

  • Servidor Principal (32GB de RAM)
  • SERVIÇOS CRÍTICOS (system.slice)
  • Nginx e PostgreSQL usam 16GB à vontade
  • O SSH está SEMPRE disponível para acederes
  • WORKERS RESTRITOS (workers-restritos.slice)
  • O worker tenta comer 10GB de RAM → TRAVADO RIGOROSAMENTE AOS 2GB!
  • O worker tenta 100% nos 8 núcleos → TRAVADO A 1.5 NÚCLEOS!
  • Se passar dos 2GB, o kernel mata APENAS o worker! O resto não sente!

Repara na segurança que ganhas: mesmo que o teu código tenha um erro grave que devore memória, o kernel do Linux trava-o no limite dos 2GB. O worker não consegue roubar RAM à base de dados, não consegue atrasar o Nginx e tu consegues sempre entrar por SSH para investigar o problema.


Como Diagnosticar Gargalos com Pressure Stall Information (PSI)

Como sabes se os teus processos estão a sofrer com falta de recursos antes de crasharem? Os cgroups v2 introduziram uma ferramenta revolucionária no kernel chamada Pressure Stall Information (PSI), que calcula a percentagem exata de tempo que os teus programas passam à espera de CPU, memória ou disco.

Consulta a Pressão de Recursos no Terminal

Podes consultar estes dados diretamente no sistema de ficheiros virtual:

# Vê a pressão geral de memória do teu servidor
cat /proc/pressure/memory

# Vê a pressão de memória dentro da fatia restrita que criámos
cat /sys/fs/cgroup/workers-restritos.slice/memory.pressure

Exemplo do que vais ver na consola:

some avg10=12.45 avg60=4.12 avg300=1.05 total=41298512
full avg10=2.10 avg60=0.85 avg300=0.20 total=9841205

O Que Significam Estes Valores:

  • some: Mostra a percentagem de tempo em que pelo menos uma tarefa esteve parada à espera que o kernel libertasse memória.
  • full: Mostra a percentagem de tempo em que todos os processos desse grupo ficaram completamente congelados por falta de RAM. Se a métrica full avg10 estiver acima de zero, os teus processos estão ativamente a engasgar-se.

Monitorizar os Teus Grupos em Tempo Real na Consola

Para veres o consumo dos teus limites em direto, usa as ferramentas nativas do systemd:

# Apresenta o consumo de CPU, RAM e I/O por grupo em tempo real
systemd-cgtop -m

# Mostra a lista completa de processos dividida por fatias
systemd-cgls

ECRÃ DE MONITORIZAÇÃO EM TEMPO REAL: SYSTEMD-CGTOP

  • Control Group
  • Tasks %CPU Memory Input/s Output/s
  • /system.slice: /system.slice/postgresql.service • /system.slice/nginx.service • /workers-restritos.slice
  • 98 2.0 4.1G 0 0: 18 1.5 3.4G 0 0 • 8 0.5 350.2M 0 0 • 12 148.9 1.9G 0 0
  • /workers-restritos.slice/processar-imagens.se 12 148.9 1.9G 0 0

Repara como o serviço de imagens está cravado em 148.9% CPU (respeitando o limite de 150%) e com 1.9G de memória (sem passar o teto dos 2GB). O resto do teu servidor mantém-se tranquilo e veloz.

Ao aplicares limites com cgroups v2, garantes proteção absoluta na tua máquina sem precisares da sobrecarga de plataformas complexas de contentores. Seguindo a nossa filosofia de anti-over-engineering, este isolamento nativo do Linux protege o teu negócio contra imprevistos. Podes encontrar mais exemplos no GitHub, mas o systemd e os cgroups v2 dão-te todo o controlo de que precisas.

No terreno, em conjunto com a experiência acumulada na Webxtek Studio, aplicamos exatamente estes padrões operacionais em setores exigentes como especialistas em devops e arquitetura cloud e provedores de cloud computing e iaas. Quando alinhas a tua estrutura através de alojamento gerido para websites e aplicações e consultoria técnica antes de construir, transformas boas práticas técnicas numa vantagem competitiva real e mensurável para o teu negócio.

[+] [ INDEX_DIRECTORY ] 17 tópicos ▼
[ SYSTEM.FAQ ]

Perguntas Frequentes

Qual é a diferença fundamental entre cgroups v1 e cgroups v2 no kernel Linux?

Nos cgroups v1, cada controlador (CPU, memória, I/O) funcionava numa árvore de pastas separada e independente, tornando impossível relacionar o consumo de disco com a memória de cache suja. Nos cgroups v2, todos os controladores foram unificados numa hierarquia única em árvore, permitindo isolamento total de recursos, gestão de OOM killer confinada à pasta e métricas de pressão (PSI).

Como é que o kernel do Linux limita o uso de CPU com o parâmetro cpu.max?

Nos cgroups v2, a quota de CPU é configurada através de uma relação entre tempo e período no ficheiro `cpu.max` (ex: `200000 100000`). O agendador CFS do kernel calcula o consumo a cada 100 milissegundos. Se o grupo de processos gastar 200ms de tempo de CPU nessa janela, o kernel coloca os processos em pausa até começar o período seguinte.

Qual é a diferença entre memory.high e memory.max nos cgroups v2?

O valor `memory.max` é um teto máximo inegociável: se os processos desse grupo ultrapassarem esse limite e o kernel não conseguir libertar memória de cache, o OOM Killer abate imediatamente um processo desse grupo. O valor `memory.high` é um aviso suave: ultrapassá-lo força o kernel a libertar memória agressivamente e abranda os processos sem os desligar à força.

Precisas de mexer diretamente na pasta /sys/fs/cgroup para configurar limites no Debian 12?

Não deves alterar essa pasta à mão. Em servidores modernos com Debian 12, a forma correta e limpa de gerir cgroups é através das unidades e fatias (slices) do systemd, criando regras nos ficheiros `.slice` ou recorrendo a comandos como `systemctl edit`.

> INICIAR_PROJETO

Precisa de um website que transmita confiança, apareça na pesquisa e dê mais força à sua presença digital? Comece a conversa aqui.