En guise d'introduction, je me permettrai simplement de paraphraser la page d'accueil du projet.
LXC est un ensemble d'outils en espace utilisateur permettant de contrôler les Linux Containers, un mécanisme léger de système virtuel parfois décrit comme « chroot gonflé aux stéroïdes ».
LXC implémente des systèmes virtuels complets en partant de chroot, en ajoutant des mécanismes de gestion des ressources et d'isolation à l'infrastructure de gestion de processus existante de Linux.
Les Linux Containers (lxc) implémentent :
- La gestion de ressources via les « groupes de contrôle de processus » (implémentés via le système de fichiers /cgroup) ;
- L'isolation de ressources via les nouveaux drapeaux (flags) de l'appel système clone(2) (capable de créer plusieurs types de nouveaux espaces de noms pour des choses telles que les PID et le routage réseau) ;
- Plusieurs mécanismes d'isolation additionnels (tels que le drapeau -o newinstance du système de fichiers devpts).
Le paquet LXC combine ces mécanismes du noyau Linux pour fournir un conteneur en espace utilisateur, un système virtuel léger avec une isolation et un contrôle des ressources complets pour une application ou un système entier.
Les Linux Containers prennent une approche complètement différente des technologies de virtualisation telles que KVM et Xen, qui ont débuté en bootant des systèmes virtuels séparés sur du matériel émulé et ensuite ont essayé de réduire leur surcharge (overhead) via la paravirtualisation et des mécanismes similaires. Au lieu d'améliorer l'efficacité d'une isolation complète, LXC se base sur un mécanisme efficace (la gestion de processus de Linux) et a ajouté l'isolation, résultant en un mécanisme de virtualisation évolutif et portable à la façon de chroot, capable de supporter simultanément des milliers de systèmes émulés sur un seul serveur, tout en fournissant des possibilités de virtualisation légère aux routeurs et aux smartphones.
L'objectif premier de ce projet est de rendre la vie plus facile aux développeurs noyau impliqués dans le projet des conteneurs (containers project) et spécialement de continuer à travailler sur les nouvelles fonctionnalités de Checkpoint/Restart. LXC est suffisamment petit pour gérer facilement un conteneur avec de simples lignes de commandes et assez complet pour être utilisé pour d'autres besoins.
1 Installation des outils
J'utilise la distribution CentOS 6 sur architecture 64 bits (6.3 à l'heure d'écrire ces lignes). Le paquet n'est pas disponible dans les dépôts standards, mais le fichier .spec est fourni dans les sources du projet. Nous allons donc utiliser l'outil d'empaquetage de la distribution pour créer notre propre paquet. Si vous n'avez jamais construit de paquet sur votre système, il faut que vous installiez rpmbuild et que vous créiez une arborescence minimale :
# yum install rpm-build
$ mkdir -p ~/rpmbuild/{SOURCES,SPECS}
Ensuite, nous téléchargeons les sources dans le répertoire adapté et extrayons le fichier .spec :
$ wget http://lxc.sourceforge.net/download/lxc/lxc-0.8.0.tar.gz \
-O ~/rpmbuild/SOURCES/lxc-0.8.0.tar.gz
$ tar -xzf ~/rpmbuild/SOURCES/lxc-0.8.0.tar.gz lxc-0.8.0/lxc.spec \
-O > ~/rpmbuild/SPECS/lxc.spec
Avant de pouvoir compiler, nous devons modifier légèrement le fichier .spec. En effet, celui-ci essaie par défaut d'activer la compatibilité avec AppArmor. Or, ce mécanisme de sécurité n'est pas disponible sur les distributions de la famille Red Hat qui lui préfèrent SELinux. Donc, utilisé tel quel, le fichier .spec générera une erreur. Le correctif est plutôt simple ; voyez vous-même :
--- lxc.spec 2012-12-21 19:16:24.709567814 +0100
+++ lxc.spec 2012-12-21 19:17:08.213817648 +0100
@@ -62,7 +62,7 @@
%prep
%setup
%build
-PATH=$PATH:/usr/sbin:/sbin %configure $args --disable-rpath
+PATH=$PATH:/usr/sbin:/sbin %configure $args --disable-rpath --disable-apparmor
make %{?_smp_mflags}
%install
$ patch ~/rpmbuild/SPECS/lxc.spec ~/rpmbuild/SPECS/lxc-0.8.0.spec.patch
Nous sommes maintenant prêts à compiler :
$ rpmbuild -ba --clean --define 'dist el6' ~/rpmbuild/SPECS/lxc.spec
Cette opération génère trois paquets RPM : lxc-0.8.0-1.el6.x86_64.rpm, lxc-devel-0.8.0-1.el6.x86_64.rpm, lxc-libs-0.8.0-1.el6.x86_64.rpm et un paquet SRPM : lxc-0.8.0-1.el6.src.rpm.
Pour cet article, nous souhaitons seulement utiliser les Linux Containers, donc nous n'installons que les paquets suivants :
# rpm -ivh ~/rpmbuild/RPMS/x86_64/lxc-{,libs-}0.8.0-1.el6.x86_64.rpm
Le paquet lxc fournit un ensemble de scripts shell /usr/bin/lxc-* que vous pouvez lire pour mieux comprendre le fonctionnement des conteneurs et les moyens d'interaction à votre disposition. Il fournit aussi la documentation : modèles de systèmes virtuels (Busybox, Debian, Fedora, ...), exemples de fichiers de configuration et pages de man.
LXC se base sur les Linux Control Groups (cgroups) pour gérer l'allocation de ressources des conteneurs LXC. Le montage de /cgroup se fait simplement en ajoutant une ligne à /etc/fstab :
# cat >> /etc/fstab << EOF
cgroup /cgroupcgroup cpuacct,memory,devices,cpu,freezer,ns,blkio 0 0
EOF
Et la libcgroup alors ?
Sur les distributions fournissant un noyau plus récent, vous pouvez passer par le paquet libcgroup qui fournit les services cgconfig et cgred. Malheureusement, le noyau disponible dans les dépôts officiels de CentOS 6 présente une incompatibilité avec ces services conduisant à l'impossibilité de démarrer les conteneurs.
Un dernier point : le répertoire de travail de LXC n'est pas créé par défaut (un patch au fichier .spec peut corriger cela) ; nous le créons :
# mkdir /var/lib/lxc
Nous voici prêts à plonger dans le vif du sujet : la création de conteneurs et leur exécution.
2 Création d'un conteneur
Le premier point que nous devons aborder est ce qu'est un conteneur. Pour faire simple, un conteneur se compose d'un système de fichiers racine contenant le système à exécuter et d'un fichier de configuration décrivant les caractéristiques du système virtuel.
Pour tester rapidement le bon fonctionnement de LXC, nous allons créer un système virtuel à partir des modèles fournis par le paquet lxc et plus précisément, celui basé sur Busybox. Pour cela, rien de plus simple :
# lxc-create -n test -t busybox
Bon, il est vrai que sans informations complémentaires, c'est un peu sec. Je vous donne donc quelques détails, à commencer par les paramètres utilisés explicitement :
-n test définit le nom du conteneur. Cela permet de le manipuler par la suite.
-t busybox définit le modèle (template) à utiliser. Les modèles sont des scripts appelés lors de la création du système virtuel pour générer le fichier de configuration et peupler l'arborescence racine. Ces scripts sont placés dans /usr/share/lxc/templates et sont préfixés par lxc- (ce qui donne lxc-busybox dans notre cas).
Et maintenant, quelques informations sur le paramètre implicite (dont la valeur par défaut a été utilisée) : -Bnone. L'option -B permet de spécifier le backend pour le stockage du système de fichiers racine du système virtuel. Nous avons à notre disposition trois possibilités :
- none pour utiliser un répertoire ; par défaut, /var/lib/lxc/<name>/rootfs ;
- lvm pour utiliser un volume logique LVM ; par défaut, le groupe de volume utilisé est lxc et le volume logique est le nom du système virtuel, ce qui donne le périphérique /dev/lxc/<name>.
- btrfs pour utiliser un sous-volume d'un système de fichiers btrfs. Sur CentOS 6.3, aussi bien LXC que btrfs sont considérés comme des « techno previews » et donc instables ; il est donc déconseillé d'utiliser cette option pour le moment.
Pour cet article, j'ai choisi la simplicité en utilisant le backend none.
Notre système a été créé et vous pouvez l'explorer dans /var/lib/lxc/test/rootfs. Il s'agit d'un système minimal basé sur Busybox, donc tous les binaires sont des liens hard vers /sbin/busybox. Le répertoire pèse 1,2 Mo réels pour 283 Mo virtuels :
# du -sh /var/lib/lxc/test/rootfs
1,2M /var/lib/lxc/test/rootfs
# du -shl /var/lib/lxc/test/rootfs
283M /var/lib/lxc/test/rootfs
Et parallèlement, un fichier de configuration a été créé : /var/lib/lxc/test/config. Si vous le consultez, vous verrez qu'il définit les paramètres suivants :
- le nom du conteneur : lxc.utsname ;
- le nombre de périphériques d'interaction : lxc.tty et lxc.pts ;
- le chemin du système de fichiers racine : lxc.rootfs ;
- les points de montage fournis au conteneur : lxc.mount.entry. Ici, ce sont des montages en mode bind pour que le système ait accès aux bibliothèques du système hôte. C'est le parti pris de ce modèle, mais vous n'êtes pas obligé de fonctionner ainsi...
Bon, nous avons bien travaillé et méritons une petite récompense : démarrons notre système.
# lxc-start -n test
udhcpc (v1.15.1) started
Sending discover...
Sending discover...
[...]
Et là, vous voyez votre système envoyer des demandes d'adresse IP via le protocole DHCP et ce, à l'infini... Ce qui est un peu décevant. Cela vient du fait que le seul script exécuté lors de la phase d'initest /etc/init.d/rcS qui se termine par la commande /bin/udhcpc, client DHCP qui boucle tant qu'il n'a pas obtenu d'adresse. Or, nulle part nous n'avons spécifié à notre conteneur comment accéder physiquement au réseau. Nous allons corriger cela, mais avant, il nous faut arrêter notre conteneur depuis un autre terminal :
# lxc-stop -n test
Nous ajoutons quelques lignes au fichier de configuration du conteneur pour créer une interface réseau :
# cat >> /var/lib/lxc/test/config << EOF
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.name = eth0
lxc.network.hwaddr = 00:00:00:00:00:01
EOF
Ces lignes méritent quelques explications :
- lxc.network.type = veth spécifie que nous créons une interface virtuelle rattachée à un bridge.
- lxc.network.flags = up spécifie que nous voulons activer l'interface au démarrage du conteneur.
- lxc.network.link = br0 spécifie le bridge auquel est rattachée l'interface virtuelle ; la création du bridge n'est pas du ressort de LXC et est à votre charge.
- lxc.network.name = eth0 spécifie le nom de l'interface virtuelle tel que vu à l'intérieur du conteneur.
- lxc.network.hwaddr = 00:00:00:00:00:01 spécifie l'adresse MAC attribuée à l'interface virtuelle.
Nous utilisons dans cet article une interface rattachée à un bridge. Je vous montre ci-dessous comment le créer et vous laisse explorer les autres types d'interface réseau par vous-même. Ci-dessous, les étapes pour créer un bridge relié à votre interface eth0 et obtenant son adresse IP via DHCP (l'UUID et l'adresse MAC sont propres à votre matériel) :
# cat > /etc/sysconfig/network-scripts/ifcfg-eth0 <<EOF
DEVICE="eth0"
TYPE="Ethernet"
UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
HWADDR=xx:xx:xx:xx:xx:xx
NM_CONTROLLED="no"
ONBOOT=yes
BRIDGE="br0"
EOF
# cat > /etc/sysconfig/network-scripts/ifcfg-br0 << EOF
DEVICE="br0"
TYPE="Bridge"
NM_CONTROLLED="no"
ONBOOT="yes"
BOOTPROTO="dhcp"
# service network restart
Votre hôte est maintenant prêt à accepter des conteneurs avec une interface virtuelle bridgée. Nous pouvons le vérifier en démarrant à nouveau notre conteneur :
# lxc-start -n test
udhcpc (v1.15.1) started
Sending discover...
Sending discover...
Sending discover...
Sending discover...
Sending select for 192.168.1.80...
Lease of 192.168.1.80 obtained, lease time 86400
Please press Enter to activate this console.
Si vous suivez l'instruction qui vous est donnée (appuyer sur [Entrée]), vous obtenez un prompt connecté en tant que root. Votre système est un peu aride, mais permet déjà d'utiliser les commandes fournies par Busybox (voire de construire un système embarqué à base de Busybox). Pour quitter votre conteneur, vous devez passer par un terminal annexe et exécuter lxc-stop -n test.
Bon, tout ceci est bien sympathique, mais si nous passions à un système plus complet. La suite de l'article décrit comment installer un système CentOS 6.3 minimal depuis votre système hôte. Ce système minimal pourra vous servir de base pour héberger des services dans votre conteneur.
3 Création du système invité avec CentOS 6.3
Cette section est un peu hors-sujet, car elle ne traite pas vraiment de virtualisation, mais si vous utilisez une distribution basée sur Red Hat, elle pourra vous mettre le pied à l'étrier pour démarrer un environnement LXC. Le principe est de peupler une arborescence avec les paquets de la distribution et d'adapter le processus de démarrage pour qu'il fonctionne au sein d'un conteneur.
Commençons par créer un répertoire pour notre futur conteneur :
# mkdir -p /var/lib/lxc/centos/rootfs
Nous profitons ensuite de la capacité de la commande rpm à modifier la racine d'installation des paquets pour initialiser une nouvelle base de configuration dans notre système :
# mkdir -p /var/lib/lxc/centos/rootfs/var/lib/rpm
# rpm --root /var/lib/lxc/centos/rootfs --initdb
Nous installons ensuite le paquet centos-release depuis un miroir de la distribution (ici, celui du Centre Inter-universitaire de Ressources Informatiques de Lorraine, aka CIRIL). Au passage, nous validons la clé GPG utilisée pour signer les paquets de la distribution (vérifiez bien son contenu avant).
# rpm -ivh --nodeps --root /var/lib/lxc/centos/rootfs \
http://ftp.ciril.fr/pub/linux/centos/6.3/os/x86_64/Packages/centos-release-6-3.el6.centos.9.x86_64.rpm
# rpm --root /var/lib/lxc/centos/rootfs \
--import /var/lib/lxc/centos/rootfs/etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
Nous continuons en installant l'utilitaire yum dans notre conteneur. Il nous servira à gérer nos paquets dans notre système. Cela installe un total de 84 paquets supplémentaires qui sont des dépendances et qui occupent 229 Mo d'espace disque.
# yum --installroot /var/lib/lxc/centos/rootfs -y install yum
Si nous regardons les dépendances installées, nous avons déjà les composants d'un système minimal. Nous pouvons donc créer un fichier de configuration pour notre conteneur :
lxc.utsname = centos
lxc.tty = 1
lxc.pts = 1
lxc.rootfs = /var/lib/lxc/centos/rootfs
# Network configuration
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
lxc.network.name = eth0
lxc.network.hwaddr = 00:00:00:00:00:02
Celui-ci est encore plus petit que celui de notre conteneur basé sur Busybox, car nous ne montons pas de système de fichiers depuis notre hôte. Essayons de le démarrer :
# lxc-start -n centos
lxc-start: No such file or directory - failed to mount a new instance of '/dev/pts'
lxc-start: failed to setup the new pts instance
lxc-start: failed to setup the container
lxc-start: invalid sequence number 1. expected 2
lxc-start: failed to spawn 'centos'
Oups, ça plante ! Le message d'erreur est plutôt explicite : impossible de monter /dev/pts car le répertoire n'existe pas. Or, nous avons demandé la création d'un périphérique de type PTS. En lisant le modèle lxc-busybox, nous pouvons constater qu'il crée un certain nombre de périphériques dans l'arborescence /dev du conteneur. Nous pouvons nous en inspirer avant de démarrer à nouveau notre conteneur :
# mknod -m 666 /var/lib/lxc/centos/rootfs/dev/null c 1 3
# mknod -m 666 /var/lib/lxc/centos/rootfs/dev/tty c 5 0
# mknod -m 600 /var/lib/lxc/centos/rootfs/dev/console c 5 1
# mknod -m 620 /var/lib/lxc/centos/rootfs/dev/tty0 c 4 0
# mknod -m 620 /var/lib/lxc/centos/rootfs/dev/tty1 c 4 1
# mknod -m 620 /var/lib/lxc/centos/rootfs/dev/tty5 c 4 5
# mknod -m 600 /var/lib/lxc/centos/rootfs/dev/ram0 b 1 0
# mknod -m 666 /var/lib/lxc/centos/rootfs/dev/urandom c 1 9
Nous créons aussi au passage un fichier /etc/fstab vide, car le système a besoin de ce fichier. Dans le cadre de cet article, nous ne montons rien à l'intérieur de notre conteneur, mais cela serait tout à fait réalisable. Et nous essayons de démarrer.
# touch /var/lib/lxc/centos/rootfs/etc/fstab
# lxc-start -n centos
lxc-start: No such file or directory - failed to exec /sbin/init
lxc-start: invalid sequence number 1. expected 2
lxc-start: failed to spawn 'centos'
À nouveau, nous sommes confrontés à un échec : le programme /sbin/init appelé par le noyau pour initialiser la phase de démarrage en mode utilisateur. Ce programme est fourni par le paquet upstart, qui est un remplaçant orienté événement du vénérable programme init. Et tant que nous y sommes, nous allons lui adjoindre le paquet initscripts qui contient le fichier /etc/inittab, les scripts de démarrage et qui dépend de 23 paquets de détection et de gestion de périphériques (soit 38 Mo supplémentaires).
# yum --installroot /var/lib/lxc/centos/rootfs install upstart initscripts
# lxc-start -n centos
Et encore une fois, le démarrage échoue. La documentation Red Hat nous fournit quelques informations complémentaires sur le processus de démarrage [3.1]. Le programme /sbin/init commence par appeler le script /etc/rc.d/rc.sysinit ; or, celui-ci est trop complet pour notre besoin : appel à udev, mdadm, plymouth... Il nous faut donc le simplifier pour ensuite l'enrichir et l'adapter à nos besoins.
# mv /var/lib/lxc/centos/rootfs/etc/rc.d/rc.sysinit /var/lib/lxc/centos/rootfs/etc/rc.d/rc.sysinit.rpmorig
# cat > /var/lib/lxc/centos/rootfs/etc/rc.d/rc.sysinit << EOF
#!/bin/bash
# Clean whatever daemon/service pids that might remain from previous session
echo "Cleaning up old files..."
rm -f $(find /var/run -name '*.pid')
rm -f /var/lock/subsys/*
# Clean up mtab as we shouldn't have any mounted filesystem other than rootfs
rm -f /etc/mtab
touch /etc/mtab
EOF
# chmod +x /var/lib/lxc/centos/rootfs/etc/rc.d/rc.sysinit
# lxc-start -n centos
Enfin, nous n'avons plus de message d'erreur. Pour être sûrs, nous allons nous connecter à la console de notre conteneur :
# lxc-console -n centos
CentOS release 6.3 (Final)
Kernel 2.6.32-279.19.1.el6.x86_64 on an x86_64
centos login:
Et là vous vous dites : « Quel est le foutu mot de passe de root ? ». Aucun pour le moment, car nous n'en avons pas défini. Pour cela, la méthode la plus simple est d'utiliser la commande passwd en démarrant une session chrootée dans notre conteneur depuis un autre terminal. Pour cela, il faut installer le paquet passwd :
# yum --installroot /var/lib/lxc/centos/rootfs install passwd
# chroot /var/lib/lxc/centos/rootfs /bin/bash --login
bash-4.1# passwd
Changement de mot de passe pour l'utilisateur root.
Nouveau mot de passe :
Retapez le nouveau mot de passe :
passwd : mise à jour réussie de tous les jetons d'authentification.
En revenant sur la console, nous pouvons maintenant nous connecter en tant que root. Nous pouvons éteindre notre conteneur de l'intérieur via un simple shutdown.
Pour autant, ce n'est pas fini : notre conteneur n'a pas configuré son interface réseau. Cette fois, nous revenons dans le domaine de la configuration d'un système CentOS :
# yum --installroot /var/lib/lxc/centos/rootfs install dhclient
# echo "NETWORKING=yes" > /var/lib/lxc/centos/rootfs/etc/sysconfig/network
# cat > /var/lib/lxc/centos/rootfs/etc/sysconfig/network-scripts/ifcfh-eth0 << EOF
DEVICE=eth0
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=dhcp
EOF
# lxc-start -n centos
Notre conteneur démarre et configure son interface réseau via le protocole DHCP. En nous connectant à la console, nous réalisons notre première installation depuis le conteneur lui-même :
bash-4.1# yum install rsyslog
bash-4.1# yum install openssh-server
bash-4.1# service sshd start
Vous pouvez maintenant accéder à votre conteneur par SSH et le configurer selon vos besoins : configurer le fuseau horaire, la langue, …, ajouter des services. Bref, vous avez un nouveau serveur CentOS qui tient en 136 paquets et 378 Mo et qui vous fera un bon point de départ. D'ailleurs, cet article devrait vous permettre de créer votre propre modèle LXC.
Inspiration
Dans cette section, je me suis inspiré d'un billet du blog de Lucas Nussbaum que j'ai enrichi : http://www.lucas-nussbaum.net/blog/?p=385.
4 Sécurisation d'un conteneur
Vous aurez remarqué que je n'ai pas abordé la sécurité des conteneurs LXC. Ceux-ci présentent les mêmes risques qu'un environnement chrooté : tout programme fonctionnant en tant que root peut sortir de la cage [4.1]. La littérature disponible indique cependant des possibilités de sécurisation : les mécanismes de type MAC (Mandatory Access Control) qui permettent de limiter les droits d'accès d'un processus. Pour faire court, les processus d'un conteneur ne sont alors autorisés qu'à accéder aux fichiers du conteneur.
Parmi ces mécanismes, nous trouvons AppArmor [4.2] et SELinux [4.3] : je ne cite que ceux-là, car LXC est directement compatible avec AppArmor sur les systèmes l'utilisant (Debian-like, openSUSE, ...) et que SELinux est fortement encouragé et développé dans la communauté Red Hat, dont hérite CentOS. Cette section sera donc un simple bookmark vers :
L'article « Secure Linux containers cookbook » d'IBM : http://www.ibm.com/developerworks/linux/library/l-lxc-security/index.html
Les travaux de Daniel P. Berrange (Red Hat) autour de la création de sandbox avec LXC :
https://fedoraproject.org/wiki/Features/VirtSandbox
https://www.berrange.com/posts/2012/01/17/building-application-sandboxes-with-libvirt-lxc-kvm/
https://gitorious.org/virt-tools/virt-sandbox
5 Aller plus loin avec libvirt
Il existe un driver pour LXC [5.1] au sein du projet Libvirt [5.2]. Libvirt est une API de gestion de systèmes virtuels capable de s'interfacer avec de multiples technologies : KVM, Xen, LXC, OpenVZ, User Mode Linux, Virtualbox, VMware ESX/GSX/Workstation/Player et Microsoft Hyper-V. C'est le couteau suisse de la virtualisation. Son utilisation est quelque peu hors-sujet, je vous laisse donc explorer cette voie par vous-même.
D'ailleurs, Libvirt exploite une fonctionnalité du système Linux pour gérer l'allocation de ressources des conteneurs : les cgroups [5.3] que j'évoque rapidement lors de la phase d'installation. Je ne m'attarderai pas sur ce sujet qui a été traité plus spécifiquement dans le numéro 141 de GNU/Linux Magazine France. Je vous invite donc à vous y reporter pour plus de précision.
Un dernier point concerne une fonctionnalité non disponible sur CentOS 6, et que je n'ai pas pu tester sur une distribution disposant d'un noyau plus récent : la possibilité de réaliser un checkpoint du système virtuel. Cela consiste à passer les processus du namespace associé au conteneur à l'état freeze pour ensuite stocker leur état dans un fichier. Il est ensuite possible de les redémarrer depuis ce fichier d'état. C'est une fonctionnalité encore jeune et les mécanismes au niveau noyau ne sont pas encore totalement fixés, mais c'est un projet à suivre.
Bibliographie
[0.1] LinuX Containers : http://lxc.sourceforge.net
[3.1] Red Hat - The /sbin/init program : https://access.redhat.com/knowledge/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Installation_Guide/s2-boot-init-shutdown-init.html
[4.1] How to break out of a chroot() jail : http://www.bpfh.net/simes/computing/chroot-break.html
[4.2] AppArmor : http://wiki.apparmor.net
[4.3] SELinux : http://selinuxproject.org
[5.1] Libvirt : http://libvirt.org
[5.2] Libvirt - LXC container driver : http://libvirt.org/drvlxc.html
[5.3] Linux Control Groups : http://fr.wikipedia.org/wiki/Cgroups