

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
<a name="resource-limiting-systemd"></a>

 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`](epel.md#cpulimit), que anteriormente solo estaba disponible para Amazon Linux en el repositorio [EPEL](epel.md) de terceros. 

 Para obtener información completa, consulte la documentación original de `systemd` para [systemd.resource-control](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html) o la página sobre man para `systemd.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
<a name="resource-limiting-systemd-interactive"></a>

 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. 

**Example Use `systemd-run` en la línea de comandos para ejecutar un proceso, no para limitar el uso de recursos**  

1.  Asegúrese de que el paquete `stress-ng` esté instalado, ya que lo usaremos en nuestro ejemplo. 

   ```
   [ec2-user ~]$ sudo dnf install -y {{stress-ng}}
   ```

1.  Utilice `systemd-run` para 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=1 {{stress-ng --cpu 1 --timeout 10}}
   Running 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.060s
   ```

    La opción `--user` le dice a `systemd-run` que ejecute el comando como el usuario con el que estamos conectados, la opción `--tty` significa que hay un TTY conectado, `--wait` significa esperar hasta que el servicio haya terminado, y la opción `--property=CPUAccounting=1` le indica a `systemd-run` que registre cuánto tiempo de CPU se utiliza para ejecutar el proceso. La opción de línea de comandos `--property` se puede utilizar para pasar la configuración de `systemd-run` que se podría configurar en un archivo de configuración `systemd.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`. 

**Example Use `systemd-run` en la línea de comandos para ejecutar un proceso, limitando el uso de la CPU a 1 segundo**  

1. Asegúrese de que `stress-ng` esté instalado para ejecutar este ejemplo.

1.  La propiedad `LimitCPU` es el equivalente a `ulimit -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ñal `SIGXCPU` y fallará. 

   ```
   [ec2-user ~]$ systemd-run --user --tty --wait --property=CPUAccounting=1 --property=LimitCPU=1 {{stress-ng --cpu 1 --timeout 10}}
   Running 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. 

**Example Use `systemd-run` para limitar un proceso al 10 % del tiempo de CPU en una CPU**  

1. Asegúrese de que `stress-ng` esté instalado para ejecutar este ejemplo.

1.  Vamos a usar la propiedad `CPUQuota` para indicar a `systemd-run` que 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 10}}
   Running 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.014s
   ```

    Observe 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-control](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html) o la página sobre man para `systemd.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-v2`](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html) tiene un montón de detalles sobre cómo funcionan los `cgroups`. 

## Control de recursos en un servicio `systemd`
<a name="resource-limiting-systemd-service"></a>

 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-control](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html) o la página sobre man para `systemd.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. 

**Example 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.   

1.  En primer lugar, necesitamos instalar los paquetes necesarios para este ejemplo. 

   ```
   [ec2-user ~]$ sudo dnf install -y {{memcached libmemcached-awesome-tools}}
   ```

1.  Habilite `memcached.service` y, a continuación, inicie el servicio para que se ejecute `memcached`. 

   ```
   [ec2-user ~]$ sudo systemctl enable {{memcached.service}}
   Created symlink /etc/systemd/system/multi-user.target.wants/memcached.service → /usr/lib/systemd/system/memcached.service.
   [ec2-user ~]$ sudo systemctl start {{memcached.service}}
   ```

1.  Compruebe que `memcached.service` se esté ejecutando. 

   ```
   [ec2-user ~]$ sudo systemctl status {{memcached.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.
   ```

1.  Ahora que `memcached` está instalado y ejecutándose, podemos observar que funciona insertando algunos datos aleatorios en la memoria caché 

    En `/etc/sysconfig/memcached` la variable `CACHESIZE` se 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 utilizando `memcached-tool`, y que `memcached.service` está 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 status {{memcached.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.
   ```

1.  Utilice la propiedad `MemoryMax` para establecer un límite estricto para `memcached.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.conf` o de forma interactiva utilizando el comando `edit` de `systemctl`. 

   ```
   [ec2-user ~]$ sudo systemctl edit {{memcached.service}}
   ```

   Añ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
   ```

1. Indique a `systemd` que vuelva a cargar su configuración

   ```
   [ec2-user ~]$ sudo systemctl daemon-reload
   ```

1. Observe que ahora se está ejecutando `memcached.service` con un límite de memoria de 32 MB.

   ```
   [ec2-user ~]$ sudo systemctl status {{memcached.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.
   ```

1.  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 status {{memcached.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.
   ```

1.  Ahora podemos hacer que `memcached` utilice más de 32 MB de memoria intentando utilizar los 64 MB completos de caché que tiene la configuración predeterminada de `memcached`. 

   ```
   [ec2-user ~]$ for i in $(seq 1 150); do dd if=/dev/random of=$i bs=512k count=1; memcp -s localhost $i; done
   ```

    Observará 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 restringido `memcached.service`. 

   ```
   [ec2-user ~]$ sudo systemctl status {{memcached.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'.
   ```