Aller au contenu

Comprendre les Cgroups V2

Mise à jour :

Si vous faites de la conteneurisation, vous avez sûrement entendu parler des cgroups, mais savez-vous vraiment ce qui se cache derrière ce concept ? Les cgroups (control groups) sont une fonctionnalité essentielle de Linux qui permet de gérer et de limiter les ressources système attribuées aux processus. Avec les cgroups, on peut définir exactement combien de CPU, de mémoire, ou encore de bande passante réseau chaque application peut utiliser, un outil particulièrement utile pour garantir une bonne répartition des ressources dans des environnements partagés.

Dans des plateformes de conteneurisation comme Docker et Kubernetes, les cgroups jouent un rôle central. Ils assurent que chaque conteneur respecte des limites strictes, évitant qu’une application gourmande n’impacte les autres.

Historique des cgroups

Les cgroups ont été introduits dans le noyau Linux en 2007, sous l’impulsion de développeurs de Google qui cherchaient un moyen d’isoler et de limiter l’utilisation des ressources pour chaque application. L’idée était de permettre aux administrateurs système de contrôler plus précisément les ressources allouées aux processus, sans avoir à recourir à des solutions externes ou complexes. À cette époque, les serveurs accueillant plusieurs applications simultanées étaient de plus en plus courants, et la demande pour une gestion fine des ressources grandissait.

Depuis leur intégration, les cgroups ont connu plusieurs améliorations. Initialement, chaque groupe de ressources, appelé sous-système (ou contrôleur), était indépendant. Cela permettait de limiter des aspects spécifiques, comme la mémoire ou le CPU, mais nécessitait des configurations distinctes. Avec le temps, ces sous-systèmes ont été mieux intégrés, notamment dans la version 2 des cgroups, appelée cgroups v2, qui unifie la gestion des ressources en un seul espace, facilitant la configuration et la surveillance.

Fonctionnalités de cgroups

Avec cgroups, la gestion des ressources dans Linux a été simplifiée et uniformisée pour offrir un contrôle encore plus précis et cohérent. Contrairement à la première version, où chaque ressource (comme le CPU ou la mémoire) disposait de sa propre hiérarchie, cgroups v2 unifie tous les contrôleurs de ressources sous une même hiérarchie. Cela permet de configurer et de surveiller plus facilement l’utilisation des ressources par chaque groupe de processus.

Voici les principales fonctionnalités offertes par cgroups v2 pour la gestion des ressources :

  1. Contrôle CPU unifié : Dans cgroups, le fichier cpu.max permet de définir une limite de temps CPU alloué par groupe de processus, sans multiplier les configurations. Par exemple, en spécifiant cpu.max=50000 100000, on limite le groupe à 50 % de CPU, simplifiant la gestion tout en offrant un contrôle fin de l’utilisation CPU.
  2. Gestion simplifiée de la mémoire : Avec le fichier memory.max, cgroups permet de limiter la mémoire maximale qu’un cgroup peut consommer. Le suivi de la consommation est aussi amélioré grâce à memory.current, qui affiche la consommation en temps réel. En cas de dépassement, le cgroup peut émettre des alertes ou bloquer les processus, protégeant ainsi le système d’une surcharge mémoire.
  3. Contrôle unifié des I/O : Le fichier io.max dans cgroups permet de gérer de manière centralisée les opérations d’entrée/sortie sur le disque. Ce fichier permet de spécifier des limites pour chaque périphérique (par exemple, io.max="8:0 rbps=1048576" pour limiter la lecture à 1 Mo/s sur le périphérique /dev/sda). Cela est essentiel pour éviter qu’une application monopolise les performances du disque.
  4. Limitation de la bande passante réseau : Bien que la gestion du réseau soit encore en développement dans cgroups, certains contrôleurs permettent de restreindre l’utilisation de la bande passante pour les processus, ce qui est particulièrement utile dans des environnements conteneurisés ou partagés où la gestion du trafic est cruciale pour garantir des performances stables.
  5. Accès restreint aux périphériques : Avec cgroups, il est possible de contrôler finement quels dispositifs peuvent être accessibles par un cgroup donné. Cela peut inclure l’accès aux disques ou autres périphériques critiques, garantissant que certains processus n’interfèrent pas avec le matériel.

Structure d’un cgroup

Chaque cgroup est représenté par un répertoire unique, situé dans le système de fichiers sous /sys/fs/cgroup. Ce répertoire contient différents fichiers qui permettent de configurer les limitations et de surveiller l’utilisation des ressources pour chaque contrôleur. Par exemple, on trouve des fichiers comme cgroup.procs (qui liste les processus associés au cgroup) et cgroup.subtree_control (qui active les contrôleurs spécifiques comme le CPU ou la mémoire pour le cgroup et ses sous-groupes).

Voici les principales étapes pour configurer un cgroup dans cgroups v2 :

  1. Création du cgroup : Pour créer un nouveau cgroup, il suffit de créer un sous-répertoire dans /sys/fs/cgroup. Ce sous-répertoire devient automatiquement un cgroup, et les processus assignés à ce répertoire suivront les règles de ce cgroup.
  2. Activation des contrôleurs : Avec cgroups v2, les contrôleurs de ressources (comme cpu, memory, et io) sont activés de manière centralisée. Dans le fichier cgroup.subtree_control, on peut spécifier quels contrôleurs doivent être appliqués au cgroup, ce qui simplifie la configuration des ressources.
  3. Gestion des processus : Les processus peuvent être ajoutés à un cgroup en écrivant leur identifiant dans le fichier cgroup.procs du cgroup concerné. Cela permet de facilement assigner ou déplacer des processus entre différents cgroups en fonction des besoins.
  4. Configuration des limites de ressources : Chaque ressource est configurée à travers des fichiers spécifiques. Par exemple, pour limiter l’utilisation du CPU,on peut configurer le fichier cpu.max, et pour la mémoire, memory.max. Ces fichiers contiennent des valeurs qui définissent les limitations que le cgroup impose aux processus qui lui sont associés.

Créer et configurer un cgroup dans cgroups v2

Créer et configurer un cgroup dans cgroups v2 est relativement simple et permet d’avoir un contrôle détaillé sur l’allocation des ressources pour des groupes de processus. La version 2 des cgroups améliore et simplifie ce processus en unifiant les contrôleurs, rendant la configuration plus claire et cohérente. Voici les étapes pour créer un cgroup, y assigner des processus et configurer des limites de ressources :

Créer un cgroup

La première étape pour créer un cgroup consiste à créer un répertoire sous /sys/fs/cgroup. Ce répertoire représente un nouveau cgroup dans lequel on pourra définir des règles spécifiques pour les processus associés.

Terminal window
mkdir /sys/fs/cgroup/mon_cgroup

En créant ce répertoire, nous créons automatiquement un nouveau cgroup, prêt à recevoir des processus et à être configuré pour gérer différentes ressources.

Activer les contrôleurs de ressources

Avec cgroups v2, chaque cgroup ne possède qu’un seul fichier de configuration pour activer ou désactiver les contrôleurs de ressources. Ce fichier, nommé cgroup.subtree_control, permet d’indiquer quels contrôleurs seront actifs pour ce cgroup et ses sous-groupes. Pour activer, par exemple, les contrôleurs cpu et memory, nous pouvons utiliser la commande suivante :

Terminal window
echo "+cpu +memory" > /sys/fs/cgroup/mon_cgroup/cgroup.subtree_control

Cela signifie que les limitations CPU et mémoire seront appliquées aux processus appartenant à ce cgroup. Cette approche rend le processus plus centralisé et facilite l’activation des contrôleurs.

Ajouter des processus au cgroup

Pour affecter un processus au cgroup, on utilise le fichier cgroup.procs. Ce fichier contient une liste des PID (identifiants de processus) des processus affectés au cgroup. En ajoutant un PID dans ce fichier, on assigne ce processus au cgroup, lui appliquant ainsi les limites de ressources configurées.

Terminal window
echo <PID> > /sys/fs/cgroup/mon_cgroup/cgroup.procs

Par exemple, pour assigner un processus ayant le PID 1234, on exécute :

Terminal window
echo 1234 > /sys/fs/cgroup/mon_cgroup/cgroup.procs

Cela place le processus dans le cgroup mon_cgroup, le soumettant aux restrictions configurées pour ce cgroup.

Configurer les limites de ressources

Une fois le cgroup créé et les contrôleurs activés, il est possible de définir des limites pour chaque ressource. Ces limites sont configurées via des fichiers spécifiques, créés automatiquement lors de l’activation des contrôleurs. Voici quelques exemples de configurations courantes :

  • Limiter l’utilisation CPU : Pour limiter le CPU, on utilise le fichier cpu.max, dans lequel on peut spécifier une limite en termes de temps CPU alloué. Par exemple, pour restreindre le CPU à 50% :

    Terminal window
    echo "50000 100000" > /sys/fs/cgroup/mon_cgroup/cpu.max

    Cette commande configure le CPU pour permettre 50 millisecondes de temps CPU toutes les 100 millisecondes.

  • Limiter l’utilisation de la mémoire : Le fichier memory.max permet de fixer une limite de mémoire en octets. Par exemple, pour allouer un maximum de 512 Mo de mémoire :

    Terminal window
    echo "536870912" > /sys/fs/cgroup/mon_cgroup/memory.max

    Avec cette configuration, si les processus du cgroup dépassent 512 Mo, le système émet une erreur et peut tuer les processus pour libérer de la mémoire.

  • Limiter les I/O disque : Pour contrôler l’accès au disque, le fichier io.max permet de définir des limites sur les opérations de lecture/écriture. Par exemple, pour limiter la lecture à 1 Mo/s sur un périphérique :

    Terminal window
    echo "8:0 rbps=1048576" > /sys/fs/cgroup/mon_cgroup/io.max

    Ici, 8:0 fait référence au périphérique (que l’on peut identifier avec lsblk), et rbps signifie read bytes per second.

Vérification et surveillance

Une fois le cgroup configuré, ont peut vérifier les ressources consommées par les processus au sein du cgroup en consultant les fichiers de statistiques. Par exemple, pour voir la mémoire utilisée par mon_cgroup :

Terminal window
cat /sys/fs/cgroup/mon_cgroup/memory.current

Les cgroups incluent des fichiers de statistiques détaillés pour chaque ressource, permettant un suivi précis des ressources utilisées. Cela facilite l’optimisation des configurations, particulièrement dans les environnements partagés où plusieurs applications doivent fonctionner en parallèle.

Gestion des cgroups avec systemd

Systemd est devenu l’un des gestionnaires de services et d’initialisation les plus populaires dans les distributions Linux modernes, et il inclut des fonctionnalités puissantes pour gérer les cgroups de manière intuitive. Grâce à systemd, il est possible de créer, configurer, et surveiller des cgroups sans avoir à manipuler directement les fichiers du système de cgroups. Systemd automatise en grande partie la configuration des cgroups, ce qui en fait un choix pratique pour gérer les services et applications.

Voici comment systemd simplifie la gestion des cgroups :

Création de cgroups avec systemd

Systemd crée automatiquement un cgroup pour chaque service ou unité (unit) lancée. Par exemple, en démarrant un service tel que nginx avec la commande suivante :

Terminal window
systemctl start nginx

Systemd crée un cgroup pour nginx, situé dans /sys/fs/cgroup/system.slice/nginx.service. Tous les processus du service nginx seront associés à ce cgroup, ce qui permet de définir des limites de ressources spécifiques pour ce service sans configurer manuellement le cgroup.

Configuration des ressources avec systemd

Systemd permet de configurer facilement les limites de ressources des services via des directives dans les fichiers d’unité (.service). Ces directives spécifient des limites de CPU, de mémoire et d’I/O, appliquées directement au cgroup du service.

Par exemple, pour limiter l’utilisation CPU et la mémoire pour le service nginx, vous pouvez éditer le fichier nginx.service avec les options suivantes :

[Service]
CPUQuota=50%
MemoryMax=512M
  • CPUQuota limite l’usage du CPU à 50% pour le service nginx.
  • MemoryMax fixe une limite de mémoire de 512 Mo.

Après avoir sauvegardé les modifications, rechargez les configurations de systemd et redémarrez le service pour appliquer les limites :

Terminal window
systemctl daemon-reload
systemctl restart nginx

Ces directives configurent automatiquement les paramètres des cgroups, ce qui est bien plus simple que de manipuler manuellement les fichiers de cgroups dans /sys/fs/cgroup.

Allez jeter un œil dans le contenu des fichiers :

/sys/fs/cgroup/system.slice/nginx.service/cpu.max
50000 100000

Et :

/sys/fs/cgroup/system.slice/nginx.service/memory.max
536870912

Limiter les I/O avec systemd

Systemd permet aussi de limiter les opérations d’entrée/sortie (I/O) pour chaque service. Par exemple, pour restreindre l’accès aux disques d’un service, vous pouvez ajouter des options comme IOReadBandwidthMax ou IOWriteBandwidthMax dans le fichier d’unité.

[Service]
IOReadBandwidthMax=/dev/sda 5M
IOWriteBandwidthMax=/dev/sda 2M

Dans cet exemple, nginx est limité à 5 Mo/s en lecture et 2 Mo/s en écriture sur le périphérique /dev/sda.

Surveiller les ressources utilisées avec systemd

Systemd fournit également des outils pour surveiller l’utilisation des ressources par chaque cgroup. Avec la commande systemctl status, vous pouvez obtenir des informations de base sur un service, y compris une vue d’ensemble des ressources qu’il consomme.

Pour une surveillance plus détaillée, la commande systemd-cgtop affiche l’utilisation des ressources (comme le CPU et la mémoire) par cgroup en temps réel, ce qui est pratique pour visualiser l’impact des services sur le système :

Terminal window
systemd-cgtop
CGroup Tasks %CPU Memory Input/s Output/s
user.slice 440 5.6 5.2G - -
user.slice/user-1000.slice 440 5.6 5.2G - -
user.slice/user-1000.slice/session-1.scope 385 4.4 5.2G - -
/ 692 3.0 4.6G - -
user.slice/user-1000.slice/session-74.scope 14 1.0 7.4M - -
user.slice/user-1000.slice/session-75.scope 14 0.1 7.1M - -
system.slice 106 0.1 631.5M - -
system.slice/tuned.service 4 0.1 18.3M - -
system.slice/multipathd.service 7 0.0 22.0M - -
system.slice/fwupd.service 6 0.0 23.1M - -
dev-hugepages.mount - - 124.0K - -
dev-mqueue.mount - - 40.0K - -
init.scope 1 - 7.5M - -
proc-sys-fs-binfmt_misc.mount - - 8.0K - -

Cette commande liste les cgroups actifs, avec un suivi précis des ressources consommées. C’est un outil précieux pour identifier les services qui consomment trop de ressources et ajuster les paramètres de manière appropriée.

Systemd propose aussi la commande systemd-cgls pour afficher l’arborescence des cgroups actifs sur le système, en montrant les services, les processus et leurs cgroups associés de manière visuelle et hiérarchique :

Terminal window
systemd-cgls
CGroup /:
-.slice
├─user.slice
└─user-1000.slice
├─user@1000.service
├─session.slice
└─dbus.service
├─53007 /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
├─55114 /usr/sbin/libvirt-dbus --session
└─55127 /usr/sbin/libvirtd --timeout=120
└─init.scope
├─1693 /usr/lib/systemd/systemd --user
└─1694 (sd-pam)
├─session-74.scope
├─143738 sshd: bob [priv]
├─143810 sshd: bob@notty
├─143811 -zsh
├─143813 sh
...

Cette commande fournit une vue d’ensemble de tous les cgroups en cours d’exécution et de leur structure, ce qui est particulièrement utile pour diagnostiquer les groupes actifs et comprendre comment les processus sont répartis entre eux.

Conclusion

Maintenant que vous connaissez le fonctionnement des cgroups et les différentes façons de les configurer, vous avez toutes les clés en main pour créer des groupes capables de limiter efficacement les ressources de certains de vos processus. Que ce soit pour restreindre l’utilisation de la mémoire, du CPU ou des I/O, vous pouvez désormais configurer des cgroups adaptés aux besoins spécifiques de vos applications. En les appliquant, vous pourrez mieux gérer les performances et garantir que chaque service fonctionne dans des limites bien définies, contribuant ainsi à la stabilité et à l’efficacité de votre système Linux.

Plus loin

Pour maîtriser chaque aspect essentiel de l’administration de serveurs Linux, parcourez les autres documentations de cette formation :