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:
- Esse script passa a devorar 100% de todos os núcleos do processador.
- Começa a alocar gigabytes de memória RAM descontroladamente até esgotar a capacidade física da máquina.
- 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.
- O Nginx deixa de conseguir responder e os teus sites caem com erros 502 e 504.
- 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étricafull avg10estiver 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 ▼
- O Pesadelo do Processo Vizinho: Como um Erro de Código Congela a Máquina
- Como Funcionam os cgroups v2: A Hierarquia Unificada do Kernel
- Implementação Prática: Como Criar Slices com o Systemd
- 1. Criar o Ficheiro de Slice: /etc/systemd/system/workers-restritos.slice
- 2. Associar o Teu Serviço à Nova Fatia
- Como Diagnosticar Gargalos com Pressure Stall Information (PSI)
- Consulta a Pressão de Recursos no Terminal
- O Que Significam Estes Valores:
- Monitorizar os Teus Grupos em Tempo Real na Consola
- Autor
- Perguntas Frequentes
- Qual é a diferença fundamental entre cgroups v1 e cgroups v2 no kernel Linux?
- Como é que o kernel do Linux limita o uso de CPU com o parâmetro cpu.max?
- Qual é a diferença entre memory.high e memory.max nos cgroups v2?
- Precisas de mexer diretamente na pasta /sys/fs/cgroup para configurar limites no Debian 12?
- Nós Relacionados
- Sequência do Caminho
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`.
[ RELATED_NODES ]
> 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.