Gestión de recursos mediante grupos de control

Explica cómo los grupos de control organizan los procesos, cómo systemd aplica las políticas de recursos y cuándo gestionar los cgroups manualmente.

Los grupos de control, denominados cgroups, son una función del núcleo de Oracle Linux que organiza los servicios systemd y, si es necesario, los procesos individuales (PIDs), en grupos jerárquicos para asignar recursos del sistema, como CPU, memoria y E/S.

Por ejemplo, si ha identificado tres procesos a los que se debe asignar tiempo de CPU en un ratio de 150:100:50, puede crear tres cgroups, cada uno con un peso de CPU que corresponda a uno de los tres valores del ratio y asignar el proceso adecuado a cada cgroup.

Importante

Utilice systemd para configurar cgroups.

La creación manual de directorios cgroup en el sistema de archivos virtual /sys/fs/cgroup (como se explica en este tema) puede ser útil para ilustrar conceptos subyacentes. Sin embargo, al utilizar este enfoque para escenarios específicos, como la depuración o la prueba temporales. Para la mayoría de los casos de uso, utilice systemd para configurar cgroups para garantizar una gestión de recursos correcta y persistente.

Por defecto, systemd crea un cgroup para lo siguiente:

  • Cada servicio systemd configurado en el host.

    Por ejemplo, un servidor puede tener el grupo de control NetworkManager.service para agrupar procesos que son propiedad del servicio NetworkManager y el grupo de control firewalld.service para agrupar procesos que son propiedad del servicio firewalld, etc.

  • Cada usuario (UID) en el host.

La funcionalidad cgroup se monta como un sistema de archivos virtual en /sys/fs/cgroup. Cada cgroup tiene un directorio correspondiente en el sistema de archivos /sys/fs/cgroup. Por ejemplo, el cgroups creado por systemd para los servicios que gestiona se puede ver ejecutando el comando ls -l /sys/fs/cgroup/system.slice | grep ".service" como se muestra en el siguiente bloque de código de ejemplo:

ls -l /sys/fs/cgroup/system.slice | grep ".service"
            ...root root 0 Mar 22 10:47 atd.service
            ...root root 0 Mar 22 10:47 auditd.service
            ...root root 0 Mar 22 10:47 chronyd.service
            ...root root 0 Mar 22 10:47 crond.service
            ...root root 0 Mar 22 10:47 dbus-broker.service
            ...root root 0 Mar 22 10:47 dtprobed.service
            ...root root 0 Mar 22 10:47 firewalld.service
            ...root root 0 Mar 22 10:47 httpd.service
            ...

También puede crear cgroups personalizado mediante la creación de directorios en el sistema de archivos virtual /sys/fs/cgroup y la asignación de ID de proceso (PIDs) a diferentes cgroups según los requisitos del sistema. Sin embargo, la práctica recomendada es utilizar systemd para configurar cgroups en lugar de crear cgroups manualmente en /sys/fs/cgroup.

Para conocer el método recomendado de gestión de cgroups mediante systemd, consulte Using Systemd to Manage Control Groups.

Hay dos versiones de grupos de control disponibles en el núcleo de Linux.

Grupos de control versión 1 (cgroups v1)

Proporciona una jerarquía de controlador por recurso. Cada recurso (CPU, memoria, E/S, etc.) tiene su propio árbol de grupos de control. Esto puede dificultar la coordinación entre los recursos. Utiliza una API heredada. Ahora se considera obsoleto, pero disponible para compatibilidad en sistemas compatibles.

Grupos de control versión 2 (cgroups v2)

Utiliza una jerarquía unificada y única para todos los controladores, lo que permite una mejor coordinación entre recursos y una gestión más sencilla. Utiliza una API moderna y simplificada. Esta es la aplicación preferida y desarrollada activamente.

En la siguiente tabla, se resume la disponibilidad por versión de Oracle Linux:

Compatibilidad con la versión de cgroups mediante la versión de Oracle Linux
Versión de Oracle Linux Cgroups v1 Cgroups v2
Oracle Linux 8 Disponible (por defecto) Disponible (activar manualmente)
Oracle Linux 9 Disponible (compatibilidad) Disponible (por defecto)
Oracle Linux 10 No disponible (en desuso) Disponible (por defecto)

Para obtener más información sobre los grupos de control, consulte las páginas del manual cgroups(7) y sysfs(5).

Activar cgroups v2 en Oracle Linux 8

  1. Compruebe los montajes actuales.
    sudo mount -l | grep cgroup

    Si la salida ya muestra cgroup2 en /sys/fs/cgroup, no se necesita ninguna acción adicional.

  2. Agregue el parámetro de inicio de jerarquía unificada.
    sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=1"

    El comando agrega systemd.unified_cgroup_hierarchy=1 a cada entrada del núcleo para que la versión 2 se monte en el inicio.

  3. Reinicie para aplicar el cambio.
  4. Verifique que cgroups v2 esté montado.
    sudo mount -l | grep cgroup

    Busque cgroup2 on /sys/fs/cgroup en la salida.

Verificación de cgroups v2 en Oracle Linux 9 y Oracle Linux 10

Confirme el punto de montaje.
sudo mount -l | grep cgroup
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,seclabel,nsdelegate,memory_recursiveprot)

Acerca de los controladores de recursos del núcleo

Los grupos de control gestionan el uso de recursos mediante controladores de recursos de núcleo. Un controlador de recursos de núcleo representa un único recurso, como el tiempo de CPU, la memoria, el ancho de banda de red o la E/S de disco.

Para identificar los controladores de recursos montados en el sistema, compruebe el contenido del archivo /procs/cgroups, por ejemplo, ejecute:

less /proc/cgroups
#subsys_name    hierarchy       num_cgroups     enabled
cpuset  0       103     1
cpu     0       103     1
cpuacct 0       103     1
blkio   0       103     1
memory  0       103     1
devices 0       103     1
freezer 0       103     1
net_cls 0       103     1
perf_event      0       103     1
net_prio        0       103     1
hugetlb 0       103     1
pids    0       103     1
rdma    0       103     1
misc    0       103     1

Para obtener una explicación detallada de los controladores de recursos del núcleo de cgroups, consulte la página del manual cgroups(7).

Acerca del sistema de archivos del grupo de control

La funcionalidad cgroup se monta como un sistema de archivos jerárquico en /sys/fs/cgroup.

El directorio /sys/fs/cgroup también se denomina grupo de control raíz.

El contenido del directorio del grupo de control raíz varía ligeramente según la versión montada, pero en los sistemas que utilizan cgroups v2, normalmente se ven entradas similares a las siguientes:

ls /sys/fs/cgroup
cgroup.controllers      cpuset.mems.effective  memory.stat
cgroup.max.depth        cpu.stat               misc.capacity
cgroup.max.descendants  dev-hugepages.mount    sys-fs-fuse-connections.mount
cgroup.procs            dev-mqueue.mount       sys-kernel-config.mount
cgroup.stat             init.scope             sys-kernel-debug.mount
cgroup.subtree_control  io.pressure            sys-kernel-tracing.mount
cgroup.threads          io.stat                system.slice
cpu.pressure            memory.numa_stat       user.slice
cpuset.cpus.effective   memory.pressure
Puede utilizar el comando mkdir para crear subdirectorios cgroup en el grupo de control raíz. Por ejemplo, puede crear los siguientes subdirectorios cgroup:
  • /sys/fs/cgroup/MyGroups/

  • /sys/fs/cgroup/MyGroups/cgroup1

  • /sys/fs/cgroup/MyGroups/cgroup2

Nota

La mejor práctica de diseño es que el elemento secundario cgroups tenga al menos 2 niveles de profundidad dentro de /sys/fs/cgroup. Los ejemplos de la lista anterior siguen esta práctica utilizando el primer grupo secundario, MyGroups, como principal que contiene los diferentes cgroups necesarios para el sistema.

Cada cgroup de la jerarquía contiene los siguientes archivos:

cgroup.controllers

Este archivo de solo lectura muestra los controladores disponibles en el cgroup actual. El contenido de este archivo coincide con el contenido del archivo cgroup.subtree_control en el archivo principal cgroup.

cgroup.subtree_control

Este archivo contiene los controladores en el archivo cgroup.controllers que están activados para el secundario inmediato cgroups de cgroup actual.

Cuando un controlador (por ejemplo, pids) está presente en el archivo cgroup.subtree_control, los archivos de interfaz de controlador correspondientes (por ejemplo, pids.max) se crean automáticamente en los secundarios inmediatos del cgroup actual.

Para ver un procedimiento de ejemplo que crea grupos secundarios donde puede implementar la gestión de recursos para una aplicación, consulte Setting CPU Weight to Regulate Distribution of CPU Time.

Para eliminar un cgroup, asegúrese de que cgroup no contenga otros grupos secundarios y, a continuación, elimine el directorio. Por ejemplo, para eliminar el grupo secundario /sys/fs/cgroup/MyGroups/cgroup1, puede ejecutar el siguiente comando:

sudo rmdir /sys/fs/cgroup/MyGroups/cgroup1

Acerca de los modelos de distribución de recursos

Los siguientes modelos de distribución proporcionan formas de implementar el control o la regulación en la distribución de recursos para su uso por parte de cgroups v2:

Pesos

En este modelo, se totalizan los pesos de todos los grupos de control. Cada grupo recibe una fracción del recurso en función de la relación entre el peso del grupo y el peso total.

Considere 10 grupos de control, cada uno con un peso de 100 para un total combinado de 1000. En este caso, cada grupo puede utilizar una décima parte de un recurso especificado.

El peso se utiliza normalmente para distribuir recursos sin estado. Para aplicar este recurso, se utiliza la opción CPUWeight.

Límites

En este modelo, un grupo puede utilizar hasta la cantidad configurada de un recurso. Si un recurso, como el uso de memoria para un proceso, supera el límite, el núcleo puede detener el proceso con un mensaje de falta de memoria (om).

También puede comprometer en exceso los recursos para que la suma de los límites de los subgrupos pueda superar el límite del grupo principal. El compromiso excesivo supone que los recursos de todos los subgrupos no pueden alcanzar todos sus límites al mismo tiempo.

Para implantar este modelo de distribución, se suele utilizar la opción MemoryMax.

Protecciones

En este modelo, a un grupo se le asigna un límite protegido. Si el uso de recursos del grupo permanece dentro de la cantidad protegida, el núcleo no puede privar al grupo del uso del recurso en favor de otros grupos que compiten por el mismo recurso. En este modelo, se permite un compromiso excesivo de recursos.

Para implantar este modelo, se suele utilizar la opción MemoryLow.

Asignaciones

En este modelo, se asigna un importe absoluto específico para el uso de tipos finitos de recursos, como el presupuesto en tiempo real.

Gestión de cgroups v2 con sysfs

Muestra cómo crear y ajustar jerarquías de cgroups v2 directamente en /sys/fs/cgroup para la resolución de problemas o pruebas temporales.

Importante

Utilice systemd para gestionar toda la gestión de recursos siempre que sea posible. Para obtener más información, consulte Uso de Systemd para gestionar grupos de control.

Los ejemplos proporcionados aquí proporcionan el contexto para las acciones que systemd realiza en un sistema y muestran la funcionalidad fuera de systemd. La información proporcionada puede ser útil al depurar problemas con cgroups.

El procedimiento de ejemplo implica asignar tiempo de CPU entre cgroups que cada uno tiene diferentes PID de aplicación asignados. Los valores de PID de aplicación y tiempo de CPU se definen en los archivos cpu.weight y cgroup.procs de cada grupo.

El ejemplo también incluye los pasos necesarios para garantizar que el controlador cpu y sus archivos asociados, incluido el archivo cpu.weight, estén disponibles en cgroups que necesita crear en /sys/fs/cgroup.

Preparación del Grupo de Control para la Distribución del Tiempo de CPU

En este procedimiento, se describe cómo preparar manualmente un grupo de control para gestionar la distribución del tiempo de CPU. Tenga en cuenta que el enfoque recomendado para configurar grupos de control es utilizar systemd.

  1. Verifique que el controlador cpu esté disponible en la parte superior de la jerarquía, en el grupo de control raíz.

    Imprimiendo el contenido del archivo /sys/fs/cgroup/cgroup.controllers en la pantalla:

    sudo cat /sys/fs/cgroup/cgroup.controllers
    cpuset cpu io memory hugetlb pids rdma misc

    Puede agregar los controladores que se muestran en el archivo cgroup.controllers al archivo cgroup.subtree_control en el mismo directorio para que estén disponibles para el secundario inmediato del grupo cgroups.

  2. Agregue el controlador cpu al archivo cgroup.subtree_control para que esté disponible para el secundario inmediato cgroups de la raíz.

    Por defecto, solo los controladores memory y pids están en el archivo. Para agregar el controlador cpu, escriba:

    echo "+cpu" | sudo tee /sys/fs/cgroup/cgroup.subtree_control
    
  3. De manera opcional, verifique que el controlador cpu se haya agregado como se esperaba.
    sudo cat /sys/fs/cgroup/cgroup.subtree_control
    cpu memory pids
  4. Cree un grupo secundario en el grupo de control raíz para convertirse en el nuevo grupo de control para gestionar los recursos de CPU en las aplicaciones.
    sudo mkdir /sys/fs/cgroup/MyGroups
  5. De manera opcional, muestre el contenido del nuevo subdirectorio o grupo secundario y confirme que el controlador cpu está presente como se esperaba.
    ls -l /sys/fs/cgroup/MyGroups
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 cgroup.controllers
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 cgroup.events
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.freeze
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.max.depth
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.max.descendants
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.procs
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 cgroup.stat
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cgroup.subtree_control
    …​
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 cpu.stat
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cpu.weight
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 cpu.weight.nice
    …​
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 memory.events.local
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 memory.high
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 memory.low
    …​
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 pids.current
    -r—​r—​r--. 1 root root 0 Jun  1 10:33 pids.events
    -rw-r—​r--. 1 root root 0 Jun  1 10:33 pids.max
  6. Active el controlador cpu en el archivo cgroup.subtree_control en el directorio MyGroups para que esté disponible para su hijo inmediato cgroups.
    echo "+cpu" | sudo tee /sys/fs/cgroup/MyGroups/cgroup.subtree_control
  7. De manera opcional, verifique que el controlador cpu esté activado para grupos secundarios en MyGroups.
    sudo cat /sys/fs/cgroup/MyGroups/cgroup.subtree_control
    cpu

Definición del Peso de CPU para Regular la Distribución del Tiempo de CPU

Este procedimiento describe cómo establecer el peso de CPU para tres procesos diferentes mediante un grupo de control para gestionar la distribución del tiempo de CPU. Tenga en cuenta que el enfoque recomendado para configurar grupos de control es utilizar systemd.

Este procedimiento se basa en las siguientes suposiciones:

  • La aplicación que consume recursos de CPU en exceso es sha1sum, como se muestra en la siguiente salida de ejemplo del comando top:

    sudo top
    ...
    PID   USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
    33301 root      20   0   18720   1756   1468 R  99.0   0.0   0:31.09 sha1sum
    33302 root      20   0   18720   1772   1480 R  99.0   0.0   0:30.54 sha1sum
    33303 root      20   0   18720   1772   1480 R  99.0   0.0   0:30.54 sha1sum
    1 root      20   0  109724  17196  11032 S   0.0   0.1   0:03.28 systemd                     
    2 root      20   0       0      0      0 S   0.0   0.0   0:00.00 kthreadd                    
    3 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_gp                      
    4 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_par_gp                  
              ...
  • Los procesos sha1sum tienen los PID 33301, 33302 y 33303, como se muestra en la salida de ejemplo anterior.

Importante

Como requisito previo para el siguiente procedimiento, debe completar la preparación de cgroup-v2 como se describe en Preparing the Control Group for Distribution of CPU Time. Si omitió esas preparaciones, no puede completar este procedimiento.

  1. Cree 3 grupos secundarios en el subdirectorio MyGroups.
    sudo mkdir /sys/fs/cgroup/MyGroups/g1
    sudo mkdir /sys/fs/cgroup/MyGroups/g2
    sudo mkdir /sys/fs/cgroup/MyGroups/g3
  2. Configure el peso de la CPU para cada grupo secundario.
    echo "150" | sudo tee /sys/fs/cgroup/MyGroups/g1/cpu.weight
    echo "100" | sudo tee /sys/fs/cgroup/MyGroups/g2/cpu.weight
    echo "50" | sudo tee /sys/fs/cgroup/MyGroups/g3/cpu.weight
  3. Aplique los PID de aplicación a sus correspondientes grupos secundarios.
    echo "33301" | sudo tee /sys/fs/cgroup/MyGroups/g1/cgroup.procs
    echo "33302" | sudo tee /sys/fs/cgroup/MyGroups/g2/cgroup.procs
    echo "33303" | sudo /sys/fs/cgroup/MyGroups/g3/cgroup.procs

    Estos comandos definen las aplicaciones seleccionadas para que se conviertan en miembros de los grupos de control MyGroups/g*/. El tiempo de CPU para cada proceso sha1sum depende de la distribución de tiempo de CPU configurada para cada grupo.

    Los pesos de los grupos g1, g2 y g3 que tienen procesos en ejecución se suman en el nivel de MyGroups, que es el grupo de control principal.

    Con esta configuración, cuando todos los procesos se ejecutan al mismo tiempo, el núcleo asigna a cada uno de los procesos sha1sum el tiempo de CPU proporcionado en función de su archivo cpu.weight correspondiente de cgroup, de la siguiente manera:

    Grupo secundario Configuración de cpu.weight Porcentaje de asignación de tiempo de CPU
    g1 150 ~50% (150/300)
    g2 100 ~33% (100/300)
    g3 50 ~16% (50/300)

    Si un grupo secundario no tiene procesos en ejecución, la asignación de tiempo de CPU para los procesos en ejecución se vuelve a calcular en función del peso total de los grupos secundarios restantes con procesos en ejecución. Por ejemplo, si el grupo secundario g2 no tiene ningún proceso en ejecución, el peso total se convierte en 200, que es el peso de g1+g3. En este caso, el tiempo de CPU para g1 se convierte en 150/200 (~75%) y para g3, 50/200 (~25%)

  4. Compruebe que las aplicaciones se están ejecutando en los grupos de control especificados.
    sudo cat /proc/33301/cgroup /proc/33302/cgroup /proc/33303/cgroup
    0::/MyGroups/g1
    0::/MyGroups/g2
    0::/MyGroups/g3
  5. Compruebe el consumo actual de CPU después de definir los pesos de CPU.
    top
    ...
    PID   USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
    33301 root      20   0   18720   1748   1460 R  49.5   0.0 415:05.87 sha1sum
    33302 root      20   0   18720   1756   1464 R  32.9   0.0 412:58.33 sha1sum
    33303 root      20   0   18720   1860   1568 R  16.3   0.0 411:03.12 sha1sum
    760 root      20   0  416620  28540  15296 S   0.3   0.7   0:10.23 tuned
    1 root      20   0  186328  14108   9484 S   0.0   0.4   0:02.00 systemd
    2 root      20   0       0      0      0 S   0.0   0.0   0:00.01 kthread
    ...