Guide Complet sur les Cgroups Systemd pour la Limitation et l'Isolation des Ressources
Systemd, le système d'initialisation moderne et le gestionnaire de systèmes et de services pour Linux, offre des outils puissants pour gérer les ressources système. Parmi ses capacités les plus significatives se trouve l'intégration avec les Control Groups (cgroups), une fonctionnalité du noyau Linux qui permet la limitation, la comptabilité et l'isolation de l'utilisation des ressources (CPU, mémoire, E/S disque, réseau, etc.) pour un ensemble de processus. Ce guide explorera comment systemd utilise les cgroups à travers ses types d'unités — slices, scopes et services — pour permettre une limitation et une isolation précises des ressources, garantissant que les processus critiques reçoivent les ressources dont ils ont besoin tout en empêchant les applications incontrôlables d'affecter la stabilité du système.
Comprendre et exploiter l'intégration de systemd avec les cgroups est crucial pour les administrateurs système, les développeurs et toute personne responsable du maintien de la performance et de la fiabilité des systèmes Linux. En définissant des limites de ressources appropriées, vous pouvez prévenir l'épuisement des ressources, améliorer la prévisibilité des performances des applications et renforcer la stabilité globale du système. Ce guide offrira une approche pratique pour configurer ces limites, rendant la gestion complexe des ressources accessible et efficace.
Comprendre les Control Groups (cgroups)
Avant de plonger dans l'implémentation de systemd, il est essentiel de saisir les concepts fondamentaux des cgroups. Les cgroups sont un mécanisme hiérarchique du noyau Linux qui vous permet de regrouper des processus et d'assigner ensuite des politiques de gestion des ressources à ces groupes. Ces politiques peuvent inclure :
- CPU : Limitation du temps CPU, priorisation de l'accès CPU.
- Mémoire : Définition des limites d'utilisation de la mémoire, prévention des conditions de manque de mémoire (OOM).
- E/S : Régulation des opérations de lecture/écriture sur disque.
- Réseau : Limitation de la bande passante réseau.
- Accès aux périphériques : Contrôle de l'accès à des périphériques spécifiques.
Le noyau expose les configurations des cgroups via un système de fichiers virtuel, généralement monté à /sys/fs/cgroup. Chaque contrôleur (par exemple, cpu, memory) possède son propre répertoire, et au sein de ceux-ci, des hiérarchies de répertoires représentent les groupes et leurs limites de ressources associées.
Architecture de gestion des Cgroups par Systemd
Systemd abstrait la complexité de la manipulation directe des cgroups en fournissant un système structuré de gestion d'unités. Il organise les processus en une hiérarchie d'unités, qui sont ensuite mappées aux hiérarchies de cgroups. Les principaux types d'unités pertinents pour la gestion des ressources sont :
- Slices : Ce sont des conteneurs abstraits pour les unités de service. Les slices forment une hiérarchie, permettant la délégation de ressources. Par exemple, une slice pour les sessions utilisateur peut contenir des slices pour des applications individuelles. Systemd crée automatiquement des slices pour les services système, les sessions utilisateur et les machines virtuelles/conteneurs.
- Scopes : Ils sont généralement utilisés pour des groupes de processus temporaires ou créés dynamiquement, souvent associés à des sessions utilisateur ou à des services système qui ne sont pas gérés comme des unités de service complètes. Ils sont transitoires et existent tant que les processus qu'ils contiennent sont en cours d'exécution.
- Services : Ce sont les unités fondamentales pour la gestion des démons et des applications. Lorsqu'une unité de service est démarrée, systemd place ses processus dans une hiérarchie cgroup, généralement au sein d'une slice. Les limites de ressources peuvent être appliquées directement aux unités de service.
La hiérarchie par défaut de Systemd ressemble souvent à ceci :
-.slice (Root slice)
|- system.slice
| |- <service_name>.service
| |- another-service.service
| ...
|- user.slice
| |- user-1000.slice
| | |- session-c1.scope
| | | |- <application>.service (if started by user)
| | | ...
| | ...
| ...
|- machine.slice (for VMs/containers)
...
Application des limites de ressources avec les fichiers d'unité Systemd
Systemd vous permet de spécifier les limites de ressources cgroup directement dans les fichiers d'unité .service, .slice ou .scope. Ces directives sont placées respectivement sous les sections [Service], [Slice] ou [Scope].
Limites de CPU
Les directives principales pour le contrôle des ressources CPU sont :
CPUQuota=: Limite le temps CPU total que l'unité peut utiliser. Ceci est spécifié en pourcentage (par exemple,50 %pour la moitié d'un cœur de CPU) ou en fraction d'un cœur de CPU (par exemple,0.5). Il est également possible de spécifier une valeur en microsecondes par période. La période par défaut est de 100 ms.CPUShares=: Définit une pondération relative pour le temps CPU. Une unité avecCPUShares=2048obtiendra deux fois plus de temps CPU qu'une unité avecCPUShares=1024en cas de contention.CPUWeight=: Un alias deCPUShares=mais avec une plage différente (1-10000, par défaut 100).CPUQuotaPeriodSec=: Définit la période pourCPUQuota. La valeur par défaut est100ms.
Exemple : Limiter un serveur web à 75 % d'un cœur de CPU :
Créez ou modifiez un fichier de service, par exemple, /etc/systemd/system/mywebapp.service :
[Unit]
Description=My Web Application
[Service]
ExecStart=/usr/bin/mywebapp
User=webappuser
Group=webappgroup
# Limit to 75% of one CPU core
CPUQuota=75%
[Install]
WantedBy=multi-user.target
Après avoir créé ou modifié le fichier de service, rechargez le démon systemd et redémarrez le service :
sudo systemctl daemon-reload
sudo systemctl restart mywebapp.service
Limites de mémoire
Les limites de mémoire sont contrôlées par des directives telles que :
MemoryLimit=: Définit une limite stricte sur la quantité de RAM que les processus de l'unité peuvent consommer. Cela peut être spécifié en octets ou avec des suffixes commeK,M,G,T(par exemple,512M).MemoryMax=: Similaire àMemoryLimit, mais souvent considéré comme plus moderne et flexible dans son interaction avec la comptabilité de la mémoire. Il est généralement recommandé par rapport àMemoryLimit.MemoryHigh=: Définit une limite souple. Lorsque cette limite est approchée, la récupération de mémoire (swapping) est déclenchée plus agressivement, mais la limite stricte n'est pas encore appliquée.MemorySwapMax=: Limite la quantité d'espace d'échange (swap) que l'unité peut utiliser.
Exemple : Limiter une base de données à 2 Go de RAM :
Créez ou modifiez un fichier de service, par exemple, /etc/systemd/system/mydb.service :
[Unit]
Description=My Database Service
[Service]
ExecStart=/usr/bin/mydb
User=dbuser
Group=dbgroup
# Limit memory to 2 Gigabytes
MemoryMax=2G
[Install]
WantedBy=multi-user.target
Rechargez et redémarrez :
sudo systemctl daemon-reload
sudo systemctl restart mydb.service
Limites d'E/S
La régulation des E/S peut être contrôlée à l'aide de directives telles que :
IOWeight=: Définit un poids relatif pour les opérations d'E/S. Des valeurs plus élevées donnent une priorité d'E/S plus importante. La plage est de 1 à 1000 (par défaut 500).IOReadBandwidthMax=: Limite la bande passante d'E/S en lecture. Spécifié comme[<périphérique>] <octets_par_seconde>. Par exemple,IOReadBandwidthMax=/dev/sda 100Mlimite les opérations de lecture sur/dev/sdaà 100 Mo/s.IOWriteBandwidthMax=: Limite la bande passante d'E/S en écriture. Format similaire àIOReadBandwidthMax.
Exemple : Limiter un service de traitement en arrière-plan à 50 Mo/s sur un disque spécifique :
Créez ou modifiez un fichier de service, par exemple, /etc/systemd/system/batchproc.service :
[Unit]
Description=Batch Processing Service
[Service]
ExecStart=/usr/bin/batchproc
User=batchuser
Group=batchgroup
# Limit write operations to 50MB/s on /dev/sdb
IOWriteBandwidthMax=/dev/sdb 50M
# Give it a moderate read priority
IOWeight=200
[Install]
WantedBy=multi-user.target
Rechargez et redémarrez :
sudo systemctl daemon-reload
sudo systemctl restart batchproc.service
Gestion et surveillance des Cgroups
Systemd fournit des outils pour inspecter et gérer les cgroups associés à vos unités.
Inspection du statut des Cgroups
La commande systemctl status fournit des informations sur l'appartenance d'une unité à un cgroup et son utilisation des ressources.
systemctl status mywebapp.service
Recherchez les lignes indiquant le chemin du cgroup. Par exemple :
● mywebapp.service - My Web Application
Loaded: loaded (/etc/systemd/system/mywebapp.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2023-10-27 10:00:00 UTC; 1 day ago
Docs: man:mywebapp(8)
Main PID: 12345 (mywebapp)
Tasks: 5 (limit: 4915)
Memory: 15.5M
CPU: 2h 30m 15s
CGroup: /system.slice/mywebapp.service
└─12345 /usr/bin/mywebapp
Vous pouvez également inspecter directement le système de fichiers cgroup :
systemd-cgls # Affiche la hiérarchie des cgroups gérée par systemd
systemd-cgtop # Similaire à top, mais pour les cgroups
Pour voir les limites spécifiques appliquées au cgroup d'un service :
# Pour les limites de mémoire
catsysfs /sys/fs/cgroup/memory/system.slice/mywebapp.service/memory.max
# Pour les limites de CPU
catsysfs /sys/fs/cgroup/cpu/system.slice/mywebapp.service/cpu.max
(Remarque : Les chemins exacts et les noms de fichiers peuvent varier légèrement en fonction de la version du cgroup et de la configuration du système.)
Modification des limites Cgroup à la volée
Bien qu'il soit recommandé de définir les limites dans les fichiers d'unité, vous pouvez les ajuster temporairement à l'aide de systemctl set-property :
sudo systemctl set-property mywebapp.service CPUQuota=50%
Ces modifications ne sont pas persistantes après un redémarrage. Pour les rendre permanentes, mettez à jour le fichier d'unité et rechargez le démon systemd.
Slices pour la délégation de ressources
Les slices sont puissantes pour gérer des groupes de services ou d'applications. Vous pouvez définir des limites de ressources sur une slice, et tous les services ou scopes au sein de cette slice hériteront ou seront contraints par ces limites.
Exemple : Créer une slice dédiée pour les tâches de traitement par lots gourmandes en ressources :
Créez un fichier de slice, par exemple, /etc/systemd/system/batch.slice :
[Unit]
Description=Batch Processing Slice
[Slice]
# Limit total CPU for all jobs in this slice to 1 core
CPUQuota=100%
# Limit total memory to 4GB
MemoryMax=4G
Maintenant, vous pouvez configurer les services pour qu'ils s'exécutent dans cette slice en utilisant la directive Slice= dans leurs fichiers .service :
[Unit]
Description=Specific Batch Job
[Service]
ExecStart=/usr/bin/mybatchjob
# Place this service into the batch.slice
Slice=batch.slice
[Install]
WantedBy=multi-user.target
Rechargez systemd, activez/démarrez la slice si nécessaire (bien qu'elle soit souvent activée implicitement), et démarrez le service.
sudo systemctl daemon-reload
sudo systemctl start mybatchjob.service
Cette approche vous permet de regrouper les processus associés et de gérer leur consommation collective de ressources.
Bonnes pratiques et considérations
- Commencez par des limites incrémentielles : Lorsque vous définissez des limites, commencez par des valeurs conservatrices et augmentez-les progressivement si nécessaire. Des limites agressives peuvent déstabiliser les applications.
- Surveillez : Surveillez régulièrement l'utilisation des ressources de votre système et l'impact de vos paramètres cgroup. Des outils comme
systemd-cgtop,htop,topetiotopsont inestimables. - Comprenez Cgroup v1 vs. v2 : Systemd prend en charge les cgroup v1 et v2. Bien que de nombreuses directives soient similaires, v2 offre une hiérarchie unifiée et quelques différences de comportement. Assurez-vous de savoir quelle version votre système utilise si vous rencontrez des problèmes complexes.
- Priorisation vs. Limites Strictes : Utilisez
CPUShares/CPUWeightpour la priorisation lorsque les ressources sont rares, etCPUQuotapour des limites strictes. De même,MemoryHighest pour les limites souples etMemoryMaxpour les limites strictes. - Service vs. Slice : Utilisez les unités de service pour les applications individuelles et les slices pour gérer des groupes d'applications connexes ou des pools de ressources.
- Documentation : Documentez clairement les limites de ressources appliquées aux services critiques, en particulier dans les environnements de production.
- OOM Killer : Sachez que si un processus dépasse sa limite
MemoryMax, le tueur Out-Of-Memory (OOM) du noyau pourrait le terminer, même s'il se trouve dans un cgroup. Systemd peut gérer le comportement du tueur OOM pour des cgroups spécifiques à l'aide de directives commeOOMPolicy=.
Conclusion
L'intégration de Systemd avec les cgroups offre un mécanisme robuste et convivial pour contrôler et isoler les ressources système. En maîtrisant l'utilisation des unités de service, de scope et de slice, les administrateurs peuvent appliquer efficacement des limites de CPU, de mémoire et d'E/S pour garantir la stabilité du système, des performances prévisibles et prévenir la famine des ressources. La mise en œuvre de ces contrôles est un aspect fondamental de l'administration moderne des systèmes Linux, permettant un contrôle accru de vos environnements d'application et de l'infrastructure sous-jacente.