virli/tutorial/3/cgroups.md

6.6 KiB

\newpage

Utiliser les cgroups

Les cgroups (pour Control Groups) permettent de collecter des statistiques sur des groupes de processus (appelés tâches) et de leur attribuer des propriétés, comme par exemple pour leur imposer des limitations d'utilisation de ressources ou altérer leurs priorités.

Premiers tests

Nous allons commencer par faire quelques tests avec le cgroup freezer, qui permet d'interrompre l'exécution d'un groupe de processus et de la reprendre.

Montage du cgroup

En fonction de la configuration de votre système, il est possible que les cgroups ne soient pas montés au démarrage dans /sys/fs/cgroup/. Si vous n'avez pas de dossier freezer ou si celui-ci est vide, montez-le en suivant la procédure suivante :

mkdir /sys/fs/cgroup/freezer/
mount -t cgroup -o freezer none /sys/fs/cgroup/freezer/

Cette dernière commande monte le groupe de processus racine, pour le cgroup freezer. Tous les dossiers contenu dans cette racine sont donc des sous-groupes.

Création d'un nouveau groupe

La première étape dans l'utilisation d'un cgroup est de créer un nouveau groupe.

Pour créer un groupe, il suffit de créer un nouveau dossier dans un groupe existant, par exemple la racine :

mkdir /sys/fs/cgroup/freezer/virli/
ls /sys/fs/cgroup/freezer/virli/

Nous avons maintenant un nouveau groupe de processus virli dans le cgroup Freezer. Comme il s'agit d'une hiérarchie, le groupe virli hérite des propriétés de son (ses) père(s).

Rattachement de processus

Pour le moment, ce nouveau groupe ne contient aucune tâche.

Ouvrons un nouveau terminal (c'est lui que l'on va freezer), et récupérons son PID : echo $$.

La liste des processus rattachés à un cgroup se trouve dans le fichier task du groupe. Pour ajouter une tâche à ce groupe, cela se passe de cette manière :

echo $PID > /sys/fs/cgroup/freezer/virli/tasks

Il faut ici remplacer $PID par le PID du shell que l'on a relevé juste avant.

En validant cette commande, nous avons déplacé le processus dans ce groupe, il n'est alors plus dans aucun autre groupe (pour ce cgroup, il ne bouge pas dans les autres cgroups).

Consultation de l'état

En affichant le contenu du dossier virli, nous pouvons constater que celui-ci contenait déjà un certain nombre de fichiers. Certain d'entre-eux sont en lecture seule et permettent de lire des statistiques instantanées sur le groupe ; tandis que d'autres sont des propriétés que nous pouvons modifier.

Nous pouvons consulter l'état de gel du groupe en affichant le contenu du fichier\newline /sys/fs/cgroup/freezer/virli/freezer.state.

Pour plus d'information sur les différents fichiers présents dans ce cgroup, consulter la documentation associée.

Changement d'état

Faisons exécuter à notre interpréteur une commande pour voir effectivement l'exécution s'arrêter. Si vous manquez d'inspiration, utilisez :

for i in $(seq 9999); do echo -n $i; sleep .1; echo -n " - "; sleep .1; done

Maintenant, nous avons donné l'ordre au noyau de ne plus allouer de temps de calcul à notre shell et ses fils :

echo FROZEN > /sys/fs/cgroup/freezer/virli/freezer.state

À cet instant, vous devriez voir votre compteur s'arrêter. Pour reprendre l'exécution :

echo THAWED > /sys/fs/cgroup/freezer/virli/freezer.state

Exercice : script de monitoring

À nous maintenant de concevoir un script qui va enregistrer vers une base de données des statistiques issues des cgroups.

Rappel d'InfluxDB

Commençons par lancer le conteneur Docker d'InfluxDB (pour éviter de l'installer sur notre machine) :

docker run -d -p 8086:8086 -p 8083:8083 influxdb

Il nous faut ensuite créer une base de données pour y stocker les métriques, rendez-vous à http://localhost:8083/ puis entrez la requête :

CREATE DATABASE metrics;

Monitoring instantané vers la console

Dans un premier temps, commençons par afficher dans la console la quantité de mémoire utilisée par le groupe monitoré.

  • Arguments de la ligne de commande :
    • premier fils à lancer dans le groupe,
    • intervalle de temps entre deux rafraîchissement ;
  • cgroup memory;
  • memory.usage_in_bytes.

Vous pouvez utiliser un programme comme memhog pour remplir rapidement votre mémoire.

Si vous n'avez pas le cgroup memory, il est possible qu'il ne soit pas activé par défaut par votre système. Si vous êtes dans ce cas, essayez d'ajouter cgroup_enable=memory à la ligne de commande de votre noyau.

Monitoring vers InfluxDB

Maintenant, envoyons nos données vers la base https://docs.influxdata.com/influxdb/v1.0/guides/writing_data/ :

curl -i -XPOST 'http://localhost:8086/write?db=metrics' --data-binary \
    "$my_cgroup_name memory.usage_in_bytes=$(cat .../my_cgroup_name/memory.usage_in_bytes)"

Pour vérifier que les données ont bien été ajoutées, nous pouvons effectuer la requête suivante dans l'interface web d'InfluxDB :

SELECT * from "$my_cgroup_name";

Monitorer davantage de données

Liste non exhaustive de données à monitorer :

  • Nombre d'IOs effectué ;
  • nombre d'octets lu/écrit sur les disques ;
  • temps de calcul utilisé ;
  • trafic réseau généré ;
  • ...

Tous les cgroups existants dans le dernier noyau publié ont leur documentation accessible ici : https://www.kernel.org/doc/Documentation/cgroup-v1/

Permettre à l'utilisateur de monitorer des processus

Maintenant, séparons notre script en deux parties afin qu'un utilisateur normal (non-root) puisse utiliser la partie monitoring de notre script.

Un premier script doit s'occuper de créer le(s) cgroups et lui attribuer les bons droits, tandis que le deuxième va utiliser effectuer le monitoring, sans privilèges particuliers.

Exemple

42sh$ sudo ./monitor_init my_cgroup_name
42sh$ ./monitor my_cgroup_name memhog 500

Pour aller plus loin

Pour tout connaître en détails, la série d'articles de Neil Brown sur les Control groups est excellente !

Depuis les noyaux 4.5, il est possible d'utiliser la nouvelle version du pseudo système de fichiers des CGroups. Le principal changement vient du regroupement au sein d'une seule hiérarchie des différents CGroups que l'on avait dans la v1. Davantage d'informations sont disponibles :