Conteneurs Linux (LXC)

Il peut arriver qu’on ait besoin d’un autre environnement pour x raisons, si cet autre environnement est un OS différent, il faut se tourner vers les solutions de virtualisation tel que vmware, virtualbox ou encore kvm, par contre, si c’est pour tourner sous Linux, on peut s’en passer et utiliser un chroot.

Sous Archlinux, on peut se référer à la page chroot du wiki pour mettre en place assez rapidement un environnement fonctionnel.

L’inconvénient avec le chroot, c’est que le système y tournant n’est pas limité dans l’accès aux ressources, plusieurs systèmes permettent d’isoler un environnement, dont les « conteneurs linux » (LXC), que j’ai découvert avec cet excellent article: Architecture Domestique – Les Conteneurs Linux, on va voir comment mettre ça en place sous Archlinux, pour les explications détaillées, rien ne sert de se répéter, l’article cité précédemment explique ça très bien.
Pour plus d’informations, vous pouvez vous référer au site LXC (même si c’est moins détaillé).

Tout d’abord, LXC a besoin de certaines options dans le noyau, pour celui livré avec Archlinux, il nous faut en plus (certaines options nécessaires sont déjà activées):

CONFIG_GROUP_SCHED=y
CONFIG_SCHED_OTHER=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=n
CONFIG_USER_SCHED=n
CONFIG_CGROUP_SCHED=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_DEBUG=n
CONFIG_CGROUP_NS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CPUSETS=y
CONFIG_PROC_PID_CPUSET=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_CGROUP_MEM_RES_CTLR=y
CONFIG_CGROUP_MEM_RES_CTLR_SWAP=n
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_NET_CLS_CGROUP=n
CONFIG_DEVPTS_MULTIPLE_INSTANCES=y

Vous pouvez vous inspirer du PKGBUILD suivant: kernel26-lxc-2.6.31.4-1.src.tar

Il faudra de même refaire les paquets genre « nvidia » par exemple ou tout autre paquet lié directement au noyau.

Pour avoir tous les outils, il nous faut aussi installer les utilitaires LXC, un pkgbuild est disponible sous AUR: lxc-git (lxc-git sur ce site).

Si on veut avoir le support du réseau dans l’environnement, il nous faut configurer un pont, sous archlinux:

pacman -S bridge-utils

En supposant que vous êtes connectés en filaire (eth0) et en dhcp, il faut modifier /etc/conf.d/bridges comme suit:

bridge_br0="eth0"
BRIDGE_INTERFACES=(br0)

et /etc/rc.conf:

eth0="eth0 0.0.0.0 up"
br0="dhcp" 
INTERFACES=(eth0 br0)

Pour éviter un temps d’attente pour le passage des données, exécutez ceci une fois le système démarré:

brctl setfd br0 0

Une fois le noyau recompilé, la machine rebootée, les outils lxc installés, et le pont configuré, il faut créer l’environnement, pour l’exemple, on va créer un environnement 32 bits appelé « arch32 », il nous faut d’abord un fichier de configuration qu’on appellera arch32.conf:

#Nom de l'environnement
lxc.utsname = arch32
lxc.rootfs=/var/lib/lxc/arch32/rootfs
#Configuration du réseau
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = br0
# Pour l'adresse, modifiez selon votre adressage.
lxc.network.ipv4 = 192.168.1.230/24
lxc.network.name = eth0
# Nombre de terminaux et pseudo terminaux disponibles
lxc.pts=1
lxc.tty=4

puis:

lxc-create -n arch32 -f arch32.conf

Cette commande crée un répertoire dans /var/lib/lxc:

arch32/
|-- config
|-- network
|   `-- veth0
|       |-- ipv4
|       |   `-- addresses
|       |-- link
|       |-- name
|       `-- up
|-- pts
|-- tty
`-- utsname

Il faut maintenant y mettre le système à proprement dit, en utilisant le pacman.conf du wiki:

[options]
HoldPkg     = pacman glibc
SyncFirst   = pacman
[core]
Server = http://mir.archlinux.fr/$repo/os/i686
[extra]
Server = http://mir.archlinux.fr/$repo/os/i686
[community]
Server = http://mir.archlinux.fr/$repo/os/i686

J’installe en plus du système de base, le serveur ssh:

mkarchroot -C /root/pacman.conf /var/lib/lxc/arch32/rootfs base openssh

Quelque modifications sont nécessaires car udev ne fonctionne pas dans le conteneur:

cd /var/lib/lxc/arch32/rootfs 
# Initialisation du répertoire /dev
cp -a lib/udev/devices/* dev/
# Création de certains fichiers supplémentaires
mknod -m 666 dev/tty c 5 0
mknod -m 666 dev/tty0 c 4 0
mknod -m 666 dev/random c 1 8
mknod -m 666 dev/urandom c 1 9
# Une console accessible depuis lxc-console, le fichier
# sera modifié par lxc.
mknod dev/tty1 c 136 4

Du fait qu’udev ne fonctionne pas, on a le choix entre modifier les scripts de démarrage d’Archlinux, ou alors mettre un fichier /sbin/init modifié comme ce qu’à fait Ulhume, ce qui a le mérite de fonctionner sans mauvaise surprise.

mv sbin/init{,.old}

sbin/init:

#!/bin/sh

# Montage des pseudos systèmes de fichier
/bin/mount -n -t proc none /proc
/bin/mount -n -t sysfs none /sys
mount -a

# arrêt/démarrage des services
/etc/rc.d/syslog-ng start
/etc/rc.d/network start
/etc/rc.d/sshd start
 
# Attente de la mise mort de la machine
rm -rf /.dead
> /.running
#agetty -8 38400 tty linux &
#sh
while [ -f /.running ]; do
    sleep 1
done
 
# Arrêt des services
/etc/rc.d/sshd stop
/etc/rc.d/network stop
/etc/rc.d/syslog-ng stop

kill -15 -1 &> /dev/null
# Démontage des systèmes de fichier
umount /proc
umount /sys
#umount /dev/shm
umount -a
mv sbin/halt{,.old}

sbin/halt:

#!/bin/sh
# le sleep permet de quitter le ssh
(sleep 2; rm /.running ) &

Personnellement, j’ai aussi modifié bin/arch et bin/uname pour avoir une réponse cohérente vu que l’environnement sera en 32 bits:

mv bin/arch{,.old}
#!/bin/sh
echo "i686"
mv bin/uname{,.old}
#!/bin/sh
uname.old "$@" | sed 's|x86_64|i686|g'

Il reste à modifier les fichiers etc/rc.conf, etc/hosts.allow pour les informations de l’environnement, le réseau et l’accès depuis l’hôte.

Avant d’accéder à l’environnement avec lxc, il faut modifier le mot de passe du root pour pouvoir y accéder depuis ssh:

# mkarchroot -r bash /var/lib/lxc/arch32/rootfs
mounting sysfs : /sys
mounting procfs : /proc
binding device nodes : /dev
binding pacman cache : /var/cache/pacman
copying mtab : /etc/mtab
copying resolv.conf : /etc/resolv.conf
starting chroot (bash)
[root@host /]# passwd
Entrez le nouveau mot de passe UNIX : 
Retapez le nouveau mot de passe UNIX : 
passwd : le mot de passe a été mis à jour avec succès
[root@host /]# exit
cleaning up mounts
#

L’environnement est normalement près, mais avant, il faut monter un périphérique spécial pour lxc:

mkdir /cgroup
mount -t cgroup cgroup /cgroup

et voilà, il ne reste plus qu’à lancer le tout:

lxc-start -n arch32
:: Starting Syslog-NG                                                    [DONE] 
:: Starting Network                                                      [DONE] 
:: Starting Secure Shell Daemon                                          [DONE]
$ ssh root@192.168.1.230
root@192.168.1.230's password: 
Last login: Mon Oct 12 10:23:42 2009 from localhost
[root@arch32 ~]# halt

Voilà, c’est un point de départ, les conteneurs ne se bornent bien sûr pas à seulement lancer un chroot, le fichier de configuration peut être bien plus complet que ça en autorisant seulement l’accès à certaines ressources.
Une fois le fonctionnement cerné, j’essaierai de faire un article dessus si quelqu’un ne s’y est pas attelé entre temps.

Un LXC HowTo (en) que j’ai découvert grâce au commentaire de l’auteur: Dwight Schauer; ça va un peu plus loin que la simple pratique.
Ainsi que la demande d’intégration d’un patch pour configurer un pont plus aisément:
FS#16625

Commentaires (2)