samedi 2 avril 2011

Virtualisation en français facile: les conteneurs

Bien que cette approche de la virtualisation soit possible non seulement sur les systèmes Linux mais aussi sur des OS de la famille Unix et BSD, je ne ferai dans cet article que référence à Linux que je connais mieux.

Cette technique de virtualisation repose sur le cloisonnement des applications et des ressources qui leur sont affectées constituant ainsi de sorte de machines virtuelles indépendantes et isolées les unes des autres.
Pour comprendre ce qui se passe sous le capot, je vais décrire ici une approche d'isolation d'applications utilisée.

Sur un système Linux, chaque programme qui s'exécute est représentée en mémoire sous la forme d'une structure de donnée appellé PCB (Process Control Block) qui contient entre autres, les informations suivantes:
  • l'état du programme (en cours d'exécution, en attente d'une lecture/écriture mémoire ou disque, en veille, etc),
  • le contenu des régistres du processeur concernant ce programme (processus),
  • les limites de la mémoire attribué à ce processus,
  • la liste des périphériques d'entrée/sortie alloués au processus,
  • la liste des fichiers ouverts attribué à ce processus (n'oubliez pas ce que je vous ai dit dans un précédent article : sur linux, tout est vue suivant l'abstration de fichiers),
  • etc
Ces informations définissent la « vue » qu'à le processus du système d'exploitation dans lequel il tourne.

De l'autre côté, les processus sous linux sont organisés sous forme d'arbre, les noeuds fils représentant des processus fils et les noeuds parents les processus parents; le processus initial est crée juste à la fin du démarrage du système d'exploitation (en fin d'article, j'indique des ressources expliquant la séquence de démarrage d'un système Linux).

Un processus fils est crée par clonage du processus parent et se voit ensuite attribuer un ID (grosso modo). Il hérite donc de la « vue » de son parent (et donc voit l'environnement dans lequel il s'exécute de la même façon que son parent). Cette propriété signifie que, à moins qu'on attribue à ce processus un code différent, des périphériques d' E/S, des limitations d'accès mémoire et une liste de fichiers différentes, ce processus fils s'exécutera exactement dans les mêmes conditions que le processus qui l'a crée (son parent).

Une machine virtuelle sera alors constituée d'un processus parent (équivalent au processus initial appelé init, qui est le père de tous les processus sous les systèmes linux) qui se chargera de démarrer l'ensemble des applications constituant la machine virtuelle (un serveur web, un shell, un programme de gestion des connexions, etc).
Sur la figure précédente, chaque "isolateur" correspond à un processus init-like tel qu'exprimé par la formule:
machine virtuelle = processus (isolateur) + ses processus descendants fournissant les services effectifs de la machine virtuelle.

En fonction des besoins, cette technique peut s'accompagner de la mise en place d'un réseau virtuelle (on verra dans l'atelier de ce soir comment mettre ceci en oeuvre), des disques virtuels (de simples fichiers vus par le conteneur comme des disques à l'image de manipulation qu'on peut faire avec un "mount -o loop"), etc, constituant ainsi tous les composants nécessaires au fonctionnement de la machine virtuelle.

Sources:
[1] http://fr.wikipedia.org/wiki/Virtualisation
[2] http://fr.wikipedia.org/wiki/Linux-VServer
[3] http://fr.wikipedia.org/wiki/Chroot
[4] http://fr.wikipedia.org/wiki/BSD_Jail
[5] http://fr.wikipedia.org/wiki/OpenVZ
[6] http://veillard.com/Talks/SL09LinuxVirt.pdf