216 lines
6.5 KiB
Markdown
216 lines
6.5 KiB
Markdown
\newpage
|
|
|
|
Utiliser les *cgroup*s
|
|
======================
|
|
|
|
Les *cgroup*s (pour *Control Group*s) 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
|
|
*cgroup*s 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/
|
|
```
|
|
|
|
Vous avez 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, vous avez 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 *cgroup*s).
|
|
|
|
|
|
### 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 vous pouvez 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](https://www.kernel.org/doc/Documentation/cgroup-v1/freezer-subsystem.txt).
|
|
|
|
|
|
### 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 *cgroup*s.
|
|
|
|
|
|
### Rappel d'InfluxDB
|
|
|
|
Commençons par lancer le conteneur Docker d'InfluxDB (pour éviter de
|
|
l'installer sur notre machine) :
|
|
|
|
```shell
|
|
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 :
|
|
|
|
```sql
|
|
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, vous pouvez effectuez la
|
|
requête suivante dans l'interface web d'InfluxDB :
|
|
|
|
```sql
|
|
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é ;
|
|
* ...
|
|
|
|
<https://www.kernel.org/doc/Documentation/cgroup-v1/>
|
|
|
|
|
|
### Permettre à l'utilisateur de monitorer des processus
|
|
|
|
Maintenant, séparer votre 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) *cgroup*s 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
|
|
|
|
Depuis les noyaux 4.5, il est possible d'utiliser la nouvelle version du
|
|
pseudo système de fichiers des *CGroup*s. Le principal changement vient du
|
|
regroupement au sein d'une seule hiérarchie des différents *CGroup*s que l'on
|
|
avait dans la v1. Davantage d'informations sont disponibles :
|
|
|
|
* [Understanding the new control groups API](https://lwn.net/Articles/679786/)
|
|
;
|
|
* [Kernel Document about Control Group v2](https://www.kernel.org/doc/Documentation/cgroup-v2.txt).
|
|
|
|
Pour tout connaître en détails, [la série d'articles de Neil Brown sur les
|
|
Control groups](https://lwn.net/Articles/604609/) est excellente !
|