Utiliser Systemd pour gérer les groupes de contrôle

Présente les concepts de cgroups dans Oracle Linux et montre comment systemd organise et gère le contrôle des ressources.

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

Par exemple, si vous devez répartir la ressource de CPU entre trois services systemd, myservice1.service, myservice2.service et myservice3.service, dans un rapport de 150:100:50, vous pouvez utiliser les outils systemd pour affecter à chaque service cgroup correspondant une pondération de CPU correspondant à sa part cible.

Remarque

systemd est responsable de la création et de la gestion de cgroups dans le système de fichiers virtuel /sys/fs/cgroup/.

La suite systemd fournit des méthodes sécurisées de haut niveau pour configurer les ressources cgroup, telles que l'utilisation de fichiers de dépôt ou de la commande systemctl set-property. La modification directe des objets systemd dans le système de fichiers virtuel /sys/fs/cgroup/ n'est pas recommandée.

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

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

    Par exemple, un serveur peut avoir le groupe de contrôle NetworkManager.service pour regrouper les processus appartenant au service NetworkManager, et le groupe de contrôle firewalld.service pour regrouper les processus appartenant au service firewalld, etc.

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

La fonctionnalité cgroup est montée en tant que système de fichiers virtuel sous /sys/fs/cgroup.

Chaque cgroup a un dossier correspondant dans le système de fichiers /sys/fs/cgroup. Par exemple, le fichier cgroups créé par systemd pour les services qu'il gère peut être vu en exécutant la commande ls -l /sys/fs/cgroup/system.slice | grep ".service" comme indiqué dans l'exemple de bloc de code suivant :

ls -l /sys/fs/cgroup/system.slice | grep ".service"
...root root 0 Mar 22 10:47 atd.service
...root root 0 Mar 22 10:47 auditd.service
...root root 0 Mar 22 10:47 chronyd.service
...root root 0 Mar 22 10:47 crond.service
...root root 0 Mar 22 10:47 dbus-broker.service
...root root 0 Mar 22 10:47 dtprobed.service
...root root 0 Mar 22 10:47 firewalld.service
...root root 0 Mar 22 10:47 httpd.service
...

Vous pouvez également créer un élément cgroups personnalisé en dehors des branches systemd, par exemple sous un emplacement tel que /sys/fs/cgroup/MyGroups/, et affecter des ID de processus (PIDs) à des éléments cgroups différents en fonction des besoins du système. Cependant, cette approche ne doit être utilisée que pour des scénarios spécifiques, tels que le débogage ou les tests temporaires. Pour la plupart des cas d'utilisation, nous recommandons d'utiliser systemd pour configurer cgroups afin de garantir une gestion correcte et persistante des ressources.

Oracle Linux fournit deux types de groupe de contrôle :

Groupes de contrôle version 1 (cgroups v1)

Ces groupes fournissent une hiérarchie de contrôleurs par ressource.

Chaque ressource (CPU, mémoire, E/S, etc.) possède sa propre hiérarchie de groupes de contrôle. Un inconvénient de ce groupe est la difficulté d'établir une bonne coordination de l'utilisation des ressources entre les groupes qui pourraient appartenir à des hiérarchies de processus différentes.

Groupes de contrôle version 2 (cgroups v2)

Ces groupes fournissent une hiérarchie de groupes de contrôle unique par rapport à laquelle tous les contrôleurs de ressources sont montés. Dans cette hiérarchie, vous pouvez obtenir une meilleure coordination des utilisations des ressources entre les différents contrôleurs de ressources. Cette version est une amélioration par rapport à cgroups v1 dont la flexibilité excessive a empêché une bonne coordination de l'utilisation des ressources entre les consommateurs du système.

Oracle Linux 8 inclut les deux versions, cgroups v1 étant activé et monté par défaut. Oracle Linux 9 fournit également les deux versions, mais active et monte cgroups v2 par défaut.

Oracle Linux 10 offre uniquement l'implémentation de la version 2 des groupes de contrôle. cgroups v1 est en phase d'abandon et n'est pas disponible. cgroups v2 est activé et monté par défaut.

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

A propos des groupes de contrôle et de systemd

Les groupes de contrôle peuvent être utilisés par le système systemd et le gestionnaire de services pour la gestion des ressources. systemd utilise ces groupes pour organiser les unités et les services qui consomment des ressources. Pour plus d'informations sur systemd, reportez-vous à Gestion du système avec systemd.

systemd fournit différents types d'unité, dont trois à des fins de contrôle des ressources :

  • Service : processus ou groupe de processus dont les paramètres sont basés sur un fichier de configuration d'unité. Les services englobent des processus spécifiés dans une "collecte" de sorte que systemd puisse démarrer ou arrêter les processus en un seul ensemble. Les noms de service suivent le format name.service.

  • Portée : groupe de processus créés en externe, tels que les sessions utilisateur, les conteneurs, les machines virtuelles, etc.

    Comme pour les services, les portées encapsulent ces processus créés et sont démarrées ou arrêtées par les processus arbitraires, puis inscrites par systemd lors de l'exécution. Les noms de portée suivent le format name.scope.

  • Tranche : groupe d'unités organisées hiérarchiquement dans lequel se trouvent les services et les portées.

    Ainsi, les tranches elles-mêmes ne contiennent pas de processus. Les portées et les services d'une tranche définissent plutôt les processus. Chaque nom d'unité de tranche correspond au chemin d'accès à un emplacement dans la hiérarchie. Les tranches racine, généralement user.slice pour tous les processus utilisateur et system.slice pour les processus système, sont créées automatiquement dans la hiérarchie. Les tranches parent existent immédiatement sous la tranche racine et suivent le format parent-name.slice. Ces tranches racine peuvent alors avoir des sous-tranches sur plusieurs niveaux.

Le service, la portée et les unités de tranche sont directement mappés avec les objets de la hiérarchie des groupes de contrôle. Lorsque ces unités sont activées, elles sont mappées directement avec les chemins de groupe de contrôle créés à partir des noms d'unités. Pour afficher la correspondance entre les types d'unité de ressource systemd et les groupes de contrôle, saisissez :

sudo systemd-cgls
Working directory /sys/fs/cgroup:
├─user.slice (#1243)
│ → trusted.invocation_id: 50ce3909b2644f919ee420adc39edb4b
│ ├─user-1001.slice (#4167)
│ │ → trusted.invocation_id: 02e80a960d4549a7a9c69ce0fb546c26
│ │ ├─session-2.scope (#4405)
│ │ │ ├─2417 sshd: alice [priv]
│ │ │ ├─2430 sshd: alice@pts/0
│ │ │ ├─2431 -bash
│ │ │ ├─2689 sudo systemd-cgls
│ │ │ ├─2691 systemd-cgls
│ │ │ └─2692 less
...
│   └─user@984.service … (#3827)
│     → trusted.delegate: 1
│     → trusted.invocation_id: 09b47ce9f3124239b75814114353f3f2
│     └─init.scope (#3861)
│       ├─2058 /usr/lib/systemd/systemd --user
│       └─2099 (sd-pam)
├─init.scope (#19)
│ └─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 17
└─system.slice (#53)
...
  ├─chronyd.service (#2467)
  │ → trusted.invocation_id: c0f77aaa9c7844e6bef6a6898ae4dd56
  │ └─1358 /usr/sbin/chronyd -F 2
  ├─auditd.service (#2331)
  │ → trusted.invocation_id: 756808add6a348609316c9e8c1801846
  │ └─1310 /sbin/auditd
  ├─tuned.service (#3079)
  │ → trusted.invocation_id: 2c358135fc46464d862b05550338d4f4
  │ └─1415 /usr/bin/python3 -Es /usr/sbin/tuned -l -P
  ├─systemd-journald.service (#1651)
  │ → trusted.invocation_id: 7cb7ccb14e044a899aadf47bbb583ada
  │ └─977 /usr/lib/systemd/systemd-journald
  ├─atd.service (#3623)
  │ → trusted.invocation_id: 597a7a4e5646468db407801b8562d869
  │ └─1915 /usr/sbin/atd -f
  ├─sshd.service (#3419)
  │ → trusted.invocation_id: 490504a683fc4311ab0fbeb0864a1a34
  │ └─1871 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
...

Pour obtenir un exemple d'utilisation des commandes systemd telles que systemctl pour gérer les ressources, reportez-vous à Contrôle de l'accès aux ressources système. Pour plus de détails techniques, reportez-vous aux pages de manuel systemctl(1), systemd-cgls(1) et systemd.resource-control(5).

Utilisation de systemd pour gérer les cgroups v2

Montre comment systemd structure les cgroups v2 pour les services et les utilisateurs et comment inspecter la hiérarchie.

La méthode préférée pour gérer l'allocation de ressources avec cgroups v2 est d'utiliser la fonctionnalité de groupe de contrôle fournie par systemd.

Remarque

Pour plus d'informations sur l'activation de la fonctionnalité cgroups v2 sur le système, reportez-vous à la section Managing Resources Using Control Groups

Par défaut, systemd crée un dossier cgroup pour chaque service systemd configuré sur l'hôte. systemd nomme ces dossiers au format servicename.service, où servicename est le nom du service associé au dossier.

Pour afficher la liste des dossiers cgroup créés par systemd pour les services, exécutez la commande ls sur la branche system.slice du système de fichiers cgroup, comme indiqué dans l'exemple de bloc de code suivant :

ls /sys/fs/cgroup/system.slice/
...                     ...                           ...
app_service1.service    cgroup.subtree_control        httpd.service
app_service2.service    chronyd.service               ...  
...                     crond.service                 ...
cgroup.controllers      dbus-broker.service           ...
cgroup.events           dtprobed.service              ...
cgroup.freeze           firewalld.service             ...
...                     gssproxy.service              ...
...                     ...                           ...

Dans le bloc de commande précédent :

  • Les dossiers app_service1.service et app_service2.service représentent les services d'application personnalisés qui peuvent s'exécuter sur le système.

Outre les groupes de contrôle de service, systemd crée également un dossier cgroup pour chaque utilisateur sur l'hôte.

Pour voir le fichier cgroups créé pour chaque utilisateur, vous pouvez exécuter la commande ls sur la branche user.slice du système de fichiers cgroup, comme indiqué dans l'exemple de bloc de code suivant :

ls /sys/fs/cgroup/user.slice/
cgroup.controllers      cgroup.subtree_control        user-1001.slice
cgroup.events           cgroup.threads                user-982.slice
cgroup.freeze           cgroup.type                   ...
...                     ...                           ...
...                     ...                           ...
...                     ...                           ...

Dans le bloc de code précédent :

  • Chaque dossier utilisateur cgroup est nommé au format user-UID.slice. Par conséquent, le groupe de contrôle user-1001.slice est destiné à un utilisateur dont UID est 1001, par exemple.

systemd fournit un accès de haut niveau aux fonctionnalités cgroups et de contrôleur de ressources de noyau afin que vous n'ayez pas à accéder directement au système de fichiers.

Par exemple, pour définir la pondération de la CPU d'un service appelé app_service1.service, exécutez la commande systemctl set-property comme suit :

sudo systemctl set-property app_service1.service CPUWeight=150

Ainsi, systemd vous permet de gérer la distribution des ressources au niveau de l'application, plutôt qu'au niveau du PID de processus utilisé lors de la configuration de cgroups sans utiliser la fonctionnalité systemd.

A propos des tranches et de l'allocation des ressources dans systemd

Cette section examine la façon dont systemd divise initialement chacun des contrôleurs de noyau par défaut, par exemple CPU, memory et blkio, en parties appelées "tranches", comme illustré par l'exemple de graphique à secteurs suivant :

Remarque

Vous pouvez également créer des tranches personnalisées pour la distribution des ressources, comme indiqué dans la section Définition des options de contrôleur de ressources et création de tranches personnalisées.

Graphique à secteurs avec 3 tranches de taille égale, étiquetées Système, Machine et Utilisateur. L'utilisateur et le système sont divisés en sous-tranches.

Comme le montre le graphique à secteurs précédent, chaque contrôleur de ressources est divisé par défaut de manière égale entre les 3 tranches suivantes :

  • Système (system.slice).

  • Utilisateur (user.slice).

  • Machine (machine.slice).

La liste suivante examine chaque tranche de plus près. Pour les besoins de la discussion, les exemples de la liste se concentrent sur le contrôleur de CPU.

Système (system.slice)

Cette tranche de ressources est utilisée pour gérer l'allocation des ressources entre les démons et les unités de service.

Comme indiqué dans l'exemple de graphique à secteurs précédent, la tranche système est divisée en autres sous-tranches. Par exemple, dans le cas de ressources CPU, nous pouvons disposer d'allocations de sous-tranches dans la tranche système qui incluent les éléments suivants :
  • httpd.service (CPUWeight=100)

  • sshd.service (CPUWeight = 100)

  • crond.service (CPUWeight = 100)

  • app1.service (CPUWeight =100)

  • app2.service (CPUWeight =100)

Dans la liste précédente, app1.service et app2.service représentent les services d'application personnalisés qui peuvent s'exécuter sur le système.
Utilisateur (user.slice)
Cette tranche de ressource est utilisée pour gérer l'allocation des ressources entre les sessions utilisateur. Une tranche unique est créée pour chaque UID, quel que soit le nombre de connexions actives par l'utilisateur associé sur le serveur. En continuant avec notre exemple de graphique à secteurs, les sous-tranches peuvent être les suivantes :
  • user1 (CPUWeight=100, UID=982)

  • user2 (CPUWeight=100, UID=1001)

Machine (machine.slice)
Cette tranche de la ressource est utilisée pour gérer l'allocation des ressources entre les machines virtuelles hébergées, telles que les invités KVM et les conteneurs Linux. La tranche de machine n'est présente sur un serveur que si ce dernier héberge des machines virtuelles ou des conteneurs Linux.
Remarque

Les allocations de partage ne définissent pas de limite maximale pour une ressource.

Dans les exemples précédents, la tranche user.slice compte 2 utilisateurs : user1 et user2. Une part égale de la ressource de CPU disponible pour le parent user.slice est allouée à chaque utilisateur. Toutefois, si les processus associés à user1 sont inactifs et ne nécessitent aucune ressource de CPU, son partage de CPU est disponible pour l'allocation à user2 si nécessaire. Dans ce cas, user2 peut même être alloué à la ressource CPU entière répartie sur le parent user.slice si cela est requis par d'autres utilisateurs.

Pour limiter la ressource CPU, vous devez définir la propriété CPUQuota sur le pourcentage requis.

Tranches, services et portées dans la hiérarchie cgroup

L'analogie des graphiques à secteurs utilisée dans les sections précédentes permet de conceptualiser la division des ressources en tranches. Cependant, en termes d'organisation structurelle, les groupes de contrôle sont organisés dans une hiérarchie. Vous pouvez afficher la hiérarchie de groupe de contrôle systemd sur le système en exécutant la commande systemd-cgls comme suit :

Conseil

Pour afficher l'intégralité de la hiérarchie cgroup, en commençant par la tranche racine -.slice, comme dans l'exemple suivant, veillez à exécuter systemd-cgls à partir de l'extérieur du point de montage du groupe de contrôle /sys/fs/cgroup/.

Sinon, si vous exécutez la commande à partir de /sys/fs/cgroup/, la sortie commence à partir de l'emplacement cgroup à partir duquel la commande a été exécutée. Pour plus d'informations, reportez-vous à systemd-cgls(1).

systemd-cgls
Control group /:
-.slice
...
├─user.slice (#1429)
│ → user.invocation_id: 604cf5ef07fa4bb4bb86993bb5ec15e0
│ ├─user-982.slice (#4131)
│ │ → user.invocation_id: 9d0d94d7b8a54bcea2498048911136c8
│ │ ├─session-c1.scope (#4437)
│ │ │ ├─2416 /usr/bin/sudo -u ocarun /usr/libexec/oracle-cloud-agent/plugins/runcommand/runcommand
│ │ │ └─2494 /usr/libexec/oracle-cloud-agent/plugins/runcommand/runcommand
│ │ └─user@982.service … (#4199)
│ │   → user.delegate: 1
│ │   → user.invocation_id: 37c7aed7aa6e4874980b79616acf0c82
│ │   └─init.scope (#4233)
│ │     ├─2437 /usr/lib/systemd/systemd --user
│ │     └─2445 (sd-pam)
│ └─user-1001.slice (#7225)
│   → user.invocation_id: ce93ad5f5299407e9477964494df63b7
│   ├─session-2.scope (#7463)
│   │ ├─20304 sshd: oracle [priv]
│   │ ├─20404 sshd: oracle@pts/0
│   │ ├─20405 -bash
│   │ ├─20441 systemd-cgls
│   │ └─20442 less
│   └─user@1001.service … (#7293)
│     → user.delegate: 1
│     → user.invocation_id: 70284db060c1476db5f3633e5fda7fba
│     └─init.scope (#7327)
│       ├─20395 /usr/lib/systemd/systemd --user
│       └─20397 (sd-pam)
├─init.scope (#19)
│ └─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 28
└─system.slice (#53)
 ...
  ├─dbus-broker.service (#2737)
  │ → user.invocation_id: 2bbe054a2c4d49809b16cb9c6552d5a6
  │ ├─1450 /usr/bin/dbus-broker-launch --scope system --audit
  │ └─1457 dbus-broker --log 4 --controller 9 --machine-id 852951209c274cfea35a953ad2964622 --max-bytes 536870912 --max-fds 4096 --max-matches 131072 --audit
 ...
  ├─chronyd.service (#2805)
  │ → user.invocation_id: e264f67ad6114ad5afbe7929142faa4b
  │ └─1482 /usr/sbin/chronyd -F 2
  ├─auditd.service (#2601)
  │ → user.invocation_id: f7a8286921734949b73849b4642e3277
  │ ├─1421 /sbin/auditd
  │ └─1423 /usr/sbin/sedispatch
  ├─tuned.service (#3349)
  │ → user.invocation_id: fec7f73678754ed687e3910017886c5e
  │ └─1564 /usr/bin/python3 -Es /usr/sbin/tuned -l -P
  ├─systemd-journald.service (#1837)
  │ → user.invocation_id: bf7fb22ba12f44afab3054aab661aedb
  │ └─1068 /usr/lib/systemd/systemd-journald
  ├─atd.service (#3961)
  │ → user.invocation_id: 1c59679265ab492482bfdc9c02f5eec5
  │ └─2146 /usr/sbin/atd -f
  ├─sshd.service (#3757)
  │ → user.invocation_id: 57e195491341431298db233e998fb180
  │ └─2097 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
  ├─crond.service (#3995)
  │ → user.invocation_id: 4f5b380a53db4de5adcf23f35d638ff5
  │ └─2150 /usr/sbin/crond -n
  ...

L'exemple de sortie précédent montre comment tous les groupes de contrôle "*.slice" résident sous la tranche racine -.slice. Sous la tranche racine, vous pouvez voir les groupes de contrôle user.slice et system.slice, chacun avec ses propres sous-tranches enfant cgroup.

En examinant la sortie de la commande systemd-cgls , vous pouvez voir comment, à l'exception de root -.slice, tous les processus se trouvent sur des noeuds feuille. Cette disposition est appliquée par cgroups v2, dans une règle appelée règle "aucun processus interne". Pour plus d'informations sur la règle "aucun processus interne", reportez-vous à la page cgroups (7).

La sortie de l'exemple de commande systemd-cgls précédent montre également comment les tranches peuvent avoir des groupes de contrôle enfant descendants qui sont des portées systemd. Les portées systemd sont examinées dans la section suivante.

Portées systemd

La portée systemd est un type d'unité systemd qui regroupe les processus actifs de service système qui ont été lancés indépendamment de systemd. Les unités de portée sont des unités cgroups transitoires créées par programmation à l'aide des interfaces de bus de systemd.

Par exemple, dans l'exemple de code suivant, l'utilisateur avec UID 1001 a exécuté la commande systemd-cgls, et la sortie indique que session-2.scope a été créé pour les processus que l'utilisateur a générés indépendamment de systemd (y compris le processus pour la commande elle-même, 21380 sudo systemd-cgls) :

Remarque

Dans l'exemple suivant, la commande a été exécutée à partir du point de montage du groupe de contrôle /sys/fs/cgroup/. Par conséquent, au lieu de la tranche racine, la sortie commence à partir de l'emplacement cgroup à partir duquel la commande a été exécutée.
sudo systemd-cgls
Working directory /sys/fs/cgroup:
...
├─user.slice (#1429)
│ → user.invocation_id: 604cf5ef07fa4bb4bb86993bb5ec15e0
│ → trusted.invocation_id: 604cf5ef07fa4bb4bb86993bb5ec15e0
...
│ └─user-1001.slice (#7225)
│   → user.invocation_id: ce93ad5f5299407e9477964494df63b7
│   → trusted.invocation_id: ce93ad5f5299407e9477964494df63b7
│   ├─session-2.scope (#7463)
│   │ ├─20304 sshd: oracle [priv]
│   │ ├─20404 sshd: oracle@pts/0
│   │ ├─20405 -bash
│   │ ├─21380 sudo systemd-cgls
│   │ ├─21382 systemd-cgls
│   │ └─21383 less
│   └─user@1001.service … (#7293)
│     → user.delegate: 1
│     → trusted.delegate: 1
│     → user.invocation_id: 70284db060c1476db5f3633e5fda7fba
│     → trusted.invocation_id: 70284db060c1476db5f3633e5fda7fba
│     └─init.scope (#7327)
│       ├─20395 /usr/lib/systemd/systemd --user
│       └─20397 (sd-pam)

Définition des options du contrôleur de ressources et création de tranches personnalisées

Présente trois approches (fichiers d'unité, drop-ins et systemctl set-property) pour affiner les contrôleurs de ressources et les dispositions de tranche.

systemd fournit les méthodes suivantes pour définir les options de contrôleur de ressources, telles que CPUWeight, CPUQuota, etc., afin de personnaliser l'allocation de ressources sur le système :

  • Utilisation des fichiers d'unité de service.

  • Utilisation de fichiers de dépôt.

  • Utilisation de la commande systemctl set-property.

Les sections suivantes fournissent des exemples de procédures d'utilisation de chacune de ces méthodes pour configurer les ressources et les tranches du système.

Utiliser des fichiers d'unité de service

Pour définir des options dans un fichier d'unité de service, procédez comme suit :

  1. Créez le fichier /etc/systemd/system/myservice1.service avec le contenu suivant :
    [Service]
    Type=oneshot
    ExecStart=/usr/lib/systemd/generate_load.sh
    TimeoutSec=0
    StandardOutput=tty
    RemainAfterExit=yes
    
    [Install]
    WantedBy=multi-user.target
  2. Le service créé à l'étape précédente nécessite un script bash /usr/lib/systemd/generate_load.sh. Créez le fichier avec le contenu suivant :
    #!/bin/bash
    for i in {1..4};do while : ; do : ; done & done
  3. Rendez le script exécutable :
    sudo chmod +x /usr/lib/systemd/generate_load.sh
  4. Pour démarrer le service, activez-le :
    sudo systemctl enable myservice1 --now
  5. Exécutez la commande systemd-cgls et vérifiez que le service myservice1 est exécuté sous system.slice :
    systemd-cgls
    Control group /:
    -.slice
    ...
    ├─user.slice (#1429)
    ...
    └─system.slice (#53)
      ...
      ├─myservice1.service (#7939)
      │ → user.invocation_id: e227f8f288444fed92a976d391e6a897
      │ ├─22325 /bin/bash /usr/lib/systemd/generate_load.sh
      │ ├─22326 /bin/bash /usr/lib/systemd/generate_load.sh
      │ ├─22327 /bin/bash /usr/lib/systemd/generate_load.sh
      │ └─22328 /bin/bash /usr/lib/systemd/generate_load.sh
      ├─pmie.service (#4369)
      │ → user.invocation_id: 68fcd40071594481936edf0f1d7a8e12
       ...
  6. Créez une tranche personnalisée pour le service.

    Ajoutez la ligne Slice=my_custom_slice.slice à la section [Service] dans le fichier myservice1.service, créé à l'étape précédente, comme indiqué dans le bloc de code suivant :

    [Service]
    Slice=my_custom_slice.slice
    Type=oneshot
    ExecStart=/usr/lib/systemd/generate_load.sh
    TimeoutSec=0
    StandardOutput=tty
    RemainAfterExit=yes
    
    [Install]
    WantedBy=multi-user.target
    
    Attention 

    Utilisez des traits de soulignement au lieu de tirets pour séparer les termes dans les noms de tranche.

    Dans systemd, un tiret dans un nom de tranche est un caractère spécial : dans systemd, les tirets dans les noms de tranche sont utilisés pour décrire le chemin cgroup complet vers la tranche (à partir de la tranche racine).

    Par exemple, si vous indiquez "my-custom-slice.slice" comme nom de tranche, au lieu de créer une tranche de ce nom, systemd crée le chemin cgroups suivant sous la tranche racine : my.slice/my-custom.slice/my-custom-slice.slice.

  7. Après avoir modifié le fichier, assurez-vous que systemd recharge ses fichiers de configuration, puis redémarrez le service :
    sudo systemctl daemon-reload
    sudo systemctl restart myservice1
  8. Exécutez la commande systemd-cgls et vérifiez que le service myservice1 est en cours d'exécution sous la tranche personnalisée my_custom_slice :
    systemd-cgls
    Control group /:
    -.slice
    ...
    ├─user.slice (#1429)
    ...
    ├─my_custom_slice.slice (#7973)
    │ → user.invocation_id: a8a493a8db1342be85e2cdf1e80255f8
    │ └─myservice1.service (#8007)
    │   → user.invocation_id: 9a4a6171f2844e479d4a0f347aac38ce
    │   ├─22385 /bin/bash /usr/lib/systemd/generate_load.sh
    │   ├─22386 /bin/bash /usr/lib/systemd/generate_load.sh
    │   ├─22387 /bin/bash /usr/lib/systemd/generate_load.sh
    │   └─22388 /bin/bash /usr/lib/systemd/generate_load.sh
    ├─init.scope (#19)
    │ └─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 28
    └─system.slice (#53)
      ├─irqbalance.service (#2907)
      │ → user.invocation_id: 00d64c9b9d224f179496a83536dd60bb
      │ └─1464 /usr/sbin/irqbalance --foreground
     ...
    

Utiliser des fichiers de dépôt

Pour configurer des ressources à l'aide d'un fichier de dépôt, procédez comme suit :

  1. Créez le répertoire du fichier de dépôt de service.
    Conseil

    Le répertoire de dépôt pour les fichiers de dépôt pour un service se trouve à l'adresse /etc/systemd/system/service_name.service.d, où service_name est le nom du service.

    En continuant avec notre exemple avec le service myservice1, nous exécuterions la commande suivante :

    sudo mkdir -p /etc/systemd/system/myservice1.service.d/
  2. Créez 2 fichiers de dépôt appelés 00-slice.conf et 10-CPUSettings.conf dans le répertoire myservice1.service.d créé à l'étape précédente.
    Remarque

    • Plusieurs fichiers de dépôt avec des noms différents sont appliqués dans l'ordre lexicographic.

    • Ces fichiers de dépôt sont prioritaires sur le fichier d'unité de service.

  3. Ajoutez le contenu suivant à 00-slice.conf
    [Service]
    Slice=my_custom_slice2.slice
    MemoryAccounting=yes
    CPUAccounting=yes
    

    Le paramètre de tranche Slice=my_custom_slice2.slice dans le fichier de dépôt est prioritaire sur l'entrée Slice=my_custom_slice.slice ajoutée au fichier d'unité de service lors d'une étape antérieure.

  4. Et ajoutez le contenu suivant à 10-CPUSettings.conf
    [Service]
    CPUWeight=200
    
  5. Créez un second service (myservice2) et affectez-lui un autre CPUWeight à celui affecté à myservice1 :
    1. Créez le fichier /etc/systemd/system/myservice2.service avec le contenu suivant :
      [Service]
      Slice=my_custom_slice2.slice
      Type=oneshot
      ExecStart=/usr/lib/systemd/generate_load2.sh
      TimeoutSec=0
      StandardOutput=tty
      RemainAfterExit=yes
      
      [Install]
      WantedBy=multi-user.target
    2. Le service créé à l'étape précédente nécessite un script bash /usr/lib/systemd/generate_load2.sh. Créez le fichier avec le contenu suivant :
      #!/bin/bash
      for i in {1..4};do while : ; do : ; done & done
    3. Rendez le script exécutable :
      sudo chmod +x /usr/lib/systemd/generate_load2.sh
    4. Créez une suppression de fichier /etc/systemd/system/myservice2.service.d/10-CPUSettings.conf pour myservice2 avec le contenu suivant :
      [Service]
      CPUWeight=400
      
  6. Assurez-vous que systemd recharge ses fichiers de configuration, puis redémarrez myservice1, et activez et démarrez myservices2 :
    sudo systemctl daemon-reload
    sudo systemctl restart myservice1
    sudo systemctl enable myservice2 --now
  7. Exécutez la commande systemd-cgtop pour afficher les groupes de contrôle classés en fonction de leur utilisation des ressources. L'exemple de sortie suivant montre comment, en plus de l'utilisation des ressources de chaque tranche, la commande systemd-cgtop affiche l'utilisation des ressources dans chaque tranche. Vous pouvez donc l'utiliser pour vérifier que la pondération de l'UC a été divisée comme prévu.
    systemd-cgtop
    Control Group                                     Tasks   %CPU   Memory  Input/s Output/s
    /                                                   228  198.8   712.5M        -        -
    my_custom_slice2.slice                                8  198.5     1.8M        -        -
    my_custom_slice2.slice/myservice2.service             4  132.8   944.0K        -        -
    my_custom_slice2.slice/myservice1.service             4   65.6   976.0K        -        -
    user.slice                                           18    0.9    43.9M        -        -
    user.slice/user-1001.slice                            6    0.9    13.7M        -        -
    user.slice/user-1001.slice/session-2.scope            4    0.9     9.4M        -        -
    system.slice                                         60    0.0   690.8M        -        -
    

Utilisation de systemctl set-property

La commande systemctl set-property place les fichiers de configuration à l'emplacement suivant :

/etc/systemd/system.control
Attention

Vous ne devez pas modifier manuellement les fichiers créés par la commande systemctl set-property.

Remarque

La commande systemctl set-property ne reconnaît pas toutes les propriétés de contrôle des ressources utilisées dans les fichiers d'unité système et de dépôt abordés précédemment dans cette rubrique.

La procédure suivante montre comment utiliser la commande systemctl set-property pour configurer l'allocation de ressources :

  1. Pour poursuivre notre exemple, créez un autre fichier de service à l'emplacement /etc/systemd/system/myservice3.service avec le contenu suivant :
    [Service]
    Type=oneshot
    ExecStart=/usr/lib/systemd/generate_load3.sh
    TimeoutSec=0
    StandardOutput=tty
    RemainAfterExit=yes
    [Install]
    WantedBy=multi-user.target
  2. Définissez la tranche du service sur my_custom_slice2 (la même tranche que celle utilisée par les services créés à partir des étapes précédentes) en ajoutant la ligne suivante à la section [Service] dans le fichier myservice3.service :
    Slice=my_custom_slice2.slice
    Remarque

    La tranche doit être définie dans le fichier service-unit car la commande systemctl set-property ne reconnaît pas la propriété Slice.

  3. Le service créé à l'étape précédente nécessite un script bash /usr/lib/systemd/generate_load3.sh. Créez le fichier avec le contenu suivant :
    #!/bin/bash
    for i in {1..4};do while : ; do : ; done & done
  4. Rendez le script exécutable :
    sudo chmod +x /usr/lib/systemd/generate_load3.sh
  5. Assurez-vous que systemd recharge ses fichiers de configuration, puis activez et démarrez le service :
    sudo systemctl daemon-reload
    sudo systemctl enable myservice3 --now
  6. Exécutez systemd-cgtop pour vérifier que les 3 services myservice1, myservice2 et myservice3 sont tous exécutés dans la même tranche.
  7. Utilisez la commande systemctl set-property pour définir CPUWeight pour myservice3 sur 800 :
    sudo systemctl set-property myservice3.service CPUWeight=800
  8. Vérifiez qu'un fichier de dépôt a été créé pour vous sous /etc/systemd/system.control/myservice3.service.d. Toutefois, vous ne devez pas modifier le fichier :
    cat /etc/systemd/system.control/myservice3.service.d/50-CPUWeight.conf
    # This is a drop-in unit file extension, created via "systemctl set-property"
    # or an equivalent operation. Do not edit.
    [Service]
    CPUWeight=800
    
  9. Assurez-vous que systemd recharge ses fichiers de configuration et redémarre tous les services :
    sudo systemctl daemon-reload
    sudo systemctl restart myservice1
    sudo systemctl restart myservice2
    sudo systemctl restart myservice3
  10. Exécutez la commande systemd-cgtop pour vérifier que la pondération de la CPU a été divisée comme prévu :
    systemd-cgtop
    Control Group                                         Tasks   %CPU   Memory  Input/s Output/s
    /                                                       235  200.0   706.1M        -        -
    my_custom_slice2.slice                                   12  198.4     2.9M        -        -
    my_custom_slice2.slice/myservice3.service                 4  112.7   976.0K        -        -
    my_custom_slice2.slice/myservice2.service                 4   56.9   996.0K        -        -
    my_custom_slice2.slice/myservice1.service                 4   28.8   988.0K        -        -
    user.slice                                               18    0.9    44.1M        -        -
    user.slice/user-1001.slice                                6    0.9    13.9M        -        -
    user.slice/user-1001.slice/session-2.scope                4    0.9     9.5M        -        -