Tuto 1 done

This commit is contained in:
nemunaire 2015-10-08 03:48:26 +02:00
parent 76495b9045
commit 49c5a27885
5 changed files with 327 additions and 116 deletions

View File

@ -1,35 +1,172 @@
\newpage \newpage
# Utiliser les *cgroups* # 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 ## 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, monter-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 des sous-groupes de
cette dernière.
### Création d'un nouveau groupe ### 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 ### Rattachement de processus
### Consultatation de l'état 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 (dans ce *cgroup*, il ne bouge pas
dans les autres *cgroup*s).
### Consultation de l'état
En affichant le contenu du dossier `virli`, nous avons pu 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, accessible ici :
<https://www.kernel.org/doc/Documentation/cgroups/freezer-subsystem.txt>
### Changement d'état ### 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
```
## Script de monitoring ## Script de monitoring
### Monitoring instantanné vers la console À nous maintenant de concevoir un script qui va enregistrer vers la base de
données créée (*metrics*) dans la partie précédente, des statistiques issues
des *cgroup*s.
#### Option pour choisir l'intervalle de polling ### 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.
### Monitoring vers InfluxDB ### Monitoring vers InfluxDB
Maintenant, envoyons nos données vers la base
<https://influxdb.com/docs/v0.9/guides/writing_data.html> :
```
curl -i -XPOST 'http://172.23.42.2: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 sont bien ajoutées, vous pouvez effectuez 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é ;
* ...
<https://www.kernel.org/doc/Documentation/cgroups/>
### Permettre à l'utilisateur de monitorer des process ### Permettre à l'utilisateur de monitorer des process
#### Séparer en deux scripts Maintenant, séparer votre script en deux parties afin qu'un utilisateur normal
(non-root) puisse utiliser la partie monitoring de notre script.
#### Ajouter les bonnes capabilities sur le premier 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
#### Rendre ok avec les exécutions concurrentes du second script #### Exemple
### Monitorer chaque fils indépendamment ```
42sh# ./monitor_init my_cgroup_name
42sh$ ./monitor my_cgroup_name memhog 500
```
## Rendu ## Rendu
@ -37,14 +174,15 @@
### Script de monitoring ### Script de monitoring
Rendez la révision la plus avancées de vos scripts de monitoring de process via Rendez la révision la plus avancées de vos scripts de monitoring de process via
les *cgroups*. les *cgroup*s.
### Questions ### Questions
1. Un même processus peut-il être dans plusieurs cgroups de type différents (freezer et cpuacct par exemple) ? 1. Un même processus peut-il être dans plusieurs *cgroup*s de type différents
(freezer et cpuacct par exemple) ?
1. Que sera-t-il possible de limiter via un nouveau cgroup dans la prochaine 1. Que sera-t-il possible de limiter via un nouveau *cgroup* dans la prochaine
version du noyau (4.3) ? version du noyau (4.3) ?
1. Comment peut-on limiter le nombre de processus lancés par un utilisateur ou 1. Actuellement, comment peut-on limiter le nombre de processus lancés par un
un groupe ? utilisateur ou un groupe ?

View File

@ -4,8 +4,8 @@
## Noyau Linux ## Noyau Linux
Ce TP requiert d'avoir un noyau Linux en version 3.8 au minimum. De plus, il Ce TP requiert un noyau Linux 3.8 au minimum. De plus, il doit être
doit être compilé avec les options suivantes : compilé avec les options suivantes :
``` ```
General setup ---> General setup --->
@ -29,6 +29,8 @@ General setup --->
Networking options ---> Networking options --->
<*> 802.1d Ethernet Bridging <*> 802.1d Ethernet Bridging
<M> 802.1Q VLAN Support <M> 802.1Q VLAN Support
[*] Network priority cgroup
[*] Network classid cgroup
Device Drivers ---> Device Drivers --->
[*] Network device support ---> [*] Network device support --->
<M> MAC-VLAN support <M> MAC-VLAN support
@ -45,8 +47,9 @@ la configuration de votre noyau en utilisant la commande `lxc-checkconfig`.
## LXC ## LXC
Pour installer LXC, utilisez le gestionnaire de paquets de votre Pour installer LXC, utilisez le gestionnaire de paquets de votre
distribution. Toute les bonnes distributions fournissent un paquet `lxc`. distribution. Toute les bonnes distributions fournissent un paquet
`lxc`. Vérifiez que la version installée est au moins la 1.0.
Aucune configuration ne devrait vous être demandé durant l'installation. Une Aucune configuration ne devrait vous être demandé durant l'installation. Une
fois l'installation terminée, exécutez la commande `lxc-checkconfig` pour fois installé, exécutez la commande `lxc-checkconfig` pour vérifier que votre
vérifier que votre noyau possède bien toutes les options nécessaires. noyau possède bien toutes les options nécessaires.

View File

@ -1,30 +1,34 @@
\newpage \newpage
# Utiliser LXC # Utiliser `lxc`
Le but de cette première partie est d'appréhender la virtualisation légère au Le but de cette première partie est d'appréhender la virtualisation légère au
travers d'un programme, `lxc`, qui va mettre en place pour nous un travers d'un programme, `lxc`, qui va mettre en place pour nous tout un
environnement distinct. environnement distinct.
## Lancer un conteneur ## Lancer un conteneur
Avec le paquet LXC que vous avez installé, vous avez également récupéré un Avec le paquet `lxc` que nous avons précédemment installé, nous avons également
certain nombre de modèles de système (souvent installés dans le dossier récupéré un certain nombre de *modèles* de système (souvent installés dans le
`/usr/share/lxc/templates/`). dossier `/usr/share/lxc/templates/`) : il s'agit d'une suite de commandes
(principalement des `wget`, `chroot` ou `debootstrap`) permettant d'obtenir un
système basic fonctionnel, en suivant les étapes d'installation habituelle de
la distribution.
La méthode la plus simple pour lancer un conteneur LXC est d'utiliser l'un de La méthode la plus simple pour lancer un conteneur `lxc` est d'utiliser l'un de
ces modèles qui va installer tout un environnement pour vous. On utilise pour ces modèles pour obtenir un nouveau système. On utilise pour cela la commande
cela la commande `lxc-create` : `lxc-create` :
``` ```
lxc-create --name toto_first --template ubuntu lxc-create --name toto_first --template debian
``` ```
Ce modèle va créer un dossier dans `/var/lib/lxc/` portant le nom que vous avez Ce modèle va créer un dossier dans `/var/lib/lxc/` (pouvant varier d'une
précisé. Ce dossier va contenir la configuration LXC du conteneur (`config`), distribution à l'autre) portant le nom que nous avons précisé. Ce dossier va
la table des partitions (`fstab`) s'il y a besoin de faire des montages contenir la configuration `lxc` du conteneur (`config`), la table des
particuliers et enfin le dossier `rootfs` contenant le système en lui-même. partitions (`fstab`) s'il y a besoin de faire des montages particuliers et
enfin le dossier `rootfs` contenant le système en lui-même.
Une fois l'installation terminée, on peut démarrer le conteneur : Une fois l'installation terminée, on peut démarrer le conteneur :
@ -32,86 +36,147 @@ Une fois l'installation terminée, on peut démarrer le conteneur :
lxc-start --name toto_first lxc-start --name toto_first
``` ```
LXC va appeler `/sbin/init` et démarrer tous les services que l'on peut `lxc` va appeler `/sbin/init` et démarrer tous les services que l'on peut
s'attendre à trouver dans n'importe quelle machine virtuelle plus classique (la s'attendre à trouver dans n'importe quelle machine virtuelle (et même physique)
seule différence réside donc dans le fait que le noyau est partagé avec plus classique (la seule différence réside donc dans le fait que le noyau est
l'hôte). partagé avec l'hôte).
Généralement on lance `lxc-start` avec l'option `--daemon`, car on ne s'attend Généralement on lance `lxc-start` avec l'option `--daemon`, car on n'a pas
pas à ce que la machine s'arrête lorsque l'on va quitter notre terminal. Dans vraiment envie d'avoir un conteneur bloquant un terminal. En mode daemon, on va
ce cas, utiliser la commande `lxc-console` pour vous attacher à votre utiliser la commande `lxc-console` pour nous attacher aux conteneurs. À tout
conteneur. À tout moment, vous pouvez vous détacher de la console (sans que moment, nous pouvons nous détacher de la console (sans que cela n'affecte
cela n'affecte l'état du conteneur) en pressant les touches : `^A q`. l'état du conteneur) en pressant les touches : `^A q`.
Connectez-vous, lancez quelques commandes puis éteignez la machine avec `sudo Connectons-nous, lancons quelques commandes puis éteignons la machine en
poweroff` dans le conteneur. Vous pouvez aussi lancer la commande `lxc-stop lançant la commande `poweroff` dans le conteneur. Il est également possible de
--name toto_first` dans un autre terminal, depuis la machine hôte. lancer la commande `lxc-stop --name toto_first` dans un autre terminal, depuis
la machine hôte.
## Le réseau ## Le réseau
Le modèle ubuntu que vous avez utilisé initialise un fichier de configuration Le modèle *Debian*, que nous avons utilisé, préremplit un fichier de
sans paramètres pour le réseau. Vous n'avez donc pas d'interface dans le configuration sans définir de paramètre pour le réseau. Il n'y a donc pas
conteneur pour le connecter au réseau. d'interface dans le conteneur pour le connecter :
Un excellent article détaillant les différents types de réseau est accessible à ```
lxc.network.type = empty
```
Un excellent article détaillant les différents types de configuration réseau
est accessible à
<https://blog.flameeyes.eu/2010/09/linux-containers-and-networking>. <https://blog.flameeyes.eu/2010/09/linux-containers-and-networking>.
N'ayant qu'une seule interface physique sur la machine et n'ayant pas accès à N'ayant qu'une seule interface physique sur la machine et n'ayant pas accès à
la configuration des VLAN de la pièce, il ne nous reste que deux méthodes pour la configuration des VLAN de la pièce, il ne nous reste que deux méthodes pour
obtenir du réseau dans nos conteneurs : Virtual Ethernet ou obtenir du réseau dans nos conteneurs : Virtual Ethernet ou MACVLAN.
MACVLAN. Malheureusement, ces deux méthodes nécessitent de mettre en place un
pont Ethernet sur votre machine :
### Installation du pont réseau
#### Bridge interface
#### Port forwarding
### Virtual Ethernet
Virtual Ethernet est la configuration la plus simple. On met en place un pont
sur la machine hôte, puis on crée une interface `veth` par conteneur que l'on
veut lancer. On n'oubliera pas d'ajouter ces interfaces au pont.
Voici un extrait de configuration correspondant au paramétrage d'une interface
`eth0` pour un conteneur donné :
```
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
```
Cette technique a pour inconvénient de laisser au noyau le soin de router les
paquets selon leur adresse IP, ce qui peut être lent et coûteux étant donné que
la carte est placé en mode de promiscuité.
### MACVLAN ### MACVLAN
Ici, le noyau va orienter les paquets en fonction de leur adresse MAC de Cette méthode est la plus simple : le noyau va orienter les paquets en fonction
destination. de leur adresse MAC de destination. Le conteneur sera donc comme une machine
supplémentaire sur le réseau.
Modifions notre fichier de configuration afin qu'il ressemble à quelque chose
comme :
``` ```
lxc.network.type = macvlan lxc.network.type = macvlan
lxc.network.macvlan.mode = bridge lxc.network.macvlan.mode = bridge
lxc.network.flags = up lxc.network.flags = up
lxc.network.link = br0 lxc.network.link = eth0
``` ```
Après avoir démarré le conteneur, il devrait avoir obtenu une IP du serveur
DHCP de l'école. L'inconvénient dans cette configuration est qu'il faille un
client netsoul dans chaque conteneur, puisque chacun est considéré comme une
machine différente aux yeux du routeur.
### Virtual Ethernet
Virtual Ethernet est la configuration la moins optimale, mais sans doute la
plus flexible.
Voici un extrait de configuration correspondant au paramétrage d'une interface
virtuelle pour un conteneur donné :
```
lxc.network.type = veth
lxc.network.ipv4 = 172.23.42.2/24
lxc.network.flags = up
```
Dans cette situation, au démarrage du conteneur, `lxc` va créer une interface
veth, avec un côté placé dans la machine hôte et l'autre côté placé dans le
conteneur. `lxc` configure l'interface dans le conteneur, il nous appartient
ensuite de configurer la machine hôte.
Commençons par attribuer une IP à cette nouvelle interface, en adaptant à votre
identifiant d'interface :
```
ip addr add 172.23.42.1/24 dev vethYJWD6R
```
À partir de là, nous devrions pouvoir pinger notre conteneur depuis notre
machine hôte : `ping 172.23.42.2`.
Notre conteneur ne peut cependant pas encore accéder à Internet. Pour cela, la
machine hôte doit faire office de routeur et donc router les paquets d'un
réseau à l'autre : en l'occurence, du réseau 172.23.42.1 vers Internet
via 10.0.0.0/8, le réseau de l'école.
Pour que notre machine hôte route les paquets, exécuter la commande :
```
sysctl -w net.ipv4.ip_forward=1
```
Cette variable, que nous retrouvons dans `/proc/sys/net/ipv4/ip_forward`,
indique au noyau qu'il peut faire passer les paquets réseau d'une interface à
l'autre. Sans plus de directives, les paquets vont conserver leur adresse
source (172.23.42.2 pour les paquets en provenance du conteneur). Cette adresse
est une adresse privée, non routable sur Internet, ni même par le bocal. Il
faut donc ajouter une couche de NAT/PAT pour réécrire les adresses sources
avant d'envoyer les paquets sur internet :
```
iptables -t nat -A POSTROUTING ! -o vethYJWD6R -s 172.23.42.0/24 -j MASQUERADE
```
Dernière étape, dans notre conteneur, nous devons indiquer la route à utiliser
pour accéder à internet :
```
ip route add default via 172.23.42.1
```
Nous avons maintenant internet dans notre conteneur !
## Utilisation du conteneur ## Utilisation du conteneur
### Redémarrage du conteneur ### Installation de InfluxDB
### Installation de InFluxDB et Graphana ```
apt-get update
apt-get install wget
wget https://s3.amazonaws.com/influxdb/influxdb_0.9.4.2_amd64.deb
dpkg -i influxdb_0.9.4.2_amd64.deb
```
### Test de l'installation ### Test de l'installation
```
/opt/influxdb/influxd
```
Une fois que le service est démarré, vous devriez pouvoir accéder à l'interface
à : <http://172.23.42.2:8083/>
Créons une nouvelle base de données "metrics", elle nous servira dans la partie suivante.
## Rendu ## Rendu
@ -130,11 +195,12 @@ installés.
### Questions ### Questions
1. Quel type de virtualisation réseau avez-vous utilisé ? pourquoi ?
1. Quels sont les autres types de virtualisation réseau existants ? Expliquez 1. Quels sont les autres types de virtualisation réseau existants ? Expliquez
en chacun une phrase leurs particularités. en chacun une phrase leurs particularités.
1. Quel fichier de configuration devriez-vous changer pour rendre persistante la
valeur d'`ip_forward` ?
1. Dans quel langage InfluxDB a-t-il était écrit ? Quelle est la particularité 1. Dans quel langage InfluxDB a-t-il était écrit ? Quelle est la particularité
des binaires générés par ce langage ? des binaires générés par ce langage ?
@ -143,6 +209,6 @@ installés.
virtualisation légère). virtualisation légère).
1. J'ai utilisé la méthode *Virtual Ethernet* pour relier mes conteneurs à 1. J'ai utilisé la méthode *Virtual Ethernet* pour relier mes conteneurs à
Internet, via un PAT (`br0`). Quelle(s) règle(s) `iptables` devrais-je Internet, via l'interface `br0`. Quelle(s) règle(s) `iptables` devrais-je
écrire sur mon hôte afin de permettre l'accès à InfluxDB depuis une autre écrire sur mon hôte afin de permettre l'accès à InfluxDB depuis une autre
machine ? machine ?

View File

@ -41,12 +41,12 @@ via votre interpréteur.
Les options attendues sont : Les options attendues sont :
* rejoindre un namespace IPC : `-i`, `--ipc` ; * rejoindre un *namespace* IPC : `-i`, `--ipc` ;
* rejoindre un namespace mount : `-m`, `--mount` ; * rejoindre un *namespace* mount : `-m`, `--mount` ;
* rejoindre un namespace net : `-n`, `--net` ; * rejoindre un *namespace* net : `-n`, `--net` ;
* rejoindre un namespace PID : `-p`, `--pid` ; * rejoindre un *namespace* PID : `-p`, `--pid` ;
* rejoindre un namespace UTS : `-u`, `--uts` ; * rejoindre un *namespace* UTS : `-u`, `--uts` ;
* rejoindre un namespace user : `-U`, `--user`. * rejoindre un *namespace* user : `-U`, `--user`.
### Exemples ### Exemples
@ -127,3 +127,7 @@ expliquant comment s'en servir.
Vous devez donc rendre 3 fichiers : `cmpns` ou `cmpns.tar.bz2`, `setns` ou Vous devez donc rendre 3 fichiers : `cmpns` ou `cmpns.tar.bz2`, `setns` ou
`setns.tar.bz2` et `mlc` ou `mlc.tar.bz2`. `setns.tar.bz2` et `mlc` ou `mlc.tar.bz2`.
\vspace{3em}
Bon courage !

View File

@ -6,10 +6,10 @@ Le but de ce premier TP est d'utiliser les commandes et les appels systèmes vu
durant le cours. durant le cours.
Tous les éléments de ce TP (exercices et questions) sont à rendre à Tous les éléments de ce TP (exercices et questions) sont à rendre à
<virli@nemunai.re> au plus tard le mercredi 21 octobre 2015 à 23 h 42. Consultez la <virli@nemunai.re> au plus tard le **mercredi 21 octobre 2015 à 23
dernière section de chaque partie pour plus d'information sur les éléments à h 42**. Consultez la dernière section de chaque partie pour plus d'information
rendre. Vous pouvez placer les réponses aux questions dans le corps du courriel sur les éléments à rendre. Vous pouvez placer les réponses aux questions dans
ou dans un fichier joint. le corps du courriel ou dans un fichier texte joint.
En tant que personnes sensibilisées à la sécurité des échanges électroniques, En tant que personnes sensibilisées à la sécurité des échanges électroniques,
vous devriez m'envoyer vos rendus signés avec votre clef PGP. Pensez à vous devriez m'envoyer vos rendus signés avec votre clef PGP. Pensez à