Um serviço web que desacelera, um worker morto sem mensagem clara ou um servidor que troca não necessariamente esgotou toda a RAM da máquina. Com o systemd, um limite definido em uma unidade pode ser suficiente para explicar o sintoma.
Os cgroups permitem que o núcleo 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 igual a infinity, o systemd não definiu um teto rígido de memória para este serviço.
Se você partir de um PID, rel leia seu cgroup a partir de /proc. No 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 igual a 0, o serviço não possui um processo principal ativo. Volte para systemctl status e para 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 núcleo não recuperar memória suficiente, um processo do grupo pode ser morto pelo OOM killer.
MemoryHigh é menos severo. O núcleo limita as alocações e tenta recuperar memória quando o cgroup ultrapassa esse limite. Para contenção de um serviço sem que ele caia no primeiro pico, esta é frequentemente uma melhor configuração inicial que MemoryMax.
CPUQuota limita o tempo de CPU disponível para o serviço. CPUQuota=25% representa 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 quota e prioridade. Uma quota 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 uma sobreposição criada 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 vir de 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 outros locais antes de modificar os cgroups: logs de aplicativo, 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, execute uma unidade temporária com systemd-run. O teste não modifica Nginx, PostgreSQL ou seu serviço de negócios.
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
Interrompa a unidade de teste assim que tiver terminado. Com sleep, o esquecimento não é grave, mas esse reflexo evita surpresas quando o teste executa um comando real.
sudo systemctl stop teste-limite-memoria.service
Aplicar uma sobreposição do systemd
Quando os logs e as medidas confirmam que um limite faz sentido, faça uma sobreposição no systemd. O exemplo abaixo define um limite alto em 800 MB, um teto rígido em 1 GB e limita o serviço ao equivalente a um núcleo de CPU.
sudo systemctl edit meu-servico.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, em seguida, reinicie o serviço somente se a interrupção for aceitável. Remotamente, mantenha uma segunda sessão SSH aberta ao tocar em um componente crítico.
sudo systemctl daemon-reload
sudo systemctl restart meu-servico.service
systemctl status meu-servico.service --no-pager
systemctl show meu-servico.service -p MemoryCurrent -p MemoryHigh -p MemoryMax -p CPUQuotaPerSecUSec
Se o serviço não iniciar mais ou se tornar muito lento, remova a sobreposição com cautela. sudo systemctl revert meu-servico.service remove as sobreposições locais da unidade. Não a utilize se o mesmo diretório contiver outras configurações a serem mantidas.
Controles após a alteração
- Verifique o estado com
systemctl is-active meu-servico.service. - Releia
MemoryCurrent,MemoryHigh,MemoryMaxeCPUQuotaPerSecUSecapós a reinicialização. - Monitore
journalctl -u meu-servico.service -be o log do kernel durante o pico de carga que estava apresentando problemas. - Meça o efeito do lado da aplicação: tempo de resposta, jobs atrasados, filas, erros do usuário.
- Registre o motivo da configuração, 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 mal dimensionado. Se o teto for atingido, mantenha o log, a carga observada e o valor configurado para escolher entre ajustar o limite e corrigir a aplicação.
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.