Início
» Como fazer
»
Limitar o uso de CPU e memória de um comando com cgroups do Ubuntu
Limitar o uso de CPU e memória de um comando com cgroups do Ubuntu
Se um comando estiver deixando seu desktop Ubuntu lento ou causando falta de memória em um servidor, coloque o comando e seus processos filhos em um cgroup gerenciado pelo systemd com cota de CPU e limite de memória. Nas versões atuais do Ubuntu, systemd-run --scopeessa é a solução mais prática e rápida: o comando é iniciado em um escopo temporário e o systemd aplica os limites por meio dos controles do cgroup.
O exemplo abaixo limita a carga de trabalho à metade da capacidade de uma CPU e 1 GiB de memória. Esses são limites para todo o escopo, incluindo processos filhos; não são uma garantia de que o programa será executado a uma velocidade específica.
Por que um processo precisa de um limite de cgroup?
Um processo ocupado pode competir com aplicativos interativos, enquanto um processo que consome muita memória pode levar a máquina a um estado de recuperação de memória ou falta de memória. Um cgroup agrupa um processo com seus descendentes para que o kernel possa contabilizar e restringir esse grupo. O systemd do Ubuntu fornece uma interface conveniente para esses controles.
As configurações de CPU e memória se comportam de maneira diferente. CPUQuota=50%Limita o tempo de CPU à metade da capacidade de uma CPU, em média, durante um período de agendamento. Um valor de 100 200%representa o tempo equivalente a até duas CPUs quando disponíveis. Este é um limite máximo, não uma prioridade de CPU ou uma reserva. MemoryMax=1GDefine um limite máximo rígido para a memória alocada ao cgroup; se a carga de trabalho não puder se manter abaixo desse limite, o kernel poderá recuperar memória ou invocar um comando de encerramento por falta de memória para um processo nesse cgroup. Escolha um limite que ofereça margem suficiente para o aplicativo e seus processos filhos.
1. Verifique se o Ubuntu está usando cgroup v2.
Os sistemas Ubuntu que utilizam systemd geralmente usam a hierarquia unificada de cgroups v2. Confirme a configuração ativa antes de confiar nos caminhos mostrados posteriormente:
stat -fc %T /sys/fs/cgroup
systemctl --version | head -n 1
O primeiro comando deve retornar um resultado cgroup2fs. Se retornar outro tipo de sistema de arquivos, os caminhos de arquivo do cgroup v2 deste artigo não se aplicam conforme descritos. As propriedades do systemd ainda podem ser suportadas com uma hierarquia diferente, mas use a documentação da distribuição correspondente em vez de copiar os caminhos do v2.
Verifique também a versão exata do systemd caso uma propriedade seja rejeitada. A documentação do Noble no Ubuntu descreve `systemd-version` CPUQuota=e ` MemoryMax=systemd-version` como configurações de controle de recursos; versões mais antigas do Ubuntu podem incluir versões diferentes do systemd.
2. Inicie a carga de trabalho dentro de um escopo limitado.
Execute o programa através de systemd-run, substituindo seu executável e argumentos reais. Para um comando no diretório atual, use ./e passe todos os argumentos após --:
Executar um comando dentro de um escopo transitório do systemd com limites de CPU e memória.
Para um comando de propriedade do usuário, tente executá-lo sem privilégios de sudoadministrador primeiro. Se o systemd informar que um controlador ou propriedade solicitada não está disponível, o administrador do sistema pode não ter permissão para delegá-la; tentar novamente como root pode ser apropriado para uma carga de trabalho em todo o sistema, mas isso altera o contexto de segurança do comando. Não execute um programa não confiável como root indiscriminadamente. Se for necessário usar o administrador do sistema como root, faça isso sudo systemd-run --scope ...somente após considerar essa alteração.
O terminal permanece conectado ao escopo enquanto o comando é executado. Pressionar Ctrl+Cinterrompe a operação em primeiro plano. O escopo é transitório e normalmente desaparece após o término dos processos. É uma maneira conveniente de iniciar um comando com restrições, em vez de uma política persistente para execuções futuras.
3. Localize o escopo e inspecione seus limites.
systemd-runImprime o nome da unidade que cria, normalmente algo como run-….scope. Enquanto o comando ainda estiver em execução, liste a árvore de cgroups:
systemd-cgls
Localize o escopo transitório e confirme se o programa alvo e seus filhos aparecem dentro dele. Isso é importante porque um filho que é executado fora do escopo não será coberto pelo mesmo limite do cgroup.
Utilize a árvore cgroup para confirmar se o programa e seus processos estão agrupados no escopo transitório.
Use o nome do escopo impresso no próximo comando. Substitua run-abc.scopepelo nome real:
systemctl show run-abc.scope \
-p ControlGroup -p CPUQuotaPerSecUSec -p MemoryMax
CPUQuotaPerSecUSec=50000é consistente com uma cota de 50% quando o período de cota do systemd é de 100 ms; MemoryMax=1073741824corresponde a 1 GiB em bytes. Os valores em tempo real são mais úteis do que assumir que todos os hosts aceitarão todas as solicitações sem alterações, visto que os cgroups pai e os controladores disponíveis podem limitar o resultado efetivo.
Verifique o grupo de controle relatado pelo osciloscópio e os limites configurados de CPU e memória.
4. Verifique os arquivos cgroup do kernel e faça os ajustes necessários com segurança.
A ControlGrouppropriedade fornece o caminho do cgroup relativo a /sys/fs/cgroup. Armazene-o em uma variável de ambiente para que os comandos sigam o caminho realmente atribuído à sua máquina:
No cgroup v2, cpu.maxo arquivo contém uma quota e um período em microssegundos. Por exemplo, 50000 100000significa 50 ms de tempo de CPU em cada período de 100 ms. memory.maxO arquivo mostra o limite de memória em bytes. Se os arquivos estiverem faltando, confirme se o escopo ainda está ativo e se o kernel está usando o cgroup v2.
Leia os arquivos cgroup v2 do kernel para verificar a cota configurada e o limite de memória.
Se você iniciou uma unidade de serviço de longa duração com nome e precisa ajustar seus limites, o systemd permite alterar as propriedades de recursos em uma unidade ativa, por exemplo sudo systemctl set-property --runtime my-worker.service CPUQuota=50% MemoryMax=1G. Isso se aplica ao cgroup desse serviço e requer privilégios apropriados. Ele não anexa um processo arbitrário já em execução apenas porque seu PID é conhecido; para um processo único, interrompa-o corretamente e reinicie-o por meio do escopo limitado. Para um serviço persistente, configure as propriedades na unidade de serviço ou em um módulo do systemd e reinicie-o durante uma janela de manutenção apropriada.
Verifique o resultado
Mantenha a carga de trabalho ativa enquanto a inspeciona. Confirme se systemd-cglso processo e seus filhos estão no escopo pretendido, se systemctl showas propriedades solicitadas são reportadas e se os arquivos correspondentes cpu.maxexistem memory.maxcom valores finitos. Quando o processo é encerrado, o escopo transitório é removido, portanto, seus arquivos cgroup podem desaparecer.
Uma quota limita o tempo de CPU, mas não garante uma porcentagem fixa em um monitor de desktop, e um limite rígido de memória pode causar falhas se o aplicativo precisar de mais do que o limite. Se a carga de trabalho se tornar instável, interrompa-a e aumente o limite para um valor seguro e mensurável ou use um MemoryHigh=limite de pressão mais flexível juntamente com um limite maior MemoryMax=. Para obter informações precisas sobre o comportamento, consulte a documentação do systemd e do kernel instalados; as referências oficiais são o manual do systemd-run do Ubuntu , o manual do resource-control do systemd do Ubuntu e a documentação do cgroup v2 do kernel Linux .