Um serviço web que fica lento, um worker morto sem mensagem clara ou um servidor que faz swap não necessariamente exauriu toda a RAM da máquina. Com o systemd, um limite estabelecido em uma unidade pode ser suficiente para explicar o sintoma.
Os cgroups permitem que o kernel Linux conte, limite e priorize os recursos de um grupo de processos. Antes de adicionar memória ou reiniciar aleatoriamente, verifique o que o systemd aplica ao serviço em questão.

Ver o cgroup de um serviço
Nas distribuições recentes, o systemd coloca cada serviço em seu próprio cgroup. Você não precisa mover PIDs manualmente para diagnosticar uma unidade clássica como Nginx, PostgreSQL ou um worker de aplicativo.
Comece lendo o estado do serviço e as propriedades relacionadas aos recursos. Substitua nginx.service pelo nome real da sua unidade.
systemctl status nginx.service --no-pager
systemctl show nginx.service -p ControlGroup -p MainPID -p MemoryCurrent -p MemoryMax -p MemoryHigh -p CPUQuotaPerSecUSec
ControlGroup fornece o caminho gerenciado pelo systemd. MemoryCurrent exibe a memória contabilizada para a unidade no momento da leitura. Se MemoryMax for infinity, o systemd não estabeleceu um teto de memória rígido para este serviço.
Se você estiver partindo de um PID, releia seu cgroup a partir de /proc. Em cgroup v2, você verá frequentemente uma linha do tipo 0::/system.slice/nginx.service.
pid=$(systemctl show nginx.service -p MainPID --value)
cat /proc/$pid/cgroup
Se MainPID for 0, o serviço não tem um processo principal ativo. Volte para systemctl status e journalctl em vez de concluir a partir de um PID vazio.
Ler os limites de memória e CPU
MemoryMax é um limite rígido. Se o cgroup atingir esse teto e o kernel não recuperar memória suficiente, um processo do grupo pode ser morto pelo OOM killer.
MemoryHigh é menos brusco. O kernel reduz as alocações e tenta recuperar memória quando o cgroup ultrapassa esse limite. Para conter um serviço sem fazê-lo falhar no primeiro pico, geralmente é um ajuste inicial melhor do que MemoryMax.
CPUQuota limita o tempo de CPU disponível para o serviço. CPUQuota=25% dá o equivalente a um quarto de um núcleo lógico. Em uma máquina com vários núcleos, CPUQuota=200% permite até dois núcleos de tempo de CPU.
systemctl show nginx.service
-p MemoryCurrent -p MemoryMax -p MemoryHigh
-p CPUUsageNSec -p CPUQuotaPerSecUSec
Não misture cota e prioridade. Uma cota impede que o serviço exceda uma quantidade de CPU. Uma prioridade, com nice ou CPUWeight, arbitra principalmente a concorrência quando várias tarefas solicitam CPU ao mesmo tempo.
Encontrar a origem de um limite
Um limite pode vir do arquivo fornecido pelo pacote, de um drop-in do systemd ou de um override criado localmente. Leia a configuração completa antes de modificar o serviço.
systemctl cat nginx.service
systemctl show nginx.service -p FragmentPath -p DropInPaths
Um arquivo em /etc/systemd/system/nginx.service.d/ normalmente tem precedência sobre a unidade fornecida pelo pacote. Evite modificar diretamente um arquivo em /usr/lib/systemd/system/ ou /lib/systemd/system/, pois uma atualização pode sobrescrevê-lo.
Em seguida, verifique os sintomas. Um serviço lento também pode ser causado por uma consulta SQL lenta, um disco saturado, uma fila cheia ou um erro de aplicativo.
journalctl -u nginx.service -b --no-pager
journalctl -k -b | grep -Ei 'oom|out of memory|killed process|memory cgroup'
Se os limites permanecerem em infinity e o log do kernel não mostrar nenhum evento de memória, procure em outro lugar antes de mexer nos cgroups: logs de aplicativos, métricas de disco, latência de rede ou consumo real do processo.
Testar sem tocar no serviço
Para validar uma sintaxe ou medir o efeito de um limite, inicie uma unidade temporária com systemd-run. O teste não modifica o Nginx, PostgreSQL ou seu serviço de negócio.
sudo systemd-run --unit=teste-limite-memoria
--property=MemoryMax=256M
--property=CPUQuota=25%
/usr/bin/bash -c 'sleep 300'
Em seguida, releia as propriedades aplicadas. Para CPUQuota=25%, o systemd pode exibir um valor equivalente a 250ms por segundo.
systemctl show teste-limite-memoria.service
-p MemoryMax -p CPUQuotaPerSecUSec -p ControlGroup -p ActiveState
systemctl cat teste-limite-memoria.service
Pare a unidade de teste assim que terminar. Com sleep, esquecer não é grave, mas esse reflexo evita surpresas quando o teste executa um comando real.
sudo systemctl stop teste-limite-memoria.service
Aplicar um override do systemd
Quando os logs e as medições confirmam que um limite faz sentido, use um override do systemd. O exemplo abaixo fixa um limite alto em 800 MB, um teto rígido em 1 GB e limita o serviço ao equivalente de um núcleo de CPU.
sudo systemctl edit meu-serviço.service
Adicione apenas as diretivas necessárias. Não copie esses valores para um serviço de produção sem ter observado seu consumo normal e seus picos.
[Service]
MemoryHigh=800M
MemoryMax=1G
CPUQuota=100%
Recarregue o systemd e reinicie o serviço somente se a interrupção for aceitável. Remotamente, mantenha uma segunda sessão SSH aberta ao mexer em um componente crítico.
sudo systemctl daemon-reload
sudo systemctl restart meu-serviço.service
systemctl status meu-serviço.service --no-pager
systemctl show meu-serviço.service -p MemoryCurrent -p MemoryHigh -p MemoryMax -p CPUQuotaPerSecUSec
Se o serviço não iniciar ou ficar muito lento, remova o override com cautela. sudo systemctl revert meu-serviço.service remove os overrides locais da unidade. Não o use se o mesmo diretório contém outras configurações a serem mantidas.
Controles após mudança
- Verifique o estado com
systemctl is-active meu-serviço.service. - Releia
MemoryCurrent,MemoryHigh,MemoryMaxeCPUQuotaPerSecUSecapós a reinicialização. - Monitore
journalctl -u meu-serviço.service -be o log do kernel durante o pico de carga que estava causando problemas. - Meça o efeito do lado do aplicativo: tempo de resposta, trabalhos atrasados, filas, erros de usuário.
- Registre o motivo do ajuste, a data, o valor definido e o sintoma corrigido em seu procedimento operacional.
Os cgroups protegem o restante da máquina e tornam os limites visíveis. Eles não corrigem um vazamento de memória, uma consulta muito cara ou um worker dimensionado incorretamente. Se o teto for atingido, mantenha o log, a carga observada e o valor configurado para escolher entre ajustar o limite e corrigir o aplicativo.
Para ir mais longe, a página systemd.resource-control(5) detalha cada diretiva. O guia Nice no Linux ajuda a escolher uma prioridade de CPU quando um teto rígido não é adequado.