cgroups
Table des matières
Retour à l'index
NOM
cgroups – Groupes de contrôle de Linux
DESCRIPTION
Les groupes de contrôle, habituellement appelés cgroups, sont une
fonctionnalité du noyau Linux qui permet d'organiser les processus en
groupes hiérarchiques afin de limiter et de superviser leur utilisation de
types divers de ressource. L’interface cgroup du noyau est fournie à travers
un pseudo-système de fichiers appelé cgroupfs. Le regroupement est
implémenté dans le code central cgroup du noyau, tandis que le suivi et les
limites de ressources sont implémentés dans un ensemble de sous-systèmes de
type par ressource (mémoire, CPU, etc.).
Terminologie
Un cgroup est une collection de processus qui sont liés à un ensemble de
limites ou de paramètres définis à l’aide du système de fichiers cgroup.
Un sous-système est un composant du noyau qui modifie le comportement des
processus dans un cgroup. Divers sous-systèmes ont été implémentés, rendant
possible de faire des choses comme la limitation de temps CPU et de mémoire
disponibles pour un cgroup, la comptabilisation du temps CPU utilisé dans un
cgroup et le gel ou la reprise de l’exécution des processus dans un
cgroup. Les sous-systèmes sont parfois connus comme contrôleurs de ressource (ou simplement, contrôleurs).
Les cgroups pour un contrôleur sont agencés dans une hiérarchie. Celle-ci
est définie en créant, supprimant et renommant des sous-répertoires dans le
système de fichiers cgroup. À chaque niveau de la hiérarchie, des attributs
(par exemple, des limites) peuvent être définis. Les limites, le contrôle et
la comptabilisation fournis par les cgroups ont généralement des effets
partout dans la sous-hiérarchie du cgroup où les attributs sont définis. Par
conséquent, par exemple, les limites placées dans un cgroup d’un niveau
supérieur dans la hiérarchie ne peuvent être franchies par des cgroups
descendants.
Cgroups version 1 et version 2
La publication initiale de l’implémentation des cgroups a été faite dans
Linux 2.6.24. Au cours du temps, divers contrôleurs de cgroup ont été
ajoutés pour permettre la gestion de divers types de ressources. Cependant,
le développement de ces contrôleurs n’a pas été coordonné en grande partie
avec pour résultat l'apparition de nombreuses incohérences entre les
contrôleurs et une complexité accrue de la gestion des hiérarchies de
cgroup. Une description plus complète de ces problèmes peut être trouvée
dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v2.rst (ou
Documentation/cgroup-v2.txt dans Linux version 4.17 et précédentes).
À cause des problèmes avec l’implémentation initiale des cgroups (cgroups
version 1), des travaux ont commencé, à partir de Linux 3.10, sur une
nouvelle implémentation indépendante pour remédier à ces problèmes. Au
départ marquée comme expérimentale, et dissimulée derrière l’option de
montage -o __DEVEL__sane_behavior, la nouvelle version (cgroups
version 2) est devenue finalement officielle avec la publication de
Linux 4.5. Les différences entre les deux versions sont décrites dans le
texte qui suit. Le fichier cgroup.sane_behavior, présent dans cgroups
version 1, est un vestige de cette option de montage. Le fichier indique
toujours « 0 » et n’est conservé que pour la rétrocompatibilité.
Bien que cgroups version 2 soit destiné à remplacer la version 1, l’ancien
système continue à exister (et pour des raisons de compatibilité, ne sera
vraisemblablement pas supprimé). Actuellement, cgroups version 2 implémente
un sous-ensemble de contrôleurs disponibles dans cgroups version 1. Les deux
systèmes sont implémentés de façon que les contrôleurs version 1 et 2
puissent être montés sur le même système. Ainsi, par exemple, il est
possible d’utiliser les contrôleurs qui sont pris en charge par la
version 2, tout en utilisant aussi des contrôleurs version 1 là où la
version 2 ne les prend pas encore en charge. La seule restriction ici est
qu’un contrôleur ne peut pas être employé simultanément dans une hiérarchie
de cgroups version 1 et dans une hiérarchie de cgroups version 2.
CGROUPS VERSION 1
Sous cgroups version 1, chaque contrôleur peut être monté pour un système de
fichiers cgroup distinct qui fournit sa propre organisation hiérarchique des
processus dans le système. Il est aussi possible de co-monter plusieurs (et
même tous) les contrôleurs de cgroups version 1 pour le même système de
fichiers cgroup, ce qui signifie que les contrôleurs co-montés gèrent la
même organisation hiérarchique des processus.
Pour chaque hiérarchie montée, l’arbre de répertoires reflète la hiérarchie
de groupes de contrôle. Chaque groupe de contrôle est représenté par un
répertoire, avec chaque cgroup de contrôle enfant représenté par un
répertoire enfant. Par exemple, /user/joe/1.session représente le groupe
de contrôle 1.session, qui est un enfant du cgroup joe, qui est un
enfant de /user. Sous chaque répertoire cgroup existe un ensemble de
fichiers qui peuvent être lus ou écrits, reflétant les limites de ressources
et quelques propriétés générales du cgroup.
Tâches (threads) versus processus
Dans cgroups version 1, une distinction est faite entre les processus et
les tâches. De ce fait, un processus peut consister en plusieurs tâches
(plus couramment appelées threads, du point de vue espace utilisateur, et
appelées ainsi dans la suite de cette page de manuel). Dans cgroups
version 1, il est possible de manipuler indépendamment l’appartenance de
cgroup des threads d’un processus.
La capacité de cgroups version 1 de répartir les threads dans des cgroups
différents cause des problèmes dans certains cas. Par exemple, cela n’a
aucun sens pour le contrôleur de mémoire, puisque tous les threads d’un
processus partagent un même espace d’adressage. À cause de cela, la capacité
de manipuler indépendamment l’appartenance de cgroup des threads dans un
processus a été retirée dans l’implémentation initiale de cgroups version 2,
et ultérieurement restaurée dans une forme plus limitée (voir l’explication
sur le « mode threads » ci-après).
Montage de contrôleurs version 1
L’utilisation de cgroups requiert un noyau construit avec l’option
CONFIG_CGROUP. De plus, chaque contrôleur version 1 possède une option de
configuration associée qui doit être définie pour utiliser ce contrôleur.
Pour utiliser un contrôleur version 1, il doit être monté pour un système de
fichiers de cgroup. L’emplacement habituel de tels montages est sous le
système de fichiers tmpfs(5) monté dans /sys/fs/cgroup. Par
conséquent, un montage du contrôleur cpu peut être réalisé ainsi :
mount -t cgroup -o cpu none /sys/fs/cgroup/cpu
Il est possible de co-monter plusieurs contrôleurs pour la même
hiérarchie. Ici par exemple, les contrôleurs cpu et cpuacct sont
co-montés pour une même hiérarchie :
mount -t cgroup -o cpu,cpuacct none /sys/fs/cgroup/cpu,cpuacct
Le co-montage de contrôleurs fait qu’un processus est dans le même cgroup
pour tous les contrôleurs co-montés. Séparer le montage de contrôleurs
permet à un processus d’être dans le cgroup /toto1 pour un contrôleur
tout en étant dans /toto2/toto3 pour un autre.
Il est possible de co-monter tous les contrôleurs version 1 pour la même
hiérarchie :
mount -t cgroup -o all cgroup /sys/fs/cgroup
(Le même résultat peut être obtenu en omettant -o all, puisque c’est le
comportement par défaut si aucun contrôleur n’est explicitement précisé.)
Il n’est pas possible de monter le même contrôleur pour plusieurs
hiérarchies de cgroup. Par exemple, il n’est pas possible de monter à la
fois les contrôleurs cpu et cpuacct pour une même hiérarchie et de
monter le contrôleur cpu seul pour une autre hiérarchie. Il est possible
de créer plusieurs montages avec exactement le même ensemble de contrôleurs
co-montés. Dans ce cas cependant, tout cela aboutit à ce que plusieurs
points de montage fournissent une vue de la même hiérarchie.
Remarquez que sur de nombreux systèmes, les contrôleurs version 1 sont
automatiquement montés sous /sys/fs/cgroup. En particulier, systemd(1)
crée automatiquement de tels montages.
Démontage des contrôleurs version 1
Un système de fichiers cgroup monté peut être démonté en utilisant la
commande umount(8) comme dans l’exemple suivant :
umount /sys/fs/cgroup/pids
Bien remarquer qu’un système de fichiers de cgroup est démonté seulement
s’il n’est pas en cours d’utilisation, c’est-à-dire qu’il n’a pas de cgroups
enfants. Si ce n’est pas le cas, le seul effet de umount(8) est de rendre
le montage invisible. Par conséquent, pour être sûr que le montage est
réellement retiré, les cgroups enfants doivent d’abord être retirés, ce qui
à son tour ne peut être fait qu'après que tous les processus membres ont été
déplacés de ces cgroups vers le cgroup racine.
Contrôleurs de cgroups version 1
Chacun de ces contrôleurs de cgroups version 1 est régi par une option de
configuration du noyau (liste ci-après). De plus, la disponibilité de la
fonctionnalité des cgroups est régie par l’option de configuration
CONFIG_CGROUPS du noyau.
- cpu (depuis Linux 2.6.24 ; CONFIG_CGROUP_SCHED)
-
Un nombre minimal de « partages de CPU » peut être garanti quand un système
est actif. Cela ne limite pas l'utilisation de CPU par un cgroup si les CPU
ne sont pas actifs. Pour plus d’informations, consultez
Documentation/scheduler/sched-design-CFS.rst (ou
Documentation/scheduler/sched-design-CFS.txt dans Linux 5.2 et les
versions antérieures).
-
Dans Linux 3.2, ce contrôleur a été étendu pour fournir un contrôle de la
« bande passante » du CPU. Si le noyau est configuré avec
CONFIG_CFS_BANDWIDTH, il est possible de définir une limite haute du
temps CPU alloué aux processus d’un cgroup à chaque période de planification
(définie à l’aide d’un fichier dans le répertoire de cgroup). La limite
haute s’applique même s’il n’existe aucune compétition pour le CPU. Plus
d’informations sont disponibles dans le fichier des sources du noyau
Documentation/scheduler/sched-bwc.rst (ou
Documentation/scheduler/sched-bwc.txt dans Linux 5.2 et les versions
antérieures).
- cpuacct (depuis 2.6.24 ; CONFIG_CGROUP_CPUACCT)
-
Ce contrôleur fournit la comptabilisation de l’utilisation du CPU par des
groupes de processus.
-
Plus d’informations sont disponibles dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v1/cpuacct.rst (ou
Documentation/cgroup-v1/cpuacct.txt dans Linux 5.2 et les versions
antérieures).
- cpuset (depuis Linux 2.6.24 ; CONFIG_CPUSETS)
-
Ce cgroup peut être utilisé pour lier les processus dans un cgroup à un
ensemble spécifié de CPU ou de nœuds NUMA.
-
Plus d’informations sont disponibles dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v1/cpusets.rst (ou
Documentation/cgroup-v1/cpusets.txt dans Linux 5.2 et les versions
précédentes).
- memory (depuis Linux 2.6.25 ; CONFIG_MEMCG)
-
Le contrôleur de mémoire prend en charge le rapport et la limitation de la
mémoire du processus, de la mémoire du noyau et de la partition d’échange
utilisées par les cgroups.
-
Plus d’informations sont disponibles dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v1/memory.rst (ou
Documentation/cgroup-v1/memory.txt dans Linux 5.2 et les versions
antérieures).
- devices (depuis Linux 2.6.26 ; CONFIG_CGROUP_DEVICE)
-
Ce contrôleur prend en charge la définition des processus qui pourront créer
(mknod) des périphériques et les ouvrir en lecture ou écriture. Les
politiques peuvent être précisées dans des listes d’autorisations ou de
refus. La hiérarchie est imposée, aussi des règles nouvelles ne doivent pas
violer les règles existantes pour la cible ou pour des cgroups ancêtres.
-
Plus d’informations sont disponibles dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v1/devices.rst (ou
Documentation/cgroup-v1/devices.txt dans Linux 5.2 et les versions
antérieures).
- freezer (depuis Linux 2.6.28 ; CONFIG_CGROUP_FREEZER)
-
Le cgroup freezer peut suspendre ou restaurer (reprendre) tous les
processus d’un cgroup. Geler un cgroup /A fait que ses enfants, par
exemple les processus dans /A/B, sont gelés.
-
Plus d’informations sont disponibles dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v1/freezer-subsystem.rst (ou
Documentation/cgroup-v1/freezer-subsystem.txt dans Linux 5.2 et les
versions antérieures).
- net_cls (depuis Linux 2.6.29 ; CONFIG_CGROUP_NET_CLASSID)
-
Ce contrôleur place un identificateur de classe (classid), précisé pour le
cgroup, sur des paquets réseau créés par un cgroup. Ces identificateurs
peuvent être utilisés dans des règles de pare-feu, ainsi que pour canaliser
le trafic en utilisant tc(8). Cela s’applique aux paquets quittant le
cgroup, pas au trafic y arrivant.
-
Plus d’informations sont disponibles dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v1/net_cls.rst (ou
Documentation/cgroup-v1/net_cls.txt dans Linux 5.2 et les versions
antérieures).
- blkio (depuis Linux 2.6.33 ; CONFIG_BLK_CGROUP)
-
Le cgroup blkio contrôle et limite l’accès aux périphériques en mode bloc
indiqués en appliquant un contrôle d’E/S sous forme de restrictions et de
limites d’accès à l’encontre de nœuds feuilles et de nœuds intermédiaires
dans la hiérarchie de stockage.
-
Deux politiques sont possibles. La première est une division du disque
proportionnelle au poids basée sur la durée et implémentée avec CFQ
(Completely Fair Queuing — file d'attente complètement équitable). C’est le
cas pour les nœuds feuilles utilisant CFQ. La seconde est une politique
d’étranglement qui précise les limites supérieures de taux d’E/S sur un
périphérique.
-
Plus d’informations sont disponibles dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v1/blkio-controller.rst (ou
Documentation/cgroup-v1/blkio-controller.txt dans Linux 5.2 et les
versions antérieures).
- perf_event (depuis Linux 2.6.39 ; CONFIG_CGROUP_PERF)
-
Ce contrôleur permet à perf de superviser l’ensemble des processus
groupés dans un cgroup.
-
Plus d’informations sont disponibles dans le fichier des sources du noyau.
- net_prio (depuis Linux 3.3 ; CONFIG_CGROUP_NET_PRIO)
-
Ce contrôleur permet de définir des priorités par interface réseau pour les
cgroups.
-
Plus d’informations sont disponibles dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v1/net_prio.rst (ou
Documentation/cgroup-v1/net_prio.txt dans Linux 5.2 et les versions
antérieures).
- hugetlb (depuis Linux 3.5 ; CONFIG_CGROUP_HUGETLB)
-
Ce contrôleur prend en charge la limitation de l’utilisation de très grandes
pages par les cgroups.
-
Plus d’informations sont disponibles dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v1/hugetlb.rst (ou
Documentation/cgroup-v1/hugetlb.txt dans Linux 5.2 et les versions
antérieures).
- pids (depuis Linux 4.3 ; CONFIG_CGROUP_PIDS)
-
Ce contrôleur permet de limiter le nombre de processus pouvant être créés
dans un cgroup (et ses descendants).
-
Plus d’informations sont disponibles dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v1/pids.rst (ou
Documentation/cgroup-v1/pids.txt dans Linux 5.2 et les versions
antérieures).
- rdma (depuis Linux 4.11 ; CONFIG_CGROUP_RDMA)
-
Le contrôleur RDMA permet de limiter l’utilisation de ressources spécifiques
à RDMA/IB.
-
Plus d’informations sont disponibles dans le fichier des sources du noyau
Documentation/admin-guide/cgroup-v1/rdma.rst (ou
Documentation/cgroup-v1/rdma.txt dans Linux 5.2 et les versions
antérieures).
Création de cgroups et déplacement de processus
Un système de fichiers de cgroup contient initialement un seul cgroup
racine, « / », auquel tous les processus appartiennent. Un nouveau cgroup
est créé en créant un répertoire dans le système de fichiers de cgroup :
mkdir /sys/fs/cgroup/cpu/cg1
Cette commande crée un nouveau cgroup vide.
Un processus peut être transféré dans ce cgroup en écrivant son PID dans le
fichier cgroup.procs du cgroup :
echo $$ > /sys/fs/cgroup/cpu/cg1/cgroup.procs
Un seul PID à la fois peut être écrit dans ce fichier.
Écrire la valeur 0 dans un fichier cgroup.procs fait que le processus
écrivain est transféré dans le cgroup correspondant.
Quand un PID est écrit dans le fichier cgroup.procs, tous les threads du
processus sont transférés ensemble dans le nouveau cgroup.
Dans une hiérarchie, un processus peut être membre d'un et un seul
cgroup. Écrire un PID de processus dans un fichier cgroup.procs le retire
automatiquement du cgroup auquel il appartenait précédemment.
Le fichier cgroup.procs peut être lu pour obtenir une liste des processus
qui sont membres d’un cgroup. L'absence de doublons dans la liste renvoyée
des PID n’est pas garantie et cette dernière ne sera pas forcément
triée. Par exemple, un PID peut être recyclé pendant la lecture de la liste.
Dans cgroups version 1, un thread individuel peut être transféré dans un
autre cgroup en écrivant son ID de thread (c’est-à-dire l’ID de thread du
noyau renvoyé par clone(2) et gettid(2)) dans le fichier tasks d'un
répertoire de cgroup. Ce fichier peut être lu pour découvrir l’ensemble des
threads membres du cgroup.
Suppression de cgroups
Pour supprimer un cgroup, il doit tout d’abord n’avoir aucun cgroup enfant
et ne contenir aucun processus (non zombie). Tant que c’est le cas, on peut
simplement supprimer le nom de chemin de répertoire correspondant. Remarquez
que les fichiers dans le répertoire de cgroup ne peuvent et n’ont pas besoin
d’être supprimés.
Notification de publication de cgroups version 1
Deux fichiers peuvent être utilisés pour déterminer si le noyau fournit des
notifications quand un cgroup devient vide. Un cgroup est considéré comme
vide quand il ne contient ni cgroup enfant, ni processus membre.
Un fichier spécial dans le répertoire racine de chaque hiérarchie de cgroup,
release_agent, peut être utilisé pour enregistrer le nom de chemin d’un
programme pouvant être invoqué quand un cgroup dans la hiérarchie devient
vide. Le nom de chemin du cgroup nouvellement vide (relatif au point de
montage du cgroup) est fourni comme seul argument de ligne de commande quand
le programme release_agent est invoqué. Le programme release_agent
pourrait supprimer le répertoire du cgroup ou, peut être, le repeupler avec
un processus.
Par défaut, le fichier release_agent est vide, signifiant qu’aucun agent
de publication n’est invoqué.
Le contenu du fichier release_agent peut être spécifié à l’aide d’une
option de montage quand le système de fichiers de cgroup est monté :
mount -o release_agent=pathname ...
Que le programme release_agent soit invoqué ou pas quand un cgroup
particulier devient vide est déterminé par la valeur inscrite dans le
fichier notify_on_release dans le répertoire de cgroup correspondant. Si
ce fichier contient la valeur 0, alors le programme release_agent n’est
pas invoqué. Si cette valeur est 1, le programme release_agent est
invoqué. La valeur par défaut inscrite dans ce fichier dans le cgroup racine
est 0. Au moment de la création d’un nouveau cgroup, la valeur dans ce
fichier est héritée du fichier correspondant dans le cgroup parent.
Hiérarchies nommées de cgroups version 1
Dans cgroups version 1, il est possible de monter une hiérarchie de cgroup
qui n’a pas de contrôleurs attachés.
mount -t cgroup -o none,name=un_nom none /un/point/de/montage
Plusieurs instances de telles hiérarchies peuvent être montées, chaque
hiérarchie devant avoir un nom unique. Le seul but de telles hiérarchies est
de suivre les processus (consultez les explications de notification de
publication ci-dessous). La hiérarchie de cgroup name=systemd qui est
utilisée par systemd(1) pour suivre les services et les sessions
d’utilisateur en est un exemple.
Depuis Linux 5.0, l’option d’amorçage cgroup_no_v1 du noyau (décrite
ci-après) peut être utilisée pour désactiver les hiérarchies nommées de
cgroups version 1, en spécifiant cgroup_no_v1=named.
CGROUPS VERSION 2
Dans cgroups version 2, tous les contrôleurs montés résident dans une seule
hiérarchie unifiée. Alors que des contrôleurs (différents) peuvent être
montés simultanément dans des hiérarchies version 1 ou 2, il n’est pas
possible de monter le même contrôleur simultanément dans les deux
hiérarchies version 1 et version 2.
Les nouveaux comportements dans cgroups version 2 sont résumés ici et, dans
quelques cas, développés dans les sous-sections suivantes.
- -
-
Les cgroups version 2 fournissent une hiérarchie unifiée pour laquelle tous
les contrôleurs sont montés.
- -
-
Les processus « internes » ne sont pas autorisés. À l’exception du cgroup
racine, les processus ne peuvent résider que dans les nœuds feuilles (les
cgroups qui ne contiennent pas eux-mêmes de cgroups enfants). Les détails
sont un peu plus subtils que ça et sont décrits ci-après.
- -
-
Les cgroups actifs doivent être indiqués à l’aide des fichiers
cgroup.controllers et cgroup.subtree_control.
- -
-
Le fichier tasks et le fichier cgroup.clone_children qui est utilisé
par le contrôleur cpuset ont été supprimés.
- -
-
Un mécanisme amélioré pour la notification de cgroups vides est fourni par
le fichier cgroup.events.
Pour plus de détails sur les modifications, consultez le fichier
Documentation/admin-guide/cgroup-v2.rst dans les sources du noyau (ou
Documentation/cgroup-v2.txt dans Linux 4.17 et les versions antérieures).
Certains de ces nouveaux comportements intègrent une modification avec
l’ajout dans Linux 4.14 du « mode thread » (décrit ci-après).
Hiérarchie unifiée de cgroups version 2
Dans les cgroups version 1, la possibilité de monter différents contrôleurs
pour différentes hiérarchies était voulue pour permettre une grande
flexibilité dans la conception des applications. En pratique, la flexibilité
s’est avérée moins utile qu’espérée et, dans de nombreux de cas, a ajouté de
la complexité. Par conséquent, dans cgroups version 2, tous les contrôleurs
disponibles sont montés pour une seule hiérarchie. Les contrôleurs
disponibles sont automatiquement montés, ce qui signifie qu’il n’est pas
nécessaire (ou possible) d’indiquer les contrôleurs lors du montage d’un
système de fichiers cgroups version 2 en utilisant une commande telle que la
suivante :
mount -t cgroup2 none /mnt/cgroup2
Un contrôleur cgroups version 2 est disponible seulement s’il n’est pas en
cours d’utilisation à l’aide d’un montage pour une hiérarchie de cgroups
version 1. Ou, pour dire les choses autrement, il n’est pas possible
d’employer le même contrôleur pour les deux hiérarchies version 1 et
version 2 unifiée. Cela signifie qu’il peut être nécessaire d’abord de
démonter un contrôleur version 1 (comme décrit ci-dessus) avant que ce
contrôleur soit disponible en version 2. Puisque systemd(1) utilise
abondamment quelques contrôleurs version 1 par défaut, il peut dans certains
cas être plus simple d’amorcer le système avec ces contrôleurs version 1
désactivés. Pour ce faire, spécifier l’option cgroup_no_v1=list sur la
ligne de commande d’amorçage du noyau. list est une liste de noms séparés
par des virgules des contrôleurs à désactiver ou le mot all pour
désactiver tous les contrôleurs version 1. Cette situation est gérée
correctement par systemd(1), ce qui revient à un amorçage sans ces
contrôleurs.
Remarquez que sur de nombreux systèmes modernes, systemd(1) monte
automatiquement le système de fichiers cgroup2 dans
/sys/fs/cgroup/unified lors du processus d’amorçage.
Options de montage pour cgroups version 2
Les options suivantes (mount -o) peuvent être spécifiées lors du montage
de systèmes de fichiers de groupe version 2 :
- nsdelegate (depuis Linux 4.15)
-
Traitement des espaces de noms cgroup comme des limites de délégation. Pour
plus de détails, voir ci-dessous.
- memory_localevents (depuis Linux 5.2)
-
memory.events devrait afficher des statistiques seulement pour le cgroup
lui-même, pas pour les cgroups descendants. C’était le comportement avant
Linux 5.2. Depuis Linux 5.2, le comportement par défaut consiste à inclure
des statistiques pour les cgroups descendants dans memory.events et cette
option de montage peut être utilisée pour revenir au comportement
traditionnel. Cette option s’applique au système entier et peut être définie
au moment du montage ou modifiée à travers un remontage seulement à partir
de l’espace de noms montage initial. Elle est silencieusement ignorée dans
les espaces de noms non initiaux.
Contrôleurs de cgroups version 2
Les contrôleurs suivants, documentés dans le fichier source du noyau
Documentation/admin-guide/cgroup-v2.rst (ou
Documentation/cgroup-v2.txt dans Linux 4.17 et les versions antérieures)
sont pris en charge dans cgroups version 2 :
- cpu (depuis Linux 4.15)
-
C’est le successeur des contrôleurs version 1 cpu et cpuacct.
- cpuset (depuis Linux 5.0)
-
C’est le successeur du contrôleur version 1 cpuset.
- freezer (depuis Linux 5.2)
-
C’est le successeur du contrôleur version 1 freezer.
- hugetlb (depuis Linux 5.6)
-
C’est le successeur du contrôleur version 1 hugetlb.
- io (depuis Linux 4.5)
-
C’est le successeur du contrôleur version 1 blkio.
- memory (depuis Linux 4.5)
-
C’est le successeur du contrôleur version 1 memory.
- perf_event (depuis Linux 4.11)
-
Identique au contrôleur version 1 perf_event.
- pids (depuis Linux 4.5)
-
Identique au contrôleur version 1 pids.
- rdma (depuis Linux 4.11)
-
Identique au contrôleur version 1 rdma.
Il n’existe pas d’équivalent direct des contrôleurs net_cls et
net_prio de cgroups version 1. À la place, une prise en charge a été
ajoutée à iptables(8) pour permettre aux filtres eBPF qui s’attachent aux
noms de chemin de cgroups version 2 de prendre des décisions à partir du
trafic réseau selon le cgroup.
Les contrôleurs version 2 devices ne fournissent pas de fichiers
d’interface. À la place, le contrôle de périphérique est sécurisé en
attachant un programme eBPF (BPF_CGROUP_DEVICE) à un cgroup version 2.
Contrôle de sous-arbres de cgroups version 2
Chaque cgroup dans une hiérarchie version 2 contient les deux fichiers
suivants :
- cgroup.controllers
-
Ce fichier en lecture seule contient une liste des contrôleurs qui sont
disponibles dans ce cgroup. Le contenu de ce fichier correspond au
contenu du fichier cgroup.subtree_control dans le cgroup parent.
- cgroup.subtree_control
-
Ce fichier contient une liste de contrôleurs qui sont actifs (permis)
dans le cgroup. L’ensemble des contrôleurs dans ce fichier est un
sous-ensemble de l’ensemble cgroup.controllers de ce cgroup. L’ensemble
des contrôleurs actifs est modifié en écrivant des chaînes dans ce fichier
contenant des noms de contrôleurs séparés par des espaces, chacun étant
précédé par un « + » (pour autoriser le contrôleur) ou un « - » (pour
interdire le contrôleur), comme dans l’exemple suivant :
-
echo '+pids -memory' > x/y/cgroup.subtree_control
-
Un essai pour autoriser un contrôleur qui n’est pas présent dans
cgroup.controllers provoque une erreur ENOENT lors d’une écriture dans
le fichier cgroup.subtree_control.
Parce que la liste de contrôleurs dans cgroup.subtree_control est un
sous-ensemble de ces cgroup.controllers, un contrôleur qui n’est plus
autorisé dans un cgroup de la hiérarchie ne peut jamais être réautorisé dans
un sous-arbre de ce cgroup.
Un fichier cgroup.subtree_control de cgroup détermine l’ensemble des
contrôleurs qui sont activés dans les cgroups enfants. Quand un
contrôleur (par exemple, pids) est présent dans le fichier
cgroup.subtree_control d’un cgroup parent, les fichiers correspondants
interface-contrôleur (par exemple, pids.max) sont automatiquement créés
dans l’enfant de ce cgroup et peuvent être utilisés pour exercer le contrôle
des ressources dans les cgroups enfants.
Règle « pas de processus internes » pour cgroups version 2
Cgroups version 2 applique une règle appelée « pas de processus
internes ». En gros, cette règle veut dire que, à l’exception du cgroup
racine, les processus ne peuvent résider que dans les nœuds feuilles (des
cgroups ne contenant pas eux-mêmes de cgroup enfant). Cela évite d'avoir à
décider comment partager les ressources entre les processus qui sont membres
du cgroup A et les processus dans des cgroups enfants de A.
Par exemple, si le cgroup /cg1/cg2 existe, un processus peut résider dans
/cg1/cg2, mais pas dans /cg1. Cela permet d'éviter une ambiguïté dans
cgroups version 1 par rapport à la délégation de ressources entre les
processus dans /cg1 et les cgroups enfants. L’approche recommandée dans
cgroups version 2 consiste à créer un sous-répertoire appelé feuille pour
n’importe quel cgroup non feuille qui contiendrait des processus mais pas de
cgroup enfant. Ainsi, les processus qui auparavant seraient allés dans
/cg1 iraient maintenant dans /cg1/feuille. Cela a l’avantage de rendre
explicite la relation entre les processus dans /cg1/feuille et les autres
enfants de /cg1.
La règle « pas de processus internes » est en fait plus subtile que ce qui
est décrit ci-dessus. Plus précisément, la règle stipule qu’un cgroup (non
racine) ne peut pas à la fois avoir des processus membres et distribuer des
ressources aux cgroups enfants — c’est-à-dire avoir un fichier
cgroup.subtree_control non vide. Par conséquent, il est possible pour
un cgroup d’avoir à la fois des processus membres et des cgroups enfants,
mais pour que les contrôleurs puissent être autorisés pour ce cgroup, les
processus membres doivent être déplacés en dehors du cgroup (par exemple,
dans les cgroups enfants).
Avec l’addition dans Linux 4.14 du « mode thread » (décrit ci-après), la
règle « pas de processus internes » a été assouplie dans certains cas.
Fichier cgroup.events de cgroups version 2
Chaque cgroup non racine dans la hiérarchie version 2 contient un fichier en
lecture seule, cgroup.events, dont le contenu consiste en paires
clé-valeur (délimitées par des caractères de nouvelle ligne, avec les clés
et valeurs séparées par des espaces) fournissant des informations d’état sur
le cgroup :
$ cat mygrp/cgroup.events
populated 1
frozen 0
Les clés suivantes peuvent apparaître dans ce fichier :
- populated
-
La valeur de cette clé est soit 1 si ce cgroup ou n’importe lequel de ses
descendants a des processus membres, soit 0 dans le cas contraire.
- frozen (depuis Linux 5.2)
-
La valeur de cette clé est 1 si ce cgroup est actuellement gelé ou 0 s’il ne
l’est pas.
Le fichier cgroup.events peut être surveillé dans le but de recevoir des
notifications quand la valeur d’une des clés change. Cette surveillance peut
être réalisée en utilisant inotify(7), qui notifie les changements tels
que les évènements IN_MODIFY ou poll(2) qui notifie les changements en
renvoyant les bits POLLPRI et POLLERR dans le champ revents.
Notification de libération de cgroups version 2
Les cgroups version 2 fournissent un nouveau mécanisme pour recevoir des
notifications lorsqu’un cgroup devient vide. Les fichiers cgroups version 1
release_agent et notify_on_release sont supprimés et remplacés par la
clé populated dans le fichier cgroup.events. Cette clé a soit la
valeur 0, signifiant que le cgroup (et ses descendants) ne contient aucun
processus membre (non zombie), ou 1, signifiant que le cgroup (ou un de ses
descendants) contient des processus membres.
Le mécanisme de notification de libération de cgroups version 2 offre les
avantages suivants par rapport au mécanisme release_agent de cgroups
version 1 :
- -
-
IL permet une notification moins coûteuse puisqu’un seul processus peut
contrôler plusieurs fichiers cgroup.events (en utilisant les techniques
décrites précédemment). En revanche, le mécanisme de cgroups version 1
requiert la charge de créer un processus pour chaque notification.
- -
-
Les notifications pour des sous-hiérarchies différentes de cgroup peuvent
être déléguées à des processus différents. En revanche, le mécanisme de
cgroups version 1 permet seulement un agent de notification pour la
hiérarchie complète.
Fichier cgroup.stat de cgroups version 2
Chaque cgroup d’une hiérarchie version 2 contient un fichier cgroup.stat
en lecture seule (introduit en premier dans Linux 4.14) qui consiste en
lignes contenant des paires clé-valeur. Les clés suivantes apparaissent
actuellement dans ce fichier :
- nr_descendants
-
C’est le nombre total de cgroups descendants visibles (c’est-à-dire en
vivants) en dessous de ce cgroup.
- nr_dying_descendants
-
C’est le nombre de cgroups descendants mourants en dessous de ce cgroup. Un
cgroup devient mourant après avoir été supprimé. Il reste dans cet état pour
une période indéfinie (qui dépend de la charge du système) pendant que les
ressources sont libérées avant que le cgroup soit détruit. Remarquez que la
présence de quelques cgroups dans l’état mourant est normal et n’indique pas
un quelconque problème.
-
Un processus ne peut devenir membre d’un cgroup mourant et celui-ci ne peut
redevenir actif.
Limitation du nombre de cgroups descendants
Chaque cgroup dans une hiérarchie version 2 contient les fichiers suivants
qui peuvent être utilisés pour afficher et définir les limites du nombre de
cgroups descendants dans ce cgroup :
- cgroup.max.depth (depuis Linux 4.14)
-
Ce fichier définit une limite sur le niveau d’imbrication de cgroups
descendants. Une valeur de 0 dans ce fichier signifie qu’aucun cgroup
descendant ne peut être créé. Un essai de création dont le niveau
d’imbrication excède la limite échouera (mkdir(2) échoue avec l’erreur
EAGAIN).
-
Écrire la chaîne "max" dans ce fichier signifie qu’aucune limite
n’est imposée. La valeur par défaut dans ce fichier est "max".
- cgroup.max.descendants (depuis Linux 4.14)
-
Ce fichier définit une limite du nombre de cgroups descendants actifs que ce
cgroup peut posséder. Un essai de créer plus de descendants qu’autorisés par
la limite échoue (mkdir(2) échoue avec l’erreur EAGAIN).
-
Écrire la chaîne "max" dans ce fichier signifie qu’aucune limite
n’est imposée. La valeur par défaut dans ce fichier est "max".
DÉLÉGATION DE CGROUPS À UN UTILISATEUR AVEC DES PRIVILÈGES MOINDRES
Dans le contexte de cgroups, déléguer signifie transmettre la gestion d'un
sous-arbre de la hiérarchie de cgroup à un utilisateur non
privilégié. Cgroups version 1 fournit une prise en charge de la délégation
basée sur les permissions de fichier dans la hiérarchie de cgroup, mais avec
des règles de confinement moins strictes que dans la version 2 (comme
signalé ci-dessous). Cgroups version 2 gère la délégation avec confinement
selon un modèle explicite. L’explication dans cette section se concentre sur
la délégation dans cgroups version 2, avec quelques différences pour cgroups
version 1 signalées au fur et à mesure.
Un peu de terminologie est nécessaire pour expliquer la délégation. Un
délégant est un utilisateur privilégié (c’est-à-dire le superutilisateur)
qui possède un cgroup parent. Un délégué est un utilisateur non
privilégié à qui sont accordées les permissions nécessaires pour gérer une
sous-hiérarchie sous le cgroup parent, connue comme le sous-arbre délégué.
Pour réaliser la délégation, le délégant autorise l'écriture par le délégué
sur certains répertoires et fichiers, typiquement en transférant la
propriété des objets à l’ID utilisateur du délégué. En supposant une
délégation de hiérarchie de racine (par exemple) /dlgt_grp et qu’il n’y a
pas encore de cgroup enfant sous ce cgroup, la propriété de ce qui suit est
transférée à l’ID utilisateur du délégué :
- /dlgt_grp
-
Modifier le propriétaire de la racine d’un sous-arbre signifie que n’importe
quel cgroup nouvellement créé dans ce sous-arbre (et les fichiers qu’il
contient) sera aussi la propriété du délégué.
- /dlgt_grp/cgroup.procs
-
Modifier le propriétaire de ce fichier signifie que le délégué peut déplacer
les processus dans la racine du sous-arbre délégué.
- /dlgt_grp/cgroup.subtree_control (cgroups version 2 seulement)
-
Modifier le propriétaire de ce fichier signifie que le délégué peut activer
des contrôleurs (qui sont présents dans /dlgt_grp/cgroup.controllers)
dans le but d’une redistribution postérieure des ressources à des niveaux
inférieurs du sous-arbre. Comme alternative au changement de propriétaire de
ce fichier, le délégant pourrait à la place ajouter les contrôleurs
sélectionnés dans ce fichier.
- /dlgt_grp/cgroup.threads (cgroups version 2 seulement)
-
Modifier le propriétaire de ce fichier est nécessaire si un sous-arbre
threaded est sous le coup d’une délégation (consultez la description du
« mode thread » ci-dessous). Cela permet au délégué d’écrire des ID de
thread dans ce fichier. Le propriétaire de ce fichier peut être aussi changé
lors de la délégation d’un sous-arbre de domaine, mais actuellement cela ne
sert à rien puisque, comme décrit ci-dessous, il n’est pas possible de
déplacer un thread entre des cgroups de domaine en inscrivant son ID de
thread dans le fichier cgroup.threads.
-
Pour les cgroups version 1, le fichier correspondant qui doit être délégué
est le fichier tasks.
Le délégant ne doit pas changer le propriétaire de n’importe quel fichier
d’interface de contrôleur (par exemple, pids.max, memory.high) dans
dlgt_grp. Ces fichiers sont utilisés au niveau juste au-dessus du
sous-arbre délégué dans le but de distribuer les ressources dans le
sous-arbre, et le délégant ne doit pas avoir la permission de modifier les
ressources qui sont distribuées dans le sous-arbre délégué.
Consultez aussi l’explication dans le fichier /sys/kernel/cgroup/delegate
dans NOTES pour des informations sur les autres fichiers délégables dans
cgroups version 2.
Après que les étapes précitées aient été réalisées, le délégué peut créer
des cgroups enfants dans le sous-arbre délégué (les sous-répertoires et les
fichiers de cgroup qu’ils contiennent seront la propriété du délégué) et
déplacer des processus entre des cgroups dans le sous-arbre. Si quelques
contrôleurs sont présents dans dlgt_grp/cgroup.subtree_control, ou si la
propriété de ce fichier a été transférée au délégué, celui-ci peut aussi
contrôler une prochaine redistribution des ressources correspondantes dans
le sous-arbre délégué.
Délégation de cgroups version 2 : nsdelegate et espace de noms cgroup
Depuis Linux 4.13, une seconde manière existe pour réaliser une délégation
de cgroup dans une hiérarchie de cgroups version 2. Cela est fait en montant
ou remontant le système de fichiers de cgroups version 2 avec l’option de
montage nsdelegate. Par exemple, si un système de fichiers de cgroups
version 2 a déjà été monté, il est possible de le remonter avec l’option
nsdelegate comme suit :
mount -t cgroup2 -o remount,nsdelegate \
none /sys/fs/cgroup/unified
L’effet de cette option de montage est que l’espace de noms cgroup
deviennent automatiquement les limites de délégation. Plus particulièrement,
les restrictions suivantes s’appliquent pour les processus à l’intérieur de
l’espace de noms cgroup :
- -
-
Inscrire les fichiers des interfaces de contrôleur dans le répertoire racine
de l’espace de noms échouera avec l’erreur EPERM. Les processus à
l’intérieur de l’espace de noms cgroup peuvent toujours écrire dans les
fichiers délégables dans le répertoire racine de l’espace de noms cgroup
tels que cgroup.procs et cgroup.subtree_control, et peuvent créer des
sous-hiérarchies au-dessous du répertoire racine.
- -
-
Les essais de migrer des processus à travers des limites d’espace de noms
sont interdits (avec l’erreur ENOENT). Les processus à l’intérieur d’un
espace de noms cgroup peuvent toujours (soumis aux règles de confinement
décrites ci-après) déplacer des processus entre cgroups à l’intérieur de
la sous-hiérarchie sous l’espace de noms racine.
La possibilité de définir des espaces de noms cgroup comme des limites de
délégation rend les espaces de noms cgroup beaucoup plus utiles. Pour en
comprendre la raison, supposons qu’il existe déjà une hiérarchie de cgroup
qui a été déléguée à un utilisateur non privilégié, cecilia, en utilisant
la technique ancienne de délégation décrite ci-dessus. Supposons que plus
tard cecilia veuille déléguer une sous-hiérarchie sous la hiérarchie
déléguée existante (par exemple, la hiérarchie déléguée peut être associée
avec un conteneur non privilégié exécuté par cecilia). Même si un espace
de noms cgroup était employé, parce que les deux hiérarchies sont la
propriété de l’utilisateur cecilia non privilégié, les actions
illégitimes suivantes pourraient être réalisées :
- -
-
Un processus dans la hiérarchie inférieure pourrait modifier les réglages du
contrôleur de ressources dans le répertoire racine de cette hiérarchie (ces
réglages sont conçus pour permettre le contrôle à exercer à partir du cgroup
parent ; un processus dans le cgroup enfant ne devrait pas pouvoir les
modifier) ;
- -
-
un processus à l’intérieur de hiérarchie subalterne pourrait déplacer des
processus dans ou en dehors de la hiérarchie inférieure si les cgroups dans
la hiérarchie supérieure étaient de quelque façon visibles.
L’utilisation de l’option de montage nsdelegate empêche les deux
possibilités.
L’option de montage nsdelegate a seulement un effet lorsque elle est
utilisée dans l’espace de noms initial montage, dans d’autres espaces de
noms montage cette option est ignorée silencieusement.
Remarque : sur certains systèmes, systemd(1) monte automatiquement le
système de fichiers de cgroup version 2. Dans le but de tester l’opération
nsdelegate, il peut être utile d’amorcer le noyau avec les options de
ligne de commande suivantes :
cgroup_no_v1=all systemd.legacy_systemd_cgroup_controller
Ces options font que le noyau amorce avec les contrôleurs cgroups version 1
désactivés (signifiant que les contrôleurs sont disponibles dans une
hiérarchie version 2) et indique à systemd(1) de ne pas monter et
utiliser la hiérarchie de cgroup version 2, de façon que la hiérarchie
version 2 puisse être montée manuellement avec les options désirées après
l’amorçage.
Règles de confinement de délégation de cgroup
Certaines règles de confinement de délégation assurent que le délégué
peut déplacer des processus entre des cgroups à l’intérieur du sous-arbre
délégué, mais ne puisse pas déplacer les processus de l’extérieur du
sous-arbre délégué dans le sous-arbre ou vice versa. Un processus non
privilégié (c’est-à-dire le délégué) peut écrire le PID d’un processus
« cible » dans un fichier cgroup.procs seulement si toutes les conditions
suivantes sont remplies :
- -
-
l’écrivain a la permission d’écriture dans le fichier cgroup.procs du
cgroup de destination ;
- -
-
l’écrivain a la permission d’écrire dans le fichier cgroup.procs dans le
plus proche ancêtre commun des cgroups source et de destination. Remarquez
que dans certains cas, ce plus proche ancêtre commun peut être le cgroup
source ou celui de destination eux-mêmes. Ce besoin n’est pas imposé pour
les hiérarchies version 1, avec pour conséquence que le confinement dans la
version 1 est moins strict que dans la version 2 (par exemple, dans cgroups
version 1 l’utilisateur possédant deux sous-hiérarchies déléguées distinctes
peut déplacer un processus entre les hiérarchies) ;
- -
-
si le système de fichiers d’un cgroup version 2 a été monté avec l’option
nsdelegate, l’écrivain doit être capable de voir les cgroups source et
destination à partir de son espace de noms cgroup ;
- -
-
Dans cgroups version 1, l’UID effectif de l’écrivain (c’est-à-dire le
délégué) correspond à l’ID réel utilisateur ou au set-user-ID enregistré du
processus cible. Avant Linux 4.11, cette exigence s’appliquait aussi dans
cgroups version 2 (c’était une exigence historique héritée de cgroups
version 1 qui a été plus tard estimée non nécessaire, puisque les autres
règles suffisent pour le confinement dans cgroups version 2).
Remarque : une conséquence des ces règles de confinement de délégation
est que le délégué non privilégié ne peut placer le premier processus dans
le sous-arbre délégué. À la place, le délégant doit placer le premier
processus (un processus possédé par le délégué) dans le sous-arbre délégué.
MODE THREAD DE CGROUPS VERSION 2
Parmi les restrictions imposées par cgroups version 2 qui n’étaient pas
présentes dans cgroups version 1 :
- -
-
pas contrôle de granularité au niveau thread : tous les threads d’un
processus doivent être dans le même cgroup ;
- -
-
pas de processus internes : un cgroup ne peut à la fois avoir des
processus membres et mettre en œuvre des contrôleurs sur des cgroups
enfants.
Ces deux restrictions ont été ajoutées parce que l’absence de ces
restrictions a causé des problèmes dans cgroups version 1. En particulier,
la possibilité de cgroups version 1 de permettre une granularité au niveau
threads pour l’appartenance à un cgroup n’avait aucun sens pour certains
contrôleurs. Un exemple notable était le contrôleur memory : puisque les
threads partagent un espace d’adressage, cela n’avait aucun sens de répartir
les threads à travers des cgroups memory différents.
Malgré le fait de la décision initiale de conception de cgroups version 2,
des cas d’utilisation existaient pour certains contrôleurs, notablement le
contrôleur cpu, pour lesquels la granularité au niveau thread du contrôle
était justifiée et utile. Pour tenir compte de tels cas, Linux 4.14 a ajouté
le mode thread pour cgroups version 2.
Le mode thread permet les choses suivantes :
- -
-
la création de sous-arbres threaded dans lesquels les threads d’un
processus peuvent être répartis à travers des cgroups à l’intérieur de
l’arbre (un sous-arbre threaded peut contenir plusieurs processus
multithreads) ;
- -
-
le concept de contrôleurs threaded qui peuvent distribuer des ressources
à travers les cgroups dans un sous-arbre threaded ;
- -
-
un relâchement de la règle « pas de processus internes », de façon à ce que,
à l’intérieur d’un sous-arbre threaded, un cgroup puisse à la fois avoir des
processus membres et mettre en œuvre des contrôleurs de ressources de
cgroups enfants.
Avec l’ajout du mode thread, chaque cgroup non racine contient désormais un
nouveau fichier, cgroup.type, qui expose, et dans certaines circonstances
qui peut être utilisé pour modifier, le « type » d’un cgroup. Ce fichier
contient une des valeurs de type suivantes :
- domain
-
C’est un cgroup version 2 normal fournissant un contrôle de niveau de
granularité processus. Si un processus est membre de ce cgroup, alors tous
les threads de ce processus sont (par définition) dans le même cgroup. C’est
le type par défaut de cgroup et il fournit le même comportement qui était
fourni pour les cgroups dans l’implémentation initiale de cgroups version 2.
- threaded
-
Ce cgroup est un membre d’un sous-arbre threaded. Des threads peuvent être
ajoutés à ce cgroup et des contrôleurs peuvent être activés pour le cgroup.
- domain threaded
-
C’est un cgroup domain qui sert de racine à un sous-arbre threaded. Ce type
de cgroup est aussi connu comme « threaded root ».
- domain invalid
-
C’est un cgroup à l’intérieur d’un sous-arbre threaded qui est dans un état
« invalid ». Un processus ne peut être ajouté au cgroup et un contrôleur ne
peut être activé pour le cgroup. La seule chose qui puisse être faite avec
ce cgroup (à part le supprimer) est de le convertir en cgroup threaded en
inscrivant la chaine « threaded » dans le fichier cgroup.type.
-
La raison de l’existence de ce type « transitoire » lors de la création d’un
sous-arbre threaded (plutôt que le noyau ne convertisse simplement
immédiatement tous les cgroups sous la racine threaded au type threaded)
est de permettre des extensions futures au modèle de mode thread.
Threaded versus contrôleurs de domaine
Avec l’ajout du mode threads, cgroups version 2 distingue désormais deux
types de contrôleurs de ressource :
- -
-
contrôleurs Threaded : ces contrôleurs gèrent la granularité au niveau
thread pour le contrôle des ressources et peuvent être activés à l’intérieur
de sous-arbres threaded avec pour résultat que les fichiers de l’interface
de contrôleur correspondants apparaissent dans les cgroups du sous-arbre
threaded. Depuis Linux 4.19, les contrôleurs suivants sont threaded :
cpu, perf_event, et pids ;
- -
-
contrôleurs Domain : ces contrôleurs gèrent seulement une granularité au
niveau processus pour le contrôle de ressource. Du point de vue contrôleur
de domaine, tous les threads d’un processus sont toujours dans le même
cgroup. Les contrôleurs de domaine ne peuvent être activés à l’intérieur
d’un sous-arbre threaded.
Création d’un sous-arbre threaded
Il existe deux manières qui conduisent à la création de sous-arbre
threaded. La première manière fonctionne comme ceci :
- (1)
-
Nous écrivons La chaine « threaded » dans le fichier cgroup.type d’un
cgroup y/z ayant actuellement le type domain. Cela a les effets
suivants :
-
- -
-
le type du cgroup y/z devient threaded ;
- -
-
le type du cgroup parent, y, devient domain threaded. Le cgroup parent
est la racine d’un sous-arbre threaded (aussi connu comme « threaded root »
– racine threaded) ;
- -
-
Tous les autres cgroups sous y qui n’étaient pas déjà de type threaded
(parce qu’ils étaient déjà dans des sous-arbres threaded existants sous la
nouvelle racine root threaded) sont convertis au type domain invalid. Tout cgroup créé après sous y aura aussi le type domain invalid.
- (2)
-
Nous écrivons La chaine « threaded » pour chacun des cgroups domain invalid sous y, dans le but de les convertir au type threaded. Comme
conséquence de cette étape, tous les threads sous la racine threaded ont
désormais le type threaded et le sous-arbre threaded est désormais
pleinement utilisable. Les conditions nécessaires pour écrire
« threaded » pour chacun de ces cgroups sont quelque peu laborieuses,
mais permettent de futures extensions au modèle de mode thread.
La second manière de créer un sous-arbre threaded est la suivante :
- (1)
-
Dans un cgroup existant, z, qui actuellement a le type domain, nous
(1.1) activons un ou plusieurs contrôleurs threaded et (1.2) faisons d’un
processus un membre de z (ces deux étapes pouvant être réalisées dans
n’importe quel ordre). Cela a les conséquences suivantes :
-
- -
-
le type de z devient domain threaded ;
- -
-
tous les cgroups descendants de z qui n’étaient déjà de type threaded
sont convertis au type domain invalid.
- (2)
-
Comme auparavant, nous rendons le sous-arbre threaded utilisable en écrivant
la chaine « threaded » pour chacun des cgroups domain invalid
sous z, dans le but de les convertir au type threaded.
Une des conséquences des manières ci-dessus de créer un sous-arbre threaded
est qu’un cgroup de racine threaded peut être un parent pour seulement des
cgroups threaded (et domain invalid). Le cgroup racine threaded ne
peut pas être un parent d’un cgroup domain et un cgroup threaded ne
peut avoir de frère qui soit un cgroup domain.
Utilisation de sous-arbre threaded
À l’intérieur d’un sous-arbre threaded, des contrôleurs threaded peuvent
être activés dans chaque sous-groupe dont le type a été changé à
threaded. Ce faisant, les fichiers de l’interface de contrôleur
correspondants apparaissent dans l’enfant de ce cgroup.
Un processus peut être déplacé dans un sous-arbre threaded en écrivant son
PID dans le fichier cgroup.procs dans un des cgroups de l’arbre. Cela a
pour effet de rendre tous les threads du processus membres du cgroup
correspondant et de faire du processus un membre du sous-arbre threaded. Les
threads du processus peuvent être répartis à travers le sous-arbre threaded
en écrivant leurs ID de thread (voir gettid(2)) dans les fichiers
cgroup.threads dans différents cgroups à l’intérieur du sous-arbre. Les
threads d’un processus doivent tous résider dans le même sous-arbre
threaded.
Comme pour l’écriture dans cgroup.procs, quelques règles de confinement
s’appliquent pour l’écriture dans le fichier cgroup.threads :
- -
-
l’écrivain doit avoir la permission d’écriture dans le fichier
cgroup.threads dans le cgroup de destination ;
- -
-
l’écrivain doit avoir la permission d’écriture dans le fichier
cgroup.procs dans l’ancêtre commun des cgroups source et destination
(dans certains cas, cet ancêtre peut être le cgroup source ou destination
eux-mêmes) ;
- -
-
les cgroups source et destination doivent être dans le même sous-arbre
threaded (en dehors d’un sous-arbre threaded, un essai de déplacer un thread
en écrivant son ID de thread dans le fichier cgroup.threads dans un
cgroup domain différent échoue avec l’erreur EOPNOTSUPP).
Le fichier cgroup.threads est présent dans chaque cgroup (incluant les
cgroups domain) et peut être lu pour découvrir l’ensemble de threads
présents dans le cgroup. L’ensemble d’ID de threads obtenu lors de la
lecture de ce fichier n’est pas garanti d’être ordonné ou ne pas avoir de
doublons.
Le fichier cgroup.procs dans la racine threaded affiche le PID de tous
les processus membres du sous-arbre threaded. Les fichiers cgroup.procs
dans les autres cgroups du sous-arbre ne sont pas lisibles.
Les contrôleurs de domaine ne peuvent être activés dans un sous-arbre
threaded. Aucun fichier d’interface de contrôleur n’apparait dans les
cgroups sous la racine threaded. Du point de vue du contrôleur de domaine,
les sous-arbres threaded sont invisibles : un processus multithreaded à
l’intérieur d’un sous-arbre threaded apparait pour un contrôleur de domaine
comme un processus qui réside dans le cgroup racine threaded.
Dans un sous-arbre threaded, la règle « pas de processus internes » ne
s’applique pas : un cgroup peut contenir des processus membres (ou des
threads) et utiliser des contrôleurs sur des cgroups enfants.
Règles pour écrire dans cgroup.type et créer des sous-arbres threaded
Un certain nombre de règles s’appliquent lors de l’écriture dans le fichier
cgroup.type :
- -
-
seule la chaine « threaded » peut être écrite. En d’autres mots, la seule
transition explicite possible est de convertir un cgroup domain au type
threaded ;
- -
-
l’effet d’écrire « threaded » dépend de la valeur en cours dans
cgroup.type, comme suit :
-
- -
-
domain ou domain threaded : début de la création d’un sous-arbre
threaded (dont la racine est le parent de ce cgroup) à l’aide de la première
des manières décrites ci-dessus,
- -
-
domain invalid : conversion de ce cgroup (qui est à l’intérieur d’un
sous-arbre threaded) pour être dans un état utilisable (c’est-à-dire
threaded),
- -
-
threaded : aucun effet (une « no-op ») ;
- -
-
il n’est pas possible d’écrire dans un fichier cgroup.type si le type du
parent est domain invalid. En d’autres mots, les cgroups d’un sous-arbre
threaded doivent être convertis dans l’état threaded d’une manière
descendante.
Quelques contraintes doivent aussi être satisfaites pour créer un sous-arbre
threaded dont la racine est le cgroup x :
- -
-
il ne peut exister de processus membres dans les cgroups descendants de x
(le cgroup_x peut lui avoir des processus membres) ;
- -
-
aucun contrôleur de domaine ne peut être activé dans le fichier
cgroup.subtree_control de x.
Si n’importe laquelle des contraintes ci-dessus n’est pas satisfaite, alors
un essai d’écrire « threaded » dans un fichier cgroup.type échouera
avec l’erreur ENOTSUP.
Le type « domain threaded » de cgroup
Selon les chemins décrits ci-dessus, le type d’un cgroup peut changer à
domain threaded dans chacun des cas suivants :
- -
-
la chaine « threaded » est écrite pour un cgroup enfant ;
- -
-
un contrôleur threaded est activé dans le cgroup et un processus est fait
membre du cgroup.
Un cgroup domain threaded, x, peut redevenir du type domain si les
conditions ci-dessus ne sont plus vraies, c’est-à-dire si tous les cgroups
enfants threaded de x ont été supprimés et si x n’a plus de
contrôleurs threaded activés ou n’a plus de processus membres.
Quand un cgroup domain threaded x redevient du type domain :
- -
-
tous les descendants domain invalid de x qui ne sont pas dans des
sous-arbres threaded de bas niveau redeviennent du type domain ;
- -
-
les cgroups racines dans n’importe quels sous-arbres threaded de bas niveau
redeviennent de type domain threaded.
Exceptions pour le cgroup racine
Le cgroup racine de la hiérarchie version 2 est traité exceptionnellement :
il peut être le parent à la fois de cgroups domain et threaded. Si la
chaine « threaded » est écrite dans le fichier cgroup.type d’un des
enfants du cgroup racine, alors :
- -
-
le type de ce cgroup devient threaded ;
- -
-
le type de tous les descendants de ce cgroup qui ne fait pas partie de
sous-arbres threaded de bas niveau change à domain invalid.
Remarquez que dans ce cas, il n’y a pas de cgroup qui deviennent domain threaded (théoriquement, le cgroup racine peut être considéré comme la
racine threaded pour le cgroup dont le type a été changé à threaded).
Le but de ce traitement exceptionnel pour le cgroup racine est de permettre
à un cgroup threaded qui emploie le contrôleur cpu d’être placé aussi
haut que possible dans la hiérarchie, de façon à minimiser le (faible) coût
de parcourir la hiérarchie de cgroup.
Le contrôleur « cpu » de cgroups version 2 et les threads en temps réel
Depuis Linux 4.19, le contrôleur cpu de cgroups version 2 ne prend pas en
charge le contrôle des threads en temps réel (particulièrement les threads
ordonnancés sous les politiques SCHED_FIFO, SCHED_RR,
SCHED_DEADLINE ; voir sched(7)). Par conséquent, le contrôleur cpu
ne peut être activé dans le cgroup racine seulement si tous les threads en
temps réel sont dans le cgroup racine (si des threads en temps réel sont
dans des cgroups non racines, alors une écriture write(2) de la chaine
« +cpu » dans le fichier cgroup.subtree_control échoue avec l’erreur
EINVAL).
Dans certains systèmes, systemd(1) place certains threads en temps réel
dans des cgroups non racines dans la hiérarchie version 2. Pour de tels
systèmes, ces threads doivent d’abord être déplacés dans le cgroup racine
avant que le contrôleur cpu ne soit activé.
ERREURS
Les erreurs suivantes peuvent survenir pour mount(2) :
- EBUSY
-
Un essai de monter un système de fichiers cgroup version 1 n’indiquait ni
l’option name= (pour monter une hiérarchie nommée) ni un nom de
contrôleur (ou all).
NOTES
Un processus enfant créé à l’aide de fork(2) hérite des appartenances de
cgroup de son parent. Les appartenances de cgroup de processus sont
préservées à travers execve(2).
Le drapeau CLONE_INTO_CGROUP de clone3(2) peut être utilisé pour créer
un processus enfant qui débute son existence dans un cgroup version 2
différent du processus parent.
Fichiers /proc
- /proc/cgroups (depuis Linux 2.6.24)
-
Ce fichier contient des informations sur les contrôleurs qui sont compilés
dans le noyau. Un exemple du contenu de ce fichier (reformaté pour une
meilleure lisibilité) est ce qui suit :
-
#subsys_name hierarchy num_cgroups enabled
cpuset 4 1 1
cpu 8 1 1
cpuacct 8 1 1
blkio 6 1 1
memory 3 1 1
devices 10 84 1
freezer 7 1 1
net_cls 9 1 1
perf_event 5 1 1
net_prio 9 1 1
hugetlb 0 1 0
pids 2 1 1
-
Les champs dans ce fichier sont de gauche à droite :
-
- [1]
-
Le nom du contrôleur.
- [2]
-
L’ID unique de la hiérarchie de cgroup pour laquelle le contrôleur est
monté. Si plusieurs contrôleurs de cgroups version 1 sont liés à la même
hiérarchie, chacun d'entre eux affichera le même ID de hiérarchie dans ce
champ. La valeur dans ce champ sera zéro si :
-
- -
-
le contrôleur n’est pas monté pour une hiérarchie de cgroups version 1 ;
- -
-
le contrôleur est lié à la seule hiérarchie unifiée de cgroups version 2 ;
- -
-
le contrôleur est désactivé (voir ci-dessous).
- [3]
-
Le nombre de groupes de contrôle dans cette hiérarchie utilisant ce
contrôleur.
- [4]
-
Ce champ contient la valeur 1 si le contrôleur est activé ou zéro s’il a été
désactivé (à l’aide du paramètre cgroup_disable d’amorçage du noyau dans
la ligne de commande).
- /proc/pid/cgroup (depuis Linux 2.6.24)
-
Ce fichier décrit les groupes de contrôle auxquels le processus ayant le PID
correspondant appartient. L’information affichée diffère pour les
hiérarchies version 1 et version 2 de cgroups.
-
Pour chaque hiérarchie de cgroup dont le processus est membre, il existe une
entrée contenant trois champs séparés par des deux-points :
-
ID_hiérarchie:liste_contrôleurs:chemin_cgroup
-
Par exemple :
-
5:cpuacct,cpu,cpuset:/daemons
-
De gauche à droite, ces trois champs séparés par des deux-points sont :
-
- [1]
-
Pour les hiérarchies de cgroups version 1, ce champ contient un numéro d’ID
unique de hiérarchie qui peut être comparé avec un ID de hiérarchie dans
/proc/cgroups. Pour les hiérarchies de cgroups version 2, ce champ
contient la valeur 0.
- [2]
-
Pour les hiérarchies de cgroups version 1, ce champ contient une liste
séparée par des virgules de contrôleurs liés à la hiérarchie. Pour les
hiérarchies de cgroups version 2, ce champ est vide.
- [3]
-
Ce champ contient le chemin du groupe de contrôle dans la hiérarchie à
laquelle le processus appartient. Ce chemin est relatif au point de montage
de la hiérarchie.
Fichiers /sys/kernel/cgroup
- /sys/kernel/cgroup/delegate (depuis Linux 4.15)
-
Ce fichier exporte une liste de fichiers cgroups version 2 (un par ligne)
qui sont délégables (c’est-à-dire dont la propriété peut être changée à l’ID
utilisateur du délégué). Dans le futur, l’ensemble des fichiers délégables
peut être modifié ou grossir, et ce fichier fournit un moyen pour le noyau
d’informer les applications en espace utilisateur quels fichiers doivent
être délégués. Depuis Linux 4.15, il est possible de voir ce qui suit lors
de l’inspection de ce fichier :
-
$ cat /sys/kernel/cgroup/delegate
cgroup.procs
cgroup.subtree_control
cgroup.threads
- /sys/kernel/cgroup/features (depuis Linux 4.15)
-
Avec le temps, l’ensemble de fonctionnalités de cgroups version 2 fournies
par le noyau peut évoluer ou grossir, ou certaines fonctionnalités
pourraient ne pas être activées par défaut. Ce fichier fournit un moyen aux
applications en espace utilisateur de découvrir quelles fonctionnalités le
noyau utilisé gère et a d’activées. Les fonctionnalités sont listées, une
par ligne :
-
$ cat /sys/kernel/cgroup/features
nsdelegate
memory_localevents
-
Les entrées pouvant apparaitre dans ce fichier sont :
-
- memory_localevents (depuis Linux 5.2)
-
Le noyau gère l’option de montage memory_localevents.
- nsdelegate (depuis Linux 4.15)
-
Le noyau gère l’option de montage nsdelegate.
- memory_recursiveprot (depuis Linux 5.7)
-
Le noyau gère l’option de montage memory_recursiveprot.
VOIR AUSSI
prlimit(1), systemd(1), systemd-cgls(1), systemd-cgtop(1),
clone(2), ioprio_set(2), perf_event_open(2), setrlimit(2),
cgroup_namespaces(7), cpuset(7), namespaces(7), sched(7),
user_namespaces(7)
Le fichier des sources du noyau Documentation/admin-guide/cgroup-v2.rst.
TRADUCTION
La traduction française de cette page de manuel a été créée par
Christophe Blaess <https://www.blaess.fr/christophe/>,
Stéphan Rafin <stephan.rafin@laposte.net>,
Thierry Vignaud <tvignaud@mandriva.com>,
François Micaux,
Alain Portal <aportal@univ-montp2.fr>,
Jean-Philippe Guérard <fevrier@tigreraye.org>,
Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>,
Julien Cristau <jcristau@debian.org>,
Thomas Huriaux <thomas.huriaux@gmail.com>,
Nicolas François <nicolas.francois@centraliens.net>,
Florentin Duneau <fduneau@gmail.com>,
Simon Paillard <simon.paillard@resel.enst-bretagne.fr>,
Denis Barbier <barbier@debian.org>,
David Prévot <david@tilapin.org>
et
Jean-Paul Guillonneau <guillonneau.jeanpaul@free.fr>
Cette traduction est une documentation libre ; veuillez vous reporter à la
GNU General Public License version 3
concernant les conditions de copie et
de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel,
veuillez envoyer un message à
Index
- NOM
-
- DESCRIPTION
-
- Terminologie
-
- Cgroups version 1 et version 2
-
- CGROUPS VERSION 1
-
- Tâches (threads) versus processus
-
- Montage de contrôleurs version 1
-
- Démontage des contrôleurs version 1
-
- Contrôleurs de cgroups version 1
-
- Création de cgroups et déplacement de processus
-
- Suppression de cgroups
-
- Notification de publication de cgroups version 1
-
- Hiérarchies nommées de cgroups version 1
-
- CGROUPS VERSION 2
-
- Hiérarchie unifiée de cgroups version 2
-
- Options de montage pour cgroups version 2
-
- Contrôleurs de cgroups version 2
-
- Contrôle de sous-arbres de cgroups version 2
-
- Règle « pas de processus internes » pour cgroups version 2
-
- Fichier cgroup.events de cgroups version 2
-
- Notification de libération de cgroups version 2
-
- Fichier cgroup.stat de cgroups version 2
-
- Limitation du nombre de cgroups descendants
-
- DÉLÉGATION DE CGROUPS À UN UTILISATEUR AVEC DES PRIVILÈGES MOINDRES
-
- Délégation de cgroups version 2 : nsdelegate et espace de noms cgroup
-
- Règles de confinement de délégation de cgroup
-
- MODE THREAD DE CGROUPS VERSION 2
-
- Threaded versus contrôleurs de domaine
-
- Création d’un sous-arbre threaded
-
- Utilisation de sous-arbre threaded
-
- Règles pour écrire dans cgroup.type et créer des sous-arbres threaded
-
- Le type « domain threaded » de cgroup
-
- Exceptions pour le cgroup racine
-
- Le contrôleur « cpu » de cgroups version 2 et les threads en temps réel
-
- ERREURS
-
- NOTES
-
- Fichiers /proc
-
- Fichiers /sys/kernel/cgroup
-
- VOIR AUSSI
-
- TRADUCTION
-
This document was created by
man2html,
using the manual pages.
Time: 05:06:36 GMT, September 19, 2025