limites de recursos do cgroups v2 com systemd

11 min de leitura - 3 de junho de 2026

hero section cover
Índice
  • Limites de recursos do cgroups v2 com o systemd
  • Ativar cgroups v2
  • Como o systemd organiza os cgroups
  • Limites da CPU
  • Limites de memória com cgroups v2
  • Limites de E/S
  • Isolamento multitenant com fatias
  • Monitorização com o systemd-cgtop e o PSI
Partilhar

Definir limites de CPU, memória e E/S com cgroups v2 e systemd. Configuração prática para hosts Linux multi-tenant, com monitorização PSI e isolamento de slice.

Limites de recursos do cgroups v2 com o systemd

O cgroups v2 é a estrutura unificada de controlo de recursos do kernel Linux. Substitui a hierarquia fragmentada da v1 por uma única árvore que gere a CPU, a memória e as E/S de forma consistente, e sustenta o isolamento de contentores no Docker, Kubernetes e systemd. Esta publicação aborda como ativar o cgroups v2, definir limites através do systemd e aplicá-lo a cenários reais de alojamento multi-tenant.

Ativar cgroups v2

As distribuições modernas vêm com os cgroups v2 ativados por predefinição: Ubuntu 21.10+, Debian 11+, Fedora 31+ e RHEL/Rocky 9+. Os sistemas mais antigos podem executar uma hierarquia híbrida ou ainda ter a v1 como predefinição. Verifique com:

stat -fc %T /sys/fs/cgroup/

A saída de cgroup2fs confirma que a v2 está ativa. tmpfs normalmente significa v1.

Para mudar um sistema híbrido para v2 puro, edite /etc/default/grub e acrescente o seguinte a GRUB_CMDLINE_LINUX_DEFAULT:

systemd.unified_cgroup_hierarchy=1 cgroup_no_v1=all

Em seguida, gere novamente o GRUB e reinicie:

sudo update-grub
sudo reboot

Para produção, execute o kernel 5.2 ou mais recente para obter o cgroup freezer para a v2 e o systemd 244+ para a cpuset . No Rocky Linux 8 e no RHEL 8, poderá também ser necessário ativar a contabilidade explicitamente, adicionando estas linhas a /etc/systemd/system.conf:

DefaultCPUAccounting=yes
DefaultMemoryAccounting=yes
DefaultIOAccounting=yes

Recarregue com sudo systemctl daemon-reexec. Após o reinício, verifique quais controladores estão disponíveis:

cat /sys/fs/cgroup/cgroup.controllers

Deve ver cpu, memory, ioe pids listados. Estes controladores não estão ativados para cgroups filhos por predefinição. Para os ativar, escreva no ficheiro de controlo da subárvore raiz:

echo "+cpu +memory +io" | sudo tee /sys/fs/cgroup/cgroup.subtree_control

Para uma visão completa de como a v2 difere da v1 internamente, a palestra de Michael Kerrisk na NDC TechTown é o melhor recurso disponível:

Como o systemd organiza os cgroups

O systemd cria um cgroup para cada serviço que inicia, com o nome da unidade. nginx.service obtém /sys/fs/cgroup/system.slice/nginx.service/, e todos os processos que gera residem dentro desse cgroup. Três tipos de unidade correspondem diretamente à hierarquia:

Tipo de unidadeFunçãoDescrição
.sliceNó internoAgrupa serviços relacionados e define limites partilhados
.serviceNó terminalGere processos iniciados pelo systemd
.scopeNó folhaAcompanha processos iniciados externamente (cargas úteis de contentores, sessões de início de sessão)

Quatro fatias padrão são fornecidas de fábrica: -.slice (raiz), system.slice, user.slicee machine.slice. Qualquer limite aplicado a uma fatia aplica-se automaticamente a todos os serviços nela contidos.

Uma regra da v2 que vale a pena lembrar: os processos só podem residir em nós folha. Um cgroup com cgroups filhos não pode hospedar processos diretamente, razão pela qual o systemd nunca coloca serviços no tronco de uma fatia.

Defina sempre os limites através do systemd em vez de escrever /sys/fs/cgroup/ diretamente. As gravações manuais não persistem após reinicializações e entram em conflito com a propriedade exclusiva da hierarquia pelo systemd. Use systemctl set-property para alterações pontuais e unit drop-ins (systemctl edit nginx.service) para alterações permanentes.

Limites da CPU

O cgroups v2 oferece dois controlos de CPU: um limite rígido (cpu.max, exposto como CPUQuota no systemd) e um peso proporcional (cpu.weight / CPUWeight).

CPUQuota é um limite máximo absoluto. CPUQuota=50% permite meio núcleo; CPUQuota=200% permite o tempo equivalente a dois núcleos completos. O serviço é limitado se tentar ultrapassar esse valor, independentemente do nível de inatividade do resto da CPU.

CPUWeight só importa em caso de contenção. O intervalo é de 1 a 10 000, sendo o valor padrão 100. Três serviços com pesos de 150, 100 e 50 recebem aproximadamente 50%, 33% e 17% do tempo de CPU quando todos o pretendem ao mesmo tempo. Quando a CPU está ociosa, os pesos não restringem nada.

Para cargas de trabalho sensíveis à latência, fixe os processos a núcleos específicos com AllowedCPUs=. Isto reduz a troca de contexto e mantém a cache por núcleo ativa:

[Service]
CPUQuota=200%
CPUWeight=150
AllowedCPUs=0-3

Utilize uma quota rígida quando precisar de custos previsíveis (faturação multi-tenant, isolamento de vizinhos ruidosos). Utilize pesos quando pretender a máxima utilização do hardware e apenas precisar de uma ordem de prioridade durante picos de carga.

Limites de memória com cgroups v2

A memória tem dois níveis: memory.high (suave, limitação) e memory.max (rígido, OOM). Para obter informações sobre swap, recuperação de páginas e o OOM killer do kernel, consulte a nossa publicação complementar sobre gestão de memória no Linux.

Defina memory.high aproximadamente 10 a 20% abaixo memory.max. O kernel começa a recuperar páginas e a limitar as alocações assim que memory.high é ultrapassado, o que normalmente permite que a carga de trabalho se recupere antes de o OOM killer ser acionado. Se a utilização atingir memory.max, o kernel encerra processos no cgroup.

Uma configuração típica:

[Service]
MemoryHigh=400M
MemoryMax=512M
MemorySwapMax=0

MemorySwapMax=0 desativa o swap para este cgroup. Vale a pena fazer isso para cargas de trabalho sensíveis à latência (bases de dados, streaming em tempo real), onde a E/S do swap prejudicaria a latência de cauda.

Para conjuntos de trabalhadores em que deixar irmãos órfãos para trás corromperia o estado partilhado, escreva 1 no ficheiro memory.oom.group . Quando um processo é encerrado por OOM, o kernel encerra todos os processos no cgroup em conjunto.

Verifique memory.events para ver com que frequência um serviço foi limitado ou encerrado por OOM:

cat /sys/fs/cgroup/system.slice/nginx.service/memory.events

O high e oom_kill indicam se os seus limites estão dimensionados corretamente. Valores persistentes diferentes de zero significam que a carga de trabalho precisa de mais margem.

Limites de E/S

O controlador de E/S tem o mesmo design de dois modos: limites absolutos através io.max e partilha proporcional via io.weight.

Os limites são por dispositivo de bloco, identificados por números major:minor. Encontre-os com lsblk -o NAME,MAJ:MIN. Uma configuração típica do systemd:

[Service]
IOReadBandwidthMax=/dev/sda 50M
IOWriteBandwidthMax=/dev/sda 30M
IOReadIOPSMax=/dev/sda 1000
IOWriteIOPSMax=/dev/sda 500

io.weight funciona como cpu.weight: intervalo de 1 a 10 000, valor padrão 100. Atribuir 500 a um serviço voltado para o cliente e 50 a um backup noturno evita que o backup sature o disco durante os horários de pico, mas permite que ele use toda a largura de banda quando nada mais a necessita.

Os limites de E/S só se aplicam quando se direciona o dispositivo certo. O kernel rastreia a E/S por dispositivo de bloco, portanto, um limite em /dev/sda não tem efeito sobre a E/S que vai para /dev/nvme0n1. Em hosts com vários discos, defina limites por dispositivo.

Isolamento multitenant com fatias

Para ambientes partilhados, defina uma fatia por inquilino. Crie /etc/systemd/system/tenant-a.slice:

[Slice]
CPUQuota=200%
CPUWeight=150
MemoryHigh=3584M
MemoryMax=4096M
MemorySwapMax=0
IOReadBandwidthMax=/dev/sda 200M
TasksMax=512

TasksMax=512 limita o número total de processos e threads, o que impede que uma bomba de fork num inquilino derrube o anfitrião. Coloque os serviços do inquilino nesta fatia (através Slice=tenant-a.slice nos seus ficheiros de unidade) e estes herdam tudo automaticamente.

Este padrão também funciona para separar tarefas de fundo ruidosas dos serviços voltados para o utilizador. Coloque backups, rotação de logs e tarefas em lote numa background.slice com baixo CPUWeight e io.weight . Recebem recursos completos quando o sistema está inativo e dão lugar quando o tráfego de produção chega.

Para ambientes de execução de contentores como o Docker e o Podman, adicione Delegate=yes aos seus ficheiros de unidade do systemd. Isto permite-lhes gerir os seus próprios sub-cgroups sem direitos de root, e os limites definidos na fatia pai continuam a aplicar-se a tudo o que está abaixo.

Monitorização com o systemd-cgtop e o PSI

Para uma visualização em tempo real, ao estilo do top, da CPU, da memória e da E/S por cgroup, execute:

systemd-cgtop

Para a hierarquia estática e para saber quais os processos que se encontram em cada local, utilize systemd-cgls.

A funcionalidade v2 mais útil para monitorização em produção é a Pressure Stall Information (PSI). A PSI reporta a percentagem de tempo em que as tarefas num cgroup ficaram paralisadas à espera de um recurso, apresentada em três ficheiros por cgroup:

cat /sys/fs/cgroup/tenant-a.slice/cpu.pressure
cat /sys/fs/cgroup/tenant-a.slice/memory.pressure
cat /sys/fs/cgroup/tenant-a.slice/io.pressure

Uma CPU com 100% de utilização e 0% de pressão está em bom estado. Todas as tarefas que necessitam de CPU estão a obtê-la. A mesma CPU com 80% de utilização, mas 30% de pressão, significa que as tarefas estão em fila para tempo de execução. Alerte com base no PSI, não na utilização: este deteta conflitos que as métricas de utilização ignoram completamente.

Ajuste os limites em tempo real sem reiniciar nada:

sudo systemctl set-property tenant-a.slice MemoryMax=6144M

A alteração aplica-se imediatamente e persiste após reinicializações. Combinado com alertas baseados no PSI, isto permite-lhe responder a mudanças de carga antes que se transformem em encerramentos por OOM ou latência descontrolada.

Se estiver a executar cargas de trabalho multitenant de alta densidade e precisar de um host com capacidade para aplicar estas políticas de forma eficaz, os nossos servidores dedicados foram concebidos para isso.

Blogue

Em destaque esta semana

Mais artigos
Fadiga ocular digital: Como proteger a sua visão num mundo dominado pelos ecrãs

Fadiga ocular digital: Como proteger a sua visão num mundo dominado pelos ecrãs

Passa o dia inteiro a olhar para ecrãs? Saiba como reduzir a fadiga ocular digital com técnicas e ferramentas comprovadas. Este guia é essencial para trabalhadores remotos, programadores e qualquer pessoa que trabalhe na área da tecnologia.

4 min de leitura - 21 de maio de 2025

Por que é importante ter um VPS potente e sem limites de tráfego

8 min de leitura - 9 de maio de 2025

Mais artigos