Cgroup2
EN CHANTIER
Article en cours d'écriture et/ou de test. Certains éléments peuvent être incomplets et mener à un résultat non fonctionnel.Merci de ne pas rager.
Cgroups (control groups) est une fonctionnalité du noyau Linux pour limiter, compter et isoler l'utilisation des ressources (processeur, mémoire, utilisation disque, RDMA, etc...).
Il est issus d'un travail initié par des ingénieurs de Google en 2006 et intégré à la version 2.6.24 du noyau. La version 1 étant dépréciée (mais encore présente dans la branche principale de Linux), seule son évolution, Cgroups2, sera traité.
Le principe général de cette technologie présentée comme un pseudo système de fichiers monté par défaut dans /sys/fs/cgroup/
est, de façon arbitraire, de créer des groupes de processus qui se verront tous appliquer des limitations communes. Il est ainsi possible de mitiger les risques de dénis de services occasionnés par un programme un peu trop gourmand en ressources. Son usage est de fait très plébiscité dans les environnements conteneurisés.
Limitation des ressources
Cgroups2 permet de limiter les ressources systèmes suivantes :
- cpu (depuis Linux 4.15) : limitation de l'usage processeur
- cpuset (depuis Linux 5.0) : permet de faire fonctionner les processus sur des nœuds NUMA et des processeurs spécifiques (plateformes matérielles multi socket)
- freezer (depuis Linux 5.2) : permet de geler et de reprendre les processus du groupe
- hugetlb (depuis Linux 5.6) : limite l'utilisation des grandes pages mémoires (huge pages)
- io (depuis Linux 4.5) : limite l'utilisation des entrées/sorties sur les périphériques de type bloc spécifiés dans le groupe
- memory (depuis Linux 4.5) : limite l'utilisation de la mémoire (RAM) des processus ; du noyau et de la SWAP
- perf_event (depuis Linux 4.11) : permet la supervision des performances (perf) des processus du groupe
- pids (depuis Linux 4.5) : limite le nombre de processus (PID) pouvant être créés dans le groupe
- rdma (depuis Linux 4.11) : permet de limiter l'usage du RDMA et de l'Infiniband dans le groupe
Leur portage depuis la version 1 est progressif. Les nouvelles versions du noyau sont donc susceptibles d'en supporter d'avantage.
Tous les processus nouvellement créés s'ajoutent dans le groupe racine (cgroup par défaut) via la liste /sys/fs/cgroup/cgroup.procs
qui ne comporte aucune limitation.
Pour limiter un ou plusieurs processus, il faut alors créer un groupe dédié aux limitations que nous voulons leur appliquer.
INFORMATION
Il est à noter qu'un PID ne peut appartenir qu'à un seul cgroup à la fois. Cette notion est importante pour la suite.Un groupe se créé par l'ajout d'un répertoire dans la racine du point de montage :
mkdir /sys/fs/cgroup/toto
Dès la création, son contenu est automatiquement peuplé des fichiers de configuration du groupe. Pour appliquer une limitation à ce dernier, il suffit donc d'inscrire une valeur dans le fichier correspondant à celle-ci.
Pour l'annuler, il suffit de supprimer son répertoire
rmdir /sys/fs/cgroup/toto/
Note : La suppression d'un cgroup n'est possible que si aucun processus ne lui est affecté.
Limitation CPU
Attribution manuelle
Pour limiter l'usage du processeur à 50% d'un cœur, il est possible d'inscrire des limites de temps (en microsecondes) dans le fichier cpu.max
:
echo "50000 100000" > /sys/fs/cgroup/toto/cpu.max
Description :
- 50000 : limite de temps CPU en microsecondes que le cgroup peut utiliser dans une période donnée. Dans cet exemple, cela signifie que le groupe
toto
peut utiliser jusqu'à 50 000 microsecondes (soit 50 millisecondes) de temps processeur - 100000 : période de temps en microsecondes sur laquelle la limite est appliquée. Dans cet exemple, cela signifie que la période est de 100 000 microsecondes (soit 100 millisecondes).
Donc le cgroup peut utiliser jusqu'à 50 millisecondes de temps CPU dans une période de 100 millisecondes. S'il dépasse cette limite, il sera restreint dans son utilisation du processeur jusqu'à la fin de la période. 100% équivaut à la charge d'un cœur, une valeur supérieure en concernera donc plusieurs.
INFORMATION
Pour rappel, la limite est globale au groupe. Tous les PID en faisant parti consommeront donc au maximum un total de 50% du CPU sur un seul cœur.Le programme utilisé pour tester notre bridage sera stress
, un outil de charge processeur disponible dans les dépôts Debian. Nous allons l'utiliser pour charger un cœur à 100% :
stress -c 1
Pour rappel, tout nouveau processus appartient par défaut (nous verrons plus loin commun influencer ce critère) au cgroup racine, il faut donc récupérer son PID afin de l'ajouter dans la liste de processus /sys/fs/cgroup/toto/cgroup.procs
# Récupération du PID (ici 1355)
ps -aux | grep stress
# Ajout du processus au cgroup toto
echo "1355" > /sys/fs/cgroup/toto/cgroup.procs
Note : L'usage du cœur sollicité a été réduit instantanément de moitié.
Pour retirer le processus du cgroup, il convient de le replacer dans la racine
echo "1355" > /sys/fs/cgroup/cgroup.procs
Note : Le cœur est reparti à 100%.
Attribution à l'exécution
La méthode exposée déroule un procédé manuel et asynchrone : le processus est d'abord créé dans le cgroup racine pour être déplacé après coup dans un groupe spécifique. Bien que cela puisse s'avérer utile pour limiter un programme déjà en cours d'exécution, il n'est pas envisageable de réaliser ces opérations manuellement à chaque lancement (d'autant plus que le PID change à chaque occurrence).
La commande cgexec
du paquet cgroup-tools
permet d'effectuer ces opérations automatiquement au lancement d'un programme (tous les PID fils sont concernés). Le cgroup doit toutefois être créé au préalable.
cgexec -g cpu:/toto stress -c 1
Attribution de service
Systemd permet d'exécuter des processus dans un cgroup via les options systemd.resource-control des unités slice.slice
, scope.scope
, service.service
, socket.socket
, mount.mount
et swap.swap
.
À faire...
Persistance
Comme tout pseudo système de fichier, cgroup2 est volatile et ne survivra pas à un redémarrage. Une persistance peut être configurée via les fichiers (non existants par défaut) /etc/cgconfig.conf
et /etc/cgconfig.conf.d/*.conf
du paquet cgroup-tools
.
Comme il est bientôt minuit et que comme à l'accoutumé, les outils simples en lignes commandes, ont des fichiers de configurations de l'espace (pourquoi ne reprennent-ils pas simplement les commandes qui fonctionnent comme iptables-persistent
?), je ne vais pas me coucher à 5 heure du matin juste pour tenter de convertir 3 pauvres lignes de commande en une série de galères longues comme le bras et complexe comme le cerveau torturé des développeurs de ce merdier. Cherchez par vous même et je documenterai peut-être ça un jour...