Gestion des ressources à l'aide de groupes de contrôle

Explique comment les groupes de contrôle organisent les processus, comment systemd applique les politiques de ressources et quand gérer les cgroups manuellement.

Les groupes de contrôle, appelés cgroups, sont une fonction de noyau Oracle Linux qui organise les services systemd et, si nécessaire, les processus individuels (PIDs) en groupes hiérarchiques pour l'affectation de ressources système, telles que l'UC, la mémoire et les E/S.

Par exemple, si vous avez identifié trois processus qui doivent être alloués du temps UC dans un ratio de 150:100:50, vous pouvez créer trois cgroups, chacun avec une pondération UC correspondant à l'une des trois valeurs du ratio, et affecter le processus approprié à chaque cgroup.

Important

Utilisez systemd pour configurer cgroups.

La création manuelle de répertoires cgroup dans le système de fichiers virtuel /sys/fs/cgroup (comme indiqué dans cette rubrique) peut être utile pour illustrer les concepts sous-jacents. Cependant, lorsque vous utilisez cette approche pour des scénarios spécifiques, tels que le débogage temporaire ou le test. Pour la plupart des cas d'utilisation, utilisez systemd pour configurer cgroups afin de garantir une gestion correcte et persistante des ressources.

Par défaut, systemd crée une valeur cgroup pour les éléments suivants :

  • Chaque service systemd configuré sur l'hôte.

    Par exemple, un serveur peut avoir le groupe de contrôle NetworkManager.service pour regrouper les processus détenus par le service NetworkManager et le groupe de contrôle firewalld.service pour regrouper les processus détenus par le service firewalld, etc.

  • Chaque utilisateur (UID) sur l'hôte.

La fonctionnalité cgroup est montée en tant que système de fichiers virtuel sous /sys/fs/cgroup. Chaque cgroup a un répertoire correspondant dans le système de fichiers /sys/fs/cgroup. Par exemple, cgroups créé par systemd pour les services qu'il gère peut être vu en exécutant la commande ls -l /sys/fs/cgroup/system.slice | grep ".service", comme illustré dans l'exemple de bloc de code suivant :

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

Vous pouvez également créer des cgroups personnalisés en créant des répertoires sous le système de fichiers virtuel /sys/fs/cgroup et en affectant des ID processus (PIDs) à des cgroups différents selon les exigences du système. Toutefois, il est recommandé d'utiliser systemd pour configurer cgroups au lieu de créer cgroups manuellement sous /sys/fs/cgroup.

Pour la méthode recommandée pour gérer cgroups au moyen de systemd, voir Utilisation de Systemd pour gérer les groupes de contrôle.

Deux versions des groupes de contrôle sont disponibles dans le noyau Linux.

Groupes de contrôle version 1 (cgroups v1)

Fournit une hiérarchie de contrôleur par ressource. Chaque ressource (UC, mémoire, E/S, etc.) possède son propre arbre de groupes de contrôle. Cela peut rendre la coordination entre les ressources difficile. Utilise une API existante. Désormais considéré comme obsolète, mais disponible pour compatibilité sur les systèmes pris en charge.

Groupes de contrôle version 2 (cgroups v2)

Utilise une hiérarchie unifiée et unique pour tous les contrôleurs, ce qui permet une meilleure coordination entre les ressources et une gestion plus simple. Utilise une API moderne et simplifiée. C'est la mise en œuvre préférée et activement développée.

Le tableau suivant résume la disponibilité par version d'Oracle Linux :

Prise en charge des versions cgroups par Oracle Linux
Version d'Oracle Linux cgroups v1 cgroups v2
Oracle Linux 8 Disponible (par défaut) Disponible (activer manuellement)
Oracle Linux 9 Disponible (compatibilité) Disponible (par défaut)
Oracle Linux 10 Non disponible (obsolète) Disponible (par défaut)

Pour plus d'informations sur les groupes de contrôle, consultez les pages de manuel cgroups(7) et sysfs(5).

Activer cgroups v2 sur Oracle Linux 8

  1. Vérifiez les montages courants.
    sudo mount -l | grep cgroup

    Si la sortie affiche déjà cgroup2 sur /sys/fs/cgroup, aucune autre action n'est requise.

  2. Ajoutez le paramètre d'initialisation de la hiérarchie unifiée.
    sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=1"

    La commande ajoute systemd.unified_cgroup_hierarchy=1 à chaque entrée de noyau de sorte que version2 se monte au démarrage.

  3. Redémarrez pour appliquer la modification.
  4. Vérifiez que cgroups v2 est monté.
    sudo mount -l | grep cgroup

    Recherchez cgroup2 on /sys/fs/cgroup dans la sortie.

Vérifier les cgroups v2 sur Oracle Linux 9 et Oracle Linux 10

Confirmez le point de montage.
sudo mount -l | grep cgroup
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,seclabel,nsdelegate,memory_recursiveprot)

À propos des contrôleurs de ressources du noyau

Les groupes de contrôle gèrent l'utilisation des ressources au moyen des contrôleurs de ressources du noyau. Un contrôleur de ressources de noyau représente une seule ressource, telle que le temps CPU, la mémoire, la bande passante réseau ou les E/S disque.

Pour identifier les contrôleurs de ressources montés dans le système, vérifiez le contenu du fichier /procs/cgroups, par exemple exécutez :

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

Pour une explication détaillée des contrôleurs de ressources du noyau de cgroups, voir la page de manuel cgroups(7).

À propos du système de fichiers du groupe de contrôle

La fonctionnalité cgroup est montée en tant que système de fichiers hiérarchique dans /sys/fs/cgroup.

Le répertoire /sys/fs/cgroup est également appelé groupe de contrôle racine.

Le contenu du répertoire du groupe de contrôle racine varie légèrement en fonction de la version montée, mais sur les systèmes utilisant cgroups v2, vous voyez généralement des entrées similaires aux suivantes :

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
Vous pouvez utiliser la commande mkdir pour créer des sous-répertoires cgroup dans le groupe de contrôle racine. Par exemple, vous pouvez créer les sous-répertoires cgroup suivants :
  • /sys/fs/cgroup/MyGroups/

  • /sys/fs/cgroup/MyGroups/cgroup1

  • /sys/fs/cgroup/MyGroups/cgroup2

Note

Les meilleures pratiques de conception permettent à l'enfant cgroups d'avoir au moins 2 niveaux de profondeur dans /sys/fs/cgroup. Les exemples de la liste précédente suivent cet exercice en utilisant le premier groupe enfant, MyGroups, en tant que parent qui contient les différents cgroups nécessaires pour le système.

Chaque cgroup de la hiérarchie contient les fichiers suivants :

cgroup.controllers

Ce fichier en lecture seule répertorie les contrôleurs disponibles dans le fichier cgroup courant. Le contenu de ce fichier correspond au contenu du fichier cgroup.subtree_control dans le fichier cgroup parent.

cgroup.subtree_control

Ce fichier contient les contrôleurs du fichier cgroup.controllers qui sont activés pour l'enfant immédiat cgroups de cgroup courant.

Lorsqu'un contrôleur (par exemple, pids) est présent dans le fichier cgroup.subtree_control, les fichiers contrôleur-interface correspondants (par exemple, pids.max) sont automatiquement créés dans les enfants immédiats du cgroup courant.

Pour un exemple de procédure qui crée des groupes enfants où vous pouvez mettre en oeuvre la gestion des ressources pour une application, voir Définition de la pondération d'UC pour réguler la répartition du temps d'UC.

Pour supprimer un cgroup, assurez-vous que cgroup ne contient pas d'autres groupes enfants, puis supprimez le répertoire. Par exemple, pour supprimer le groupe enfant /sys/fs/cgroup/MyGroups/cgroup1, vous pouvez exécuter la commande suivante :

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

À propos des modèles de répartition des ressources

Les modèles de distribution suivants vous permettent de mettre en oeuvre le contrôle ou la réglementation dans la répartition des ressources à utiliser par cgroups v2 :

Pondérations

Dans ce modèle, les pondérations de tous les groupes de contrôle sont totalisées. Chaque groupe reçoit une fraction de la ressource en fonction du rapport du poids du groupe par rapport au poids total.

Considérez 10 groupes de contrôle, chacun avec un poids de 100 pour un total combiné de 1000. Dans ce cas, chaque groupe peut utiliser un dixième d'une ressource spécifiée.

La pondération est généralement utilisée pour répartir les ressources sans état. Pour appliquer cette ressource, l'option CPUWeight est utilisée.

Limites

Dans ce modèle, un groupe peut utiliser jusqu'à la quantité configurée d'une ressource. Si une ressource telle que l'utilisation de la mémoire pour un processus dépasse la limite, le noyau peut arrêter le processus avec un message " out-of-memory " (oom).

Vous pouvez également surengager des ressources afin que la somme des limites des sous-groupes puisse dépasser la limite du groupe parent. Le surengagement suppose que les ressources de tous les sous-groupes ne sont pas susceptibles d'atteindre toutes leurs limites en même temps.

Pour mettre en oeuvre ce modèle de distribution, l'option MemoryMax est souvent utilisée.

Protections

Dans ce modèle, une frontière protégée est affectée à un groupe. Si l'utilisation des ressources du groupe reste dans la quantité protégée, le noyau ne peut pas priver le groupe de l'utilisation de la ressource au profit d'autres groupes qui sont en concurrence pour la même ressource. Dans ce modèle, un surengagement de ressources est autorisé.

Pour mettre en oeuvre ce modèle, l'option MemoryLow est souvent utilisée.

Affectations

Dans ce modèle, un montant absolu spécifique est affecté à l'utilisation de ressources de type fini, telles que le budget en temps réel.

Gestion des cgroups v2 à l'aide de sysfs

Indique comment créer et régler des hiérarchies cgroups v2 directement dans /sys/fs/cgroup à des fins de dépannage ou de tests temporaires.

Important

Utilisez systemd pour gérer toutes les ressources dans la mesure du possible. Pour plus d'informations, voir Utilisation de Systemd pour gérer les groupes de contrôle.

Les exemples fournis ici fournissent le contexte des actions que systemd effectue sur un système et montrent la fonctionnalité en dehors de systemd. Les informations fournies peuvent être utiles lors du débogage des problèmes avec cgroups.

L'exemple de procédure consiste à allouer du temps CPU entre cgroups pour lesquels des PID d'application différents leur sont affectés. Les valeurs de temps UC et d'ID PID d'application sont définies dans les fichiers cpu.weight et cgroup.procs de chaque groupe.

L'exemple inclut également les étapes requises pour garantir que le contrôleur cpu et ses fichiers associés, y compris le fichier cpu.weight, sont disponibles dans cgroups que vous devez créer sous /sys/fs/cgroup.

Préparation du groupe de contrôle pour la répartition du temps UC

Cette procédure décrit comment préparer manuellement un groupe de contrôle pour gérer la répartition du temps CPU. Notez que l'approche recommandée pour configurer les groupes de contrôle consiste à utiliser systemd.

  1. Vérifiez que le contrôleur cpu est disponible en haut de la hiérarchie, dans le groupe de contrôle racine.

    Impression du contenu du fichier /sys/fs/cgroup/cgroup.controllers à l'écran :

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

    Vous pouvez ajouter tous les contrôleurs répertoriés dans le fichier cgroup.controllers au fichier cgroup.subtree_control dans le même répertoire pour les mettre à la disposition de l'enfant immédiat cgroups du groupe.

  2. Ajoutez le contrôleur cpu au fichier cgroup.subtree_control pour le rendre disponible à l'enfant immédiat cgroups de la racine.

    Par défaut, seuls les contrôleurs memory et pids se trouvent dans le fichier. Pour ajouter le contrôleur cpu, entrez :

    echo "+cpu" | sudo tee /sys/fs/cgroup/cgroup.subtree_control
    
  3. Facultativement, vérifiez que le contrôleur cpu a été ajouté comme prévu.
    sudo cat /sys/fs/cgroup/cgroup.subtree_control
    cpu memory pids
  4. Créez un groupe enfant sous le groupe de contrôle racine pour devenir le nouveau groupe de contrôle permettant de gérer les ressources d'UC dans les applications.
    sudo mkdir /sys/fs/cgroup/MyGroups
  5. Facultativement, répertoriez le contenu du nouveau sous-répertoire ou groupe enfant et vérifiez que le responsable cpu est présent comme prévu.
    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. Activez le contrôleur cpu dans le fichier cgroup.subtree_control du répertoire MyGroups pour le mettre à la disposition de son enfant immédiat cgroups.
    echo "+cpu" | sudo tee /sys/fs/cgroup/MyGroups/cgroup.subtree_control
  7. Facultativement, vérifiez que le contrôleur cpu est activé pour les groupes enfants sous MyGroups.
    sudo cat /sys/fs/cgroup/MyGroups/cgroup.subtree_control
    cpu

Définition du poids d'UC pour réguler la répartition du temps d'UC

Cette procédure décrit comment définir le poids CPU de trois processus différents à l'aide d'un groupe de contrôle pour gérer la répartition du temps CPU. Notez que l'approche recommandée pour configurer les groupes de contrôle consiste à utiliser systemd.

Cette procédure repose sur les hypothèses suivantes :

  • L'application qui consomme trop de ressources d'UC est sha1sum, comme indiqué dans l'exemple de sortie suivant de la commande 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                  
              ...
  • Les processus sha1sum ont des PID 33301, 33302 et 33303, comme indiqué dans l'exemple de sortie précédent.

Important

Comme préalable à la procédure suivante, vous devez effectuer les préparatifs de cgroup-v2, comme décrit dans Préparation du groupe de contrôle pour la répartition du temps d'UC. Si vous avez ignoré ces préparations, vous ne pouvez pas terminer cette procédure.

  1. Créez 3 groupes enfants dans le sous-répertoire MyGroups.
    sudo mkdir /sys/fs/cgroup/MyGroups/g1
    sudo mkdir /sys/fs/cgroup/MyGroups/g2
    sudo mkdir /sys/fs/cgroup/MyGroups/g3
  2. Configurez le poids de l'UC pour chaque groupe enfant.
    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. Appliquez les PID d'application à leurs groupes enfants correspondants.
    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

    Ces commandes définissent les applications sélectionnées pour qu'elles deviennent membres des groupes de contrôle MyGroups/g*/. Le temps UC de chaque processus sha1sum dépend de la répartition du temps UC configurée pour chaque groupe.

    Les pondérations des groupes g1, g2 et g3 qui ont des processus en cours d'exécution sont sommées au niveau de MyGroups, qui est le groupe de contrôle parent.

    Avec cette configuration, lorsque tous les processus s'exécutent en même temps, le noyau affecte à chacun des processus sha1sum le temps d'UC proportionnel en fonction du fichier cpu.weight de leur cgroup respectif, comme suit :

    Groupe enfant Paramètre cpu.weight Pourcentage d'affectation de temps UC
    g1 150 ~50% (150/300)
    g2 100 ~33 % (100/300)
    g3 50 ~16 % (50/300)

    Si un groupe enfant n'a pas de processus en cours d'exécution, l'allocation de temps CPU pour les processus en cours d'exécution est recalculée en fonction de la pondération totale des autres groupes enfants avec les processus en cours d'exécution. Par exemple, si le groupe enfant g2 n'a aucun processus en cours d'exécution, la pondération totale devient 200, soit la pondération de g1+g3. Dans ce cas, le temps UC pour g1 devient 150/200 (~75 %) et pour g3, 50/200 (~25 %)

  4. Vérifiez que les applications sont exécutées dans les groupes de contrôle spécifiés.
    sudo cat /proc/33301/cgroup /proc/33302/cgroup /proc/33303/cgroup
    0::/MyGroups/g1
    0::/MyGroups/g2
    0::/MyGroups/g3
  5. Vérifiez la consommation d'UC courante après avoir défini les pondérations d'UC.
    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
    ...