As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
Limitar o uso de recursos do processo no AL2023 usando systemd
No Amazon Linux 2023 (AL2023), recomendamos o uso de systemd para controlar quais recursos podem ser usados por processos ou grupos de processos. O uso de systemd é um substituto poderoso e fácil de usar para manipular cgroups manualmente ou usar utilitários como cpulimit, que antes só estavam disponíveis para o Amazon Linux no repositório EPEL de terceiros.
Para obter informações abrangentes, consulte a documentação do systemd upstream para systemd.resource-controlsystemd.resource-control em uma instância do AL2023.
Os exemplos abaixo usarão o teste de estresse da CPU stress-ng (do pacote stress-ng) para simular uma aplicação com uso intenso da CPU e memcached para simular uma aplicação com uso intenso da memória.
Os exemplos abaixo abrangem a aplicação de um limite de CPU em um comando único e um limite de memória em um serviço. A maioria das restrições de recursos que systemd oferece podem ser usadas em qualquer lugar que systemd execute um processo, e é possível usar várias ao mesmo tempo. Os exemplos abaixo são limitados a uma única restrição para fins ilustrativos.
Controle de recursos com systemd-run para execução de comandos únicos
Embora comumente associado aos serviços do sistema, systemd também pode ser usado por usuários que não são raiz para executar serviços, agendar temporizadores ou executar processos pontuais. No exemplo a seguir, vamos usar stress-ng como a aplicação. No primeiro exemplo, vamos executá-la usando systemd-run na conta padrão ec2-user e, no segundo exemplo, vamos aplicar limites quanto ao uso da CPU.
exemplo : usar systemd-run na linha de comandos para executar um processo, sem limitar o uso de recursos
-
Garanta que o pacote
stress-ngesteja instalado, pois vamos usá-lo no exemplo.[ec2-user ~]$sudo dnf install -ystress-ng -
Use
systemd-runpara executar um teste de estresse da CPU de 10 segundos sem limitar a quantidade de CPU que ele pode usar.[ec2-user ~]$systemd-run --user --tty --wait --property=CPUAccounting=1stress-ng --cpu 1 --timeout 10Running as unit: run-u6.service Press ^] three times within 1s to disconnect TTY. stress-ng: info: [339368] setting to a 10 second run per stressor stress-ng: info: [339368] dispatching hogs: 1 cpu stress-ng: info: [339368] successful run completed in 10.00s Finished with result: success Main processes terminated with: code=exited/status=0 Service runtime: 10.068s CPU time consumed: 9.060sA opção
--userinstruisystemd-runa executar o comando como o usuário conectado, a opção--ttysignifica que há um TTY anexado,--waitindica para esperar até que o serviço seja concluído e a opção--property=CPUAccounting=1instruisystemd-runa registrar quanto tempo de CPU é usado na execução do processo. A opção da linha de comandos--propertypode ser usada para enviar as configurações desystemd-runque podem estar definidas em um arquivo de configuraçãosystemd.unit.
Quando instruído a colocar carga na CPU, o programa stress-ng usará todo o tempo de CPU disponível para realizar o teste durante o período solicitado. Para uma aplicação do mundo real, pode ser desejável limitar o tempo total de execução de um processo. No exemplo abaixo, solicitaremos que stress-ng seja executado por um tempo maior do que a restrição de duração máxima que foi imposta usando systemd-run.
exemplo : usar systemd-run na linha de comandos para executar um processo, limitando o uso da CPU a 1 segundo
-
Verifique se
stress-ngestá instalado para executar este exemplo. -
A propriedade
LimitCPUé equivalente aulimit -t, que limitará o tempo máximo que esse processo poderá usar a CPU. Nesse caso, como estamos solicitando uma execução de estresse de 10 segundos e limitando o uso da CPU a 1 segundo, o comando receberá um sinalSIGXCPUe falhará.[ec2-user ~]$systemd-run --user --tty --wait --property=CPUAccounting=1 --property=LimitCPU=1stress-ng --cpu 1 --timeout 10Running as unit: run-u12.service Press ^] three times within 1s to disconnect TTY. stress-ng: info: [340349] setting to a 10 second run per stressor stress-ng: info: [340349] dispatching hogs: 1 cpu stress-ng: fail: [340349] cpu instance 0 corrupted bogo-ops counter, 1370 vs 0 stress-ng: fail: [340349] cpu instance 0 hash error in bogo-ops counter and run flag, 3250129726 vs 0 stress-ng: fail: [340349] metrics-check: stressor metrics corrupted, data is compromised stress-ng: info: [340349] unsuccessful run completed in 1.14s Finished with result: exit-code Main processes terminated with: code=exited/status=2 Service runtime: 1.201s CPU time consumed: 1.008s
Mais comumente, talvez você queira restringir a porcentagem do tempo da CPU que pode ser consumido por um processo específico. No exemplo abaixo, restringiremos a porcentagem do tempo da CPU que pode ser consumido por stress-ng. Para um serviço do mundo real, pode ser desejável limitar a porcentagem máxima do tempo da CPU que um processo em segundo plano pode consumir para deixar os recursos livres para o processo que atende às solicitações do usuário.
exemplo : usar systemd-run para limitar um processo a 10% do tempo de uma CPU
-
Verifique se
stress-ngestá instalado para executar este exemplo. -
Vamos usar a propriedade
CPUQuotapara instruirsystemd-runa restringir o uso da CPU pelo comando que vamos executar. Não vamos limitar a quantidade de tempo que o processo pode permanecer em execução, apenas a quantidade de CPU que ele pode usar.[ec2-user ~]$systemd-run --user --tty --wait --property=CPUAccounting=1 --property=CPUQuota=10%stress-ng --cpu 1 --timeout 10Running as unit: run-u13.service Press ^] three times within 1s to disconnect TTY. stress-ng: info: [340664] setting to a 10 second run per stressor stress-ng: info: [340664] dispatching hogs: 1 cpu stress-ng: info: [340664] successful run completed in 10.08s Finished with result: success Main processes terminated with: code=exited/status=0 Service runtime: 10.140s CPU time consumed: 1.014sObserve como a contabilidade da CPU nos informa que, embora o serviço tenha sido executado por 10 segundos, ele consumiu apenas 1 segundo de tempo real da CPU.
Há várias maneiras de configurar systemd para limitar o uso de recursos de CPU, memória, rede e E/S. Consulte a documentação do systemd upstream para systemd.resource-controlsystemd.resource-control em uma instância do AL2023 para obter informações abrangentes.
Nos bastidores, systemd usa recursos de kernel do Linux, como cgroups, para implementar esses limites, evitando a necessidade de configurá-los manualmente. A documentação de kernel do Linux para cgroup-v2cgroups funcionam.
Controle de recursos em um serviço de systemd
Há vários parâmetros que podem ser adicionados à seção [Service] dos serviços de systemd para controlar o uso dos recursos do sistema. Isso inclui limites rígidos e flexíveis. Para conhecer o comportamento exato de cada opção, consulte a documentação de systemd upstream para systemd.resource-controlsystemd.resource-control em uma instância do AL2023.
Os limites comumente usados são MemoryHigh para especificar um limite de controle de utilização para o uso de memória, MemoryMax para definir um limite superior rígido (uma vez atingido, o OOM Killer é invocado) e CPUQuota (conforme ilustrado na seção anterior). Também é possível configurar pesos e prioridades em vez de números fixos.
exemplo : usar systemd para definir limites de uso de memória para os serviços
Neste exemplo, definiremos um limite rígido de uso de memória para memcached, um cache simples de valores-chave, e mostraremos como o OOM Killer é invocado para esse serviço e não para todo o sistema.
-
Primeiro, precisamos instalar os pacotes necessários para este exemplo.
[ec2-user ~]$sudo dnf install -ymemcached libmemcached-awesome-tools -
Habilite
memcached.service, depois inicie o serviço para quememcachedesteja em execução.[ec2-user ~]$sudo systemctl enablememcached.serviceCreated symlink /etc/systemd/system/multi-user.target.wants/memcached.service → /usr/lib/systemd/system/memcached.service.[ec2-user ~]$sudo systemctl startmemcached.service -
Verifique se
memcached.serviceestá em execução.[ec2-user ~]$sudo systemctl statusmemcached.service● memcached.service - memcached daemon Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled) Active: active (running) since Fri 2025-01-31 22:36:42 UTC; 1s ago Main PID: 356294 (memcached) Tasks: 10 (limit: 18907) Memory: 1.8M CPU: 20ms CGroup: /system.slice/memcached.service └─356294 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1 Jan 31 22:35:36 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon. -
Agora que
memcachedestá instalado e em execução, podemos observar que ele funciona inserindo alguns dados aleatórios no cache.Em
/etc/sysconfig/memcached, a variávelCACHESIZEé definida como 64 por padrão, o que significa 64 megabytes. Ao inserir mais dados do que o tamanho máximo do cache, podemos ver que preenchemos o cache e alguns itens são removidos usandomemcached-tool, e quememcached.serviceestá usando cerca de 64 MB de memória.[ec2-user ~]$for i in $(seq 1 150); do dd if=/dev/random of=$i bs=512k count=1; memcp -s localhost $i; done[ec2-user ~]$memcached-tool localhost display# Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM 2 120B 0s 1 0 no 0 0 0 39 512.0K 4s 63 126 yes 24 2 0[ec2-user ~]$sudo systemctl statusmemcached.service● memcached.service - memcached daemon Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled) Active: active (running) since Fri 2025-01-31 22:36:42 UTC; 7min ago Main PID: 356294 (memcached) Tasks: 10 (limit: 18907) Memory: 66.7M CPU: 203ms CGroup: /system.slice/memcached.service └─356294 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1 Jan 31 22:36:42 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon. -
Use a propriedade
MemoryMaxpara definir um limite rígido paramemcached.service. Se esse limite atingido, o OOM Killer será invocado. Opções adicionais podem ser definidas para o serviço adicionando-as a um arquivo de substituição. Isso pode ser feito editando diretamente o arquivo/etc/systemd/system/memcached.service.d/override.confou de forma interativa, usando o comandoeditdesystemctl.[ec2-user ~]$sudo systemctl editmemcached.serviceAdicione o seguinte à substituição para definir um limite rígido de 32 MB de memória para o serviço.
[Service] MemoryMax=32M -
Instrua
systemda recarregar sua configuração.[ec2-user ~]$sudo systemctl daemon-reload -
Observe que
memcached.serviceagora está sendo executado com um limite de memória de 32 MB.[ec2-user ~]$sudo systemctl statusmemcached.service● memcached.service - memcached daemon Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled) Drop-In: /etc/systemd/system/memcached.service.d └─override.conf Active: active (running) since Fri 2025-01-31 23:09:13 UTC; 49s ago Main PID: 358423 (memcached) Tasks: 10 (limit: 18907) Memory: 1.8M (max: 32.0M available: 30.1M) CPU: 25ms CGroup: /system.slice/memcached.service └─358423 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1 Jan 31 23:09:13 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon. -
O serviço funcionará normalmente usando menos de 32 MB de memória, o que podemos confirmar ao carregar menos de 32 MB de dados aleatórios no cache e verificar o status do serviço.
[ec2-user ~]$for i in $(seq 1 30); do dd if=/dev/random of=$i bs=512k count=1; memcp -s localhost $i; done[ec2-user ~]$sudo systemctl statusmemcached.service● memcached.service - memcached daemon Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled) Drop-In: /etc/systemd/system/memcached.service.d └─override.conf Active: active (running) since Fri 2025-01-31 23:14:48 UTC; 3s ago Main PID: 359492 (memcached) Tasks: 10 (limit: 18907) Memory: 18.2M (max: 32.0M available: 13.7M) CPU: 42ms CGroup: /system.slice/memcached.service └─359492 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1 Jan 31 23:14:48 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon. -
Agora podemos fazer com que
memcacheduse mais de 32 MB de memória, tentando usar os 64 MB completos de cache que são a configuração padrão dememcached.[ec2-user ~]$for i in $(seq 1 150); do dd if=/dev/random of=$i bs=512k count=1; memcp -s localhost $i; doneVocê observará que em algum momento durante o comando acima, há erros de conexão com o servidor de
memcached. Isso ocorre porque o OOM Killer encerrou o processo devido à restrição que impusemos a ele. O restante do sistema funcionará normalmente e nenhum outro processo será considerado pelo OOM Killer, já que restringimos apenasmemcached.service.[ec2-user ~]$sudo systemctl statusmemcached.service● memcached.service - memcached daemon Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled) Drop-In: /etc/systemd/system/memcached.service.d └─override.conf Active: failed (Result: oom-kill) since Fri 2025-01-31 23:20:28 UTC; 2s ago Duration: 2.901s Process: 360130 ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS (code=killed, signal=KILL) Main PID: 360130 (code=killed, signal=KILL) CPU: 94ms Jan 31 23:20:25 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon. Jan 31 23:20:28 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: memcached.service: A process of this unit has been killed by the OOM killer. Jan 31 23:20:28 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: memcached.service: Main process exited, code=killed, status=9/KILL Jan 31 23:20:28 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: memcached.service: Failed with result 'oom-kill'.