Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Limite el uso de recursos de procesos en AL2023 mediante systemd
En Amazon Linux 2023 (AL2023), recomendamos usar systemd para controlar qué recursos pueden usar los procesos o grupos de procesos. El uso de systemd es una alternativa potente y fácil de usar tanto para manipular cgroups manualmente como para utilizar utilidades como cpulimit, que anteriormente solo estaba disponible para Amazon Linux en el repositorio EPEL de terceros.
Para obtener información completa, consulte la documentación original de systemd para systemd.resource-controlsystemd.resource-control en una instancia de AL2023.
En los ejemplos siguientes se utilizará la prueba de stress de la CPU stress-ng (incluida en el paquete stress-ng) para simular una aplicación con un uso intensivo de la CPU y memcached con un uso intensivo de memoria.
En los siguientes ejemplos, se describe cómo establecer un límite de CPU para un comando único y un límite de memoria para un servicio. La mayoría de las restricciones de recursos que ofrece systemd se pueden utilizar en cualquier lugar en el que systemd ejecute un proceso, y se pueden utilizar varias al mismo tiempo. Los ejemplos siguientes se limitan a una sola restricción con fines ilustrativos.
Control de recursos con systemd-run para ejecutar comandos únicos
Si bien suele asociarse a los servicios del sistema, también pueden utilizar systemd los usuarios que no son root para ejecutar servicios, programar temporizadores o ejecutar procesos únicos. En el siguiente ejemplo, vamos a utilizar stress-ng como aplicación de ejemplo. En el primer ejemplo, la ejecutaremos con systemd-run en la cuenta ec2-user predeterminada y, en el segundo, pondremos límites al uso de la CPU.
ejemplo Use systemd-run en la línea de comandos para ejecutar un proceso, no para limitar el uso de recursos
-
Asegúrese de que el paquete
stress-ngesté instalado, ya que lo usaremos en nuestro ejemplo.[ec2-user ~]$sudo dnf install -ystress-ng -
Utilice
systemd-runpara ejecutar una prueba de estrés de la CPU de 10 segundos sin limitar la cantidad de CPU que puede utilizar.[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.060sLa opción
--userle dice asystemd-runque ejecute el comando como el usuario con el que estamos conectados, la opción--ttysignifica que hay un TTY conectado,--waitsignifica esperar hasta que el servicio haya terminado, y la opción--property=CPUAccounting=1le indica asystemd-runque registre cuánto tiempo de CPU se utiliza para ejecutar el proceso. La opción de línea de comandos--propertyse puede utilizar para pasar la configuración desystemd-runque se podría configurar en un archivo de configuraciónsystemd.unit.
Cuando se le indica que coloque carga en la CPU, el programa stress-ng utilizará todo el tiempo de CPU disponible para realizar su prueba durante el tiempo que usted le pida que se ejecute. Para una aplicación en el mundo real, puede ser conveniente establecer un límite en el tiempo total de ejecución de un proceso. En el siguiente ejemplo, le pediremos a stress-ng que se ejecute durante más tiempo que la restricción de duración máxima que le imponemos utilizando systemd-run.
ejemplo Use systemd-run en la línea de comandos para ejecutar un proceso, limitando el uso de la CPU a 1 segundo
-
Asegúrese de que
stress-ngesté instalado para ejecutar este ejemplo. -
La propiedad
LimitCPUes el equivalente aulimit -t, lo que limitará la cantidad máxima de tiempo en la CPU que este proceso podrá utilizar. En este caso, dado que estamos pidiendo una ejecución de stress de 10 segundos y estamos limitando el uso de la CPU a 1 segundo, el comando recibirá una señalSIGXCPUy fallará.[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
Lo más habitual es restringir el porcentaje de tiempo de CPU que puede consumir un proceso concreto. En el siguiente ejemplo, restringiremos el porcentaje de tiempo de CPU que stress-ng puede consumir. En el caso de un servicio real, puede ser conveniente limitar el porcentaje máximo de tiempo de CPU que puede consumir un proceso en segundo plano a fin de dejar recursos libres para el proceso que atiende las solicitudes de los usuarios.
ejemplo Use systemd-run para limitar un proceso al 10 % del tiempo de CPU en una CPU
-
Asegúrese de que
stress-ngesté instalado para ejecutar este ejemplo. -
Vamos a usar la propiedad
CPUQuotapara indicar asystemd-runque restrinja el uso de la CPU para el comando que vamos a ejecutar. No estamos limitando la cantidad de tiempo que puede ejecutarse el proceso, solo la cantidad de CPU que puede 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 cómo la contabilidad de la CPU nos indica que, aunque el servicio se ejecutó durante 10 segundos, solo consumió 1 segundo de tiempo real de CPU.
Hay muchas formas de configurar systemd para limitar el uso de recursos de la CPU, la memoria, las redes y las E/S. Para obtener información completa, consulte la documentación original de systemd para systemd.resource-controlsystemd.resource-control en una instancia de AL2023.
Mientras tanto, systemd usa características del kernel de Linux, como cgroups, para poner en práctica estos límites sin que tengas que configurarlos a mano. La documentación del kernel de Linux para cgroup-v2cgroups.
Control de recursos en un servicio systemd
Hay varios parámetros que se pueden agregar a la sección [Service] de los servicios systemd para controlar el uso de los recursos del sistema. Estos incluyen límites estrictos y flexibles. Para conocer el comportamiento exacto de cada opción, consulta la documentación original de systemd para systemd.resource-controlsystemd.resource-control en una instancia de AL2023.
Los límites más utilizados son MemoryHigh, para especificar un límite de restricción en el uso de la memoria, MemoryMax, para establecer un límite máximo estricto (que, una vez alcanzado, se invoca el OOM Killer), y CPUQuota (como se ilustra en la sección anterior). También es posible configurar ponderaciones y prioridades en lugar de números fijos.
ejemplo Uso de systemd para establecer límites de uso de memoria en los servicios
En este ejemplo, estableceremos un límite estricto de uso de memoria para memcached, una caché simple de clave-valor, y mostraremos cómo se invoca el OOM Killer para ese servicio en lugar de para todo el sistema.
-
En primer lugar, necesitamos instalar los paquetes necesarios para este ejemplo.
[ec2-user ~]$sudo dnf install -ymemcached libmemcached-awesome-tools -
Habilite
memcached.servicey, a continuación, inicie el servicio para que se ejecutememcached.[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 -
Compruebe que
memcached.servicese esté ejecutando.[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. -
Ahora que
memcachedestá instalado y ejecutándose, podemos observar que funciona insertando algunos datos aleatorios en la memoria cachéEn
/etc/sysconfig/memcachedla variableCACHESIZEse establece en 64 de forma predeterminada, es decir, 64 megabytes. Al insertar más datos en la caché que el tamaño máximo de la misma, podemos ver que la llenamos y que algunos elementos se eliminan utilizandomemcached-tool, y quememcached.serviceestá utilizando alrededor de 64 MB de memoria.[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. -
Utilice la propiedad
MemoryMaxpara establecer un límite estricto paramemcached.service, que, si se alcanza, activará OOM Killer. Se pueden configurar opciones adicionales para el servicio añadiéndolas a un archivo de anulación. Esto se puede hacer editando directamente el archivo/etc/systemd/system/memcached.service.d/override.confo de forma interactiva utilizando el comandoeditdesystemctl.[ec2-user ~]$sudo systemctl editmemcached.serviceAñada lo siguiente a la modificación para establecer un límite máximo de 32 MB de memoria para el servicio.
[Service] MemoryMax=32M -
Indique a
systemdque vuelva a cargar su configuración[ec2-user ~]$sudo systemctl daemon-reload -
Observe que ahora se está ejecutando
memcached.servicecon un límite de memoria 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. -
El servicio funcionará normalmente si utiliza menos de 32 MB de memoria, lo que podemos comprobar cargando menos de 32 MB de datos aleatorios en la memoria caché y comprobando después el estado del servicio.
[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. -
Ahora podemos hacer que
memcachedutilice más de 32 MB de memoria intentando utilizar los 64 MB completos de caché que tiene la configuración predeterminada dememcached.[ec2-user ~]$for i in $(seq 1 150); do dd if=/dev/random of=$i bs=512k count=1; memcp -s localhost $i; doneObservará que en algún momento del comando anterior se producen errores de conexión con el servidor
memcached. Esto se debe a que OOM Killer ha cancelado el proceso debido a la restricción que le pusimos. El resto del sistema funcionará con normalidad y el OOM Killer no tendrá en cuenta ningún otro proceso, ya que solo hemos restringidomemcached.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'.