Tuto 3 done
This commit is contained in:
parent
15236db9af
commit
8c402e6d65
15 changed files with 604 additions and 310 deletions
|
|
@ -1,50 +1,123 @@
|
|||
\newpage
|
||||
|
||||
Utiliser les *cgroup*s
|
||||
======================
|
||||
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. Par exemple, il est possible leur imposer des limites d'utilisation
|
||||
de ressources ou d'altérer leur comportement.
|
||||
sur des **groupes de processus** (voire même, des threads !) et de leur
|
||||
attribuer des propriétés. Il est par exemple possible de leur imposer des
|
||||
limites d'utilisation de ressources ou d'altérer leur comportement : quantité
|
||||
de RAM, temps CPU, bande passante, ...
|
||||
|
||||
Apparue dès [Linux
|
||||
2.6.24](https://kernelnewbies.org/Linux_2_6_24#Task_Control_Groups)
|
||||
(en 2008 !), les *cgroup*s sont répartis en différents sous-systèmes
|
||||
(*subsystem*), chacun étant responsable d'un type de ressources
|
||||
spécifique :
|
||||
|
||||
## Premiers tests
|
||||
- [`blkio` (`io` dans la v2)
|
||||
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/blkio-controller.html)
|
||||
limites et statistiques de bande passante sur les disques ;
|
||||
- `cpu` : cycles CPU minimum garantis ;
|
||||
- [`cpuacct` (inclus dans `cpu` dans la v2)
|
||||
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpuacct.html)
|
||||
statistiques du temps CPU utilisé ;
|
||||
- [`cpuset`
|
||||
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/cpusets.html)
|
||||
associe des tâches à un/des CPU particuliers (par exemple pour dédier un cœur
|
||||
du CPU à un programme, qui ne pourra alors utiliser que ce CPU et pas les
|
||||
autres) ;
|
||||
- [`devices`
|
||||
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/devices.html)
|
||||
règles de contrôle de création (`mknod`) et d'accès aux périphériques ;
|
||||
- [`freezer`
|
||||
:](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/freezer-subsystem.html)
|
||||
pour suspendre et reprendre l'exécution d'un groupe de tâches ;
|
||||
- [`hugetlb` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/hugetlb.html) statistiques et limitation de l'usage de la fonctionnalité `HugeTLB` (permettant d'obtenir des pages mémoires plus grande que 4 kB) ;
|
||||
- [`memory` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/memory.html) statistiques et limitation d'usage de la mémoire vive et de la *swap* ;
|
||||
- [`net_cls` (v1 seulement) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/net_cls.html) applique un `classid` à tous les paquets émis par les tâches du *cgroup*, pour filtrage par le pare-feu en sortie ;
|
||||
- [`net_prio` (v1 seulement) :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/net_prio.html) surcharge la valeur de l'option de priorité `SO_PRIORITY`, ordonant la file d'attente des paquets sortants ;
|
||||
- [`pids` :](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/pids.html) statistiques et limitation du nombre de processus ;
|
||||
- ...
|
||||
|
||||
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.
|
||||
permet d'interrompre l'exécution d'un groupe de processus, puis de la reprendre
|
||||
lorsqu'on le décide.
|
||||
|
||||
|
||||
### Montage du *cgroup*
|
||||
### Montage du *freezer*
|
||||
|
||||
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 :
|
||||
En fonction de la configuration de votre système, vous allez vous trouver dans
|
||||
l'une de ces trois situations :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
mkdir /sys/fs/cgroup/freezer/
|
||||
mount -t cgroup -o freezer none /sys/fs/cgroup/freezer/
|
||||
```
|
||||
</div>
|
||||
- Votre dossier `/sys/fs/cgroup` contient à la fois des fichiers `cgroup.*` et
|
||||
éventuellement des dossiers : vous avez une distribution moderne qui utilise
|
||||
la nouvelle version des `cgroup`s.
|
||||
|
||||
Cette dernière commande monte l'arborescence de groupes relative à ce *cgroup*
|
||||
*freezer*. Tous les dossiers contenus dans cette racine sont donc des
|
||||
sous-groupes.
|
||||
- Votre dossier `/sys/fs/cgroup` contient d'autres dossiers au nom des
|
||||
sous-systèmes que l'on a listé ci-dessus : il s'agit des `cgroup`s v1.
|
||||
|
||||
- Votre dossier `/sys/fs/cgroup` est vide ou inexistant, vous pouvez choisir
|
||||
d'utiliser la version de votre choix :
|
||||
|
||||
Pour utiliser la v1 :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
mkdir /sys/fs/cgroup/freezer/
|
||||
mount -t cgroup -o freezer none /sys/fs/cgroup/freezer/
|
||||
```
|
||||
</div>
|
||||
|
||||
|
||||
Pour utiliser la v2 :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
mkdir /sys/fs/cgroup/
|
||||
mount -t cgroup2 none /sys/fs/cgroup/
|
||||
```
|
||||
</div>
|
||||
|
||||
::::: {.question}
|
||||
Avant d'aller plus loin, notez que les exemples seront donnés pour les deux
|
||||
versions des `cgroup`s à chaque fois.
|
||||
|
||||
La principale différence entre les deux est la fusion des différents
|
||||
sous-systèmes au sein d'une même arborescence. Dans la première version, chaque
|
||||
sous-système disposait de sa propre arborescence et il fallait créer les
|
||||
groupes et associer les tâches pour chaque sous-système. Avec la seconde
|
||||
version, une seule création est nécessaire, quelque soit le nombre de
|
||||
sous-systèmes que l'on souhaite utiliser.
|
||||
:::::
|
||||
|
||||
|
||||
### Création d'un nouveau groupe
|
||||
|
||||
La première étape dans l'utilisation d'un *cgroup* est de créer un groupe.
|
||||
Les *cgroup*s sont organisé autour d'une arborescence de groupe, où chaque
|
||||
groupe est représenté par un dossier. Il peut bien évidemment y avoir des
|
||||
sous-groupes, en créant des dossiers dans les dossiers existants, etc.\
|
||||
|
||||
La première étape dans l'utilisation d'un *cgroup* est donc de créer un groupe.
|
||||
|
||||
Pour ce faire, il suffit de créer un nouveau dossier dans un groupe existant,
|
||||
par exemple la racine :
|
||||
par exemple la racine.
|
||||
|
||||
On commence par se rendre à la racine :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
mkdir /sys/fs/cgroup/freezer/virli/
|
||||
ls /sys/fs/cgroup/freezer/virli/
|
||||
cd /sys/fs/cgroup/freezer/ # v1
|
||||
cd /sys/fs/cgroup/ # v2
|
||||
```
|
||||
</div>
|
||||
|
||||
Puis on crée notre groupe :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
mkdir virli
|
||||
ls virli/
|
||||
```
|
||||
</div>
|
||||
|
||||
|
|
@ -53,19 +126,50 @@ Nous avons maintenant un nouveau groupe de processus `virli` dans le *cgroup*
|
|||
propriétés de son (ses) père(s).
|
||||
|
||||
|
||||
### Sélection de contrôleur (v2 seulement)
|
||||
|
||||
Du fait de l'unification de tous les sous-systèmes, si vous utilisez la seconde
|
||||
version, vous allez devoir activer le ou les contrôleurs dont vous avez besoin
|
||||
(tandis que dans la première version, on se rendait dans l'arborescence du
|
||||
sous-système que l'on voulait).
|
||||
|
||||
Pour activer le contrôleur *memory* dans notre groupe `virli`, nous utilisons
|
||||
la commande suivante :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
echo "+memory" > virli/cgroup.subtree_control
|
||||
```
|
||||
</div>
|
||||
|
||||
::::: {.warning}
|
||||
Si vous obtenez l'erreur `No such file or directory`, c'est sans doute que vous
|
||||
avez les `cgroup`s v1 activé quelque part. Vous devriez plutôt utiliser la
|
||||
première version, le fait qu'elle soit active empêche l'utilisation de la v2 en
|
||||
parallèle.
|
||||
:::::
|
||||
|
||||
On peut contrôler les contrôleurs actifs en consultant le fichier
|
||||
`virli/cgroup.controllers`.
|
||||
|
||||
Le contrôleur *freezer* est activé par défaut, il n'y a pas besoin de
|
||||
l'activer.
|
||||
|
||||
|
||||
### Rattachement de processus
|
||||
|
||||
Pour le moment, ce nouveau groupe ne contient aucune tâche.
|
||||
Pour le moment, ce nouveau groupe ne contient aucun processus, comme le montre
|
||||
le fichier `cgroup.procs` de notre groupe. Ce fichier contient la liste des
|
||||
processus rattachés à notre *cgroup*.
|
||||
|
||||
Ouvrons un nouveau terminal (c'est lui que l'on va geler), 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 :
|
||||
Pour ajouter une tâche à ce groupe, cela se passe de cette manière :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
echo $PID > /sys/fs/cgroup/freezer/virli/tasks
|
||||
echo $PID > /sys/fs/cgroup/{,freezer/}virli/cgroup.procs
|
||||
```
|
||||
</div>
|
||||
|
||||
|
|
@ -75,7 +179,7 @@ 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 *cgroup*s).
|
||||
|
||||
Malgré l'utilisation de la redirection `>` (et non `>>`), il s'agit belle et
|
||||
Malgré l'utilisation de la redirection `>` (et non `>>`), il s'agit bel et
|
||||
bien d'un ajout au fichier et non d'un écrasement. Il faut garder en tête que
|
||||
le système de fichier est entièrement simulé et que certains comportements sont
|
||||
adaptés.
|
||||
|
|
@ -84,15 +188,15 @@ adaptés.
|
|||
### Consultation de l'état
|
||||
|
||||
En affichant le contenu du dossier `virli`, nous pouvions 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.
|
||||
celui-ci contenait déjà un certain nombre de fichiers. Certains 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\
|
||||
`/sys/fs/cgroup/freezer/virli/freezer.state`.
|
||||
`/sys/fs/cgroup/freezer/virli/freezer.state` ou `/sys/fs/cgroup/virli/cgroup.freeze`.
|
||||
|
||||
Pour plus d'information sur les différents fichiers présents dans ce *cgroup*,
|
||||
Pour plus d'informations sur les différents fichiers présents dans ce *cgroup*,
|
||||
consultez
|
||||
[la documentation associée](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v1/freezer-subsystem.html).
|
||||
|
||||
|
|
@ -113,7 +217,8 @@ calcul à notre shell et ses fils :
|
|||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
echo FROZEN > /sys/fs/cgroup/freezer/virli/freezer.state
|
||||
echo FROZEN > /sys/fs/cgroup/freezer/virli/freezer.state # v1
|
||||
echo 1 > /sys/fs/cgroup/virli/cgroup.freeze # v2
|
||||
```
|
||||
</div>
|
||||
|
||||
|
|
@ -122,57 +227,30 @@ l'exécution :
|
|||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
echo THAWED > /sys/fs/cgroup/freezer/virli/freezer.state
|
||||
echo THAWED > /sys/fs/cgroup/freezer/virli/freezer.state # v1
|
||||
echo 0 > /sys/fs/cgroup/virli/cgroup.freeze # v2
|
||||
```
|
||||
</div>
|
||||
|
||||
|
||||
## Exercice : script de monitoring
|
||||
### Exercice : script de monitoring {- #script-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) :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
docker container run --name mytsdb -d -p 8086:8086 influxdb
|
||||
```
|
||||
</div>
|
||||
|
||||
Il nous faut ensuite créer une base de données pour y stocker nos
|
||||
métriques. Voici comment on s'était débrouillé dans un précédent TP pour
|
||||
interagir avec InfluxDB :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
docker container exec -i mytsdb influx <<EOF
|
||||
CREATE DATABASE metrics;
|
||||
SHOW DATABASES;
|
||||
EOF
|
||||
```
|
||||
</div>
|
||||
|
||||
Vérifiez que la base de données `metrics` a bien été créée.
|
||||
|
||||
|
||||
### Monitoring instantané vers la console
|
||||
données des statistiques issues des *cgroup*s, tel `telegraf`.
|
||||
|
||||
Dans un premier temps, commençons par afficher dans la console, la quantité de
|
||||
mémoire utilisée par le groupe monitoré.
|
||||
|
||||
::::: {.code}
|
||||
Vous pouvez utiliser un programme comme
|
||||
[`memhog`](https://virli.nemunai.re/memhog.c) pour remplir rapidement votre
|
||||
mémoire.
|
||||
:::::
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
42sh# mkdir /sys/fs/cgroup...
|
||||
42sh$ echo $$ | sudo tee /sys/fs/cgroup.../tasks
|
||||
42sh$ echo $$ | sudo tee /sys/fs/cgroup.../cgroup.procs
|
||||
42sh# ./monitor group_name memhog 500
|
||||
~~~ 13595 ~~~ Current memory usage: 75194368/550502400 (13%)
|
||||
~~~ 13595 ~~~ Current memory usage: 150290432/550502400 (27%)
|
||||
|
|
@ -185,79 +263,26 @@ mémoire.
|
|||
```
|
||||
</div>
|
||||
|
||||
::::: {.warning}
|
||||
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
|
||||
### Fixer des limites {#Fixer-des-limites}
|
||||
|
||||
Maintenant, envoyons nos données vers la base
|
||||
<https://docs.influxdata.com/influxdb/v1.6/guides/writing_data/> :
|
||||
|
||||
<div lang="en-US">
|
||||
```bash
|
||||
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)"
|
||||
```
|
||||
</div>
|
||||
|
||||
Pour vérifier que les données ont bien été ajoutées, nous pouvons effectuer la
|
||||
requête suivante dans notre client `influx` :
|
||||
|
||||
<div lang="en-US">
|
||||
```sql
|
||||
SELECT * from "$my_cgroup_name";
|
||||
```
|
||||
</div>
|
||||
|
||||
|
||||
### 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/html/latest/admin-guide/cgroup-v1/index.html>
|
||||
|
||||
|
||||
### 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) *cgroup*s et lui attribuer les
|
||||
bons droits, tandis que le deuxième va effectuer le monitoring, sans privilèges
|
||||
particuliers.
|
||||
|
||||
#### Exemple
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
42sh$ sudo ./monitor_init my_cgroup_name
|
||||
42sh$ ./monitor my_cgroup_name memhog 500
|
||||
```
|
||||
</div>
|
||||
|
||||
|
||||
## Fixer des limites
|
||||
|
||||
Au delà de la simple consultation, les *cgroup*s peuvent servir à limiter la
|
||||
quantité de ressources mise à disposition à un groupe de processus.
|
||||
Au-delà de la simple consultation, les *cgroup*s peuvent servir à limiter la
|
||||
quantité de ressources mises à disposition à un groupe de processus.
|
||||
|
||||
Pour définir une limite, nous allons écrire la valeur dans le fichier
|
||||
correspondant à une valeur limite, comme par exemple
|
||||
`memory.max_usage_in_bytes`, qui limite le nombre d'octets que notre groupe de
|
||||
processus va pouvoir allouer au maximum :
|
||||
`memory.max_usage_in_bytes`/`memory.max`, qui limite le nombre d'octets que
|
||||
notre groupe de processus va pouvoir allouer au maximum :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
# cgroup v1
|
||||
42sh$ cat /sys/fs/cgroup/memory/virli/memory.max_usage_in_bytes
|
||||
0
|
||||
# 0 = Aucune limite
|
||||
|
|
@ -268,21 +293,26 @@ processus va pouvoir allouer au maximum :
|
|||
```
|
||||
</div>
|
||||
|
||||
Chaque *cgroup*s défini de nombreux indicateurs et possède de nombreux
|
||||
<div lang="en-US">
|
||||
```
|
||||
# cgroup v2
|
||||
42sh$ cat /sys/fs/cgroup/virli/memory.max
|
||||
max
|
||||
# max = Aucune limite
|
||||
42sh$ echo 4M > /sys/fs/cgroup/virli/memory.max
|
||||
# Maintenant, la limite est à 4MB, vérifions...
|
||||
42sh$ cat /sys/fs/cgroup/virli/memory.max
|
||||
4194304
|
||||
```
|
||||
</div>
|
||||
|
||||
Chaque *cgroup*s définit de nombreux indicateurs et possède de nombreux
|
||||
limiteurs, n'hésitez pas à consulter la documentation associée à chaque
|
||||
*cgroup*.
|
||||
|
||||
|
||||
## Pour aller plus loin {-}
|
||||
### Pour aller plus loin {-}
|
||||
|
||||
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 !
|
||||
|
||||
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/html/latest/admin-guide/cgroup-v2.html).
|
||||
Control groups](https://lwn.net/Articles/604609/) est excellente ! Plus [cet
|
||||
article sur la version 2](https://lwn.net/Articles/679786/).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue