Linux Containers (LXC) et Oracle Linux 6.3

Linux Container ou LXC est une solution de virtualisation légère. Elle est l’équivalent des zones Solaris. La solution a intégré le kernel mainline et prend progressivement le pas sur d’autres solutions comme OpenVZ. LXC s’appuie sur plusieurs technologies comme Chroot, les Cgroups ou le support de différents espaces de nommage de la commande clone.

Contrairement aux solutions basées sur un hyperviseur comme Xen ou VMWare, les containers partagent le noyau du serveur. Si cette approche a plusieurs inconvénients, elle est très légère et permet de créer des instances beaucoup plus nombreuses qu’avec n’importe quel hyperviseur.

Oracle Linux 6.3 intégre, en « preview » LXC, ainsi qu’un ensemble de scripts pour gérer la solution dont certains visiblement développés par Wim Coekaerts. Cette implémentation s’appuie sur Btrfs pour cloner les différentes instances. Cet article présente l’utilisation de LXC dans ce contexte.

Note :
La documentation liée à la mise en oeuvre de LXC est disponible dans Oracle® Linux Administrator’s Solutions Guide for Release 6 – Chapter 8. Linux Containers. La procédure d’installation fait partie de cette documentation.

Création d’un système de fichiers Btrfs

L’implémentation des scripts LXC qui vient avec Oracle Linux 6.3 s’appuie sur Btrfs pour la partie clone des containers. Vous pouvez simplement ajouter un système de fichiers sur le répertoire /container de votre serveur. On supposera que vous avez créé une partition /dev/sdb1.  Pour créer le système de fichiers, ainsi qu’un sous-volume ol6-template, vous pouvez procéder comme dans le script ci-dessous :

pvcreate /dev/sdb1
vgcreate VMs_vg /dev/sdb1
vgdisplay VMs_vg
lvcreate -l5118 -n VMs_lv VMs_vg
mkfs -t btrfs  /dev/VMs_vg/VMs_lv
mkdir /container
echo "/dev/mapper/VMs_vg-VMs_lv /container btrfs defaults 0 0"
   >>/etc/fstab
mount /container
btrfs subvolume create /container/ol6-template

Note:
Le script de création des containers LXC qui vient avec Oracle Linux 6 suppose que /container/ol6-template est un sous-volume Btrfs. Les chemins sont définis dans le script et ils supposent que Linux que ol6-template soit un sous-volume qui contient une version complète de Linux.

Une fois le volume Btrfs créé, vous pouvez copier le contenu de votre serveur dans le répertoire associé à l’aide de la commande ci-dessous :

find / -mount -depth | cpio -pdv /container/ol6-template

Note:
Il est important que la création du template vienne avant l’installation des packages LXC, l’installation des packages et les configurations liées à l’utilisation de LXC comme les bridges. Dans l’hypothèse inverse, vous risquez d’hériter également de cette configuration dans vos containers. 

Installation des packages nécessaires à LXC

Pour utiliser LXC, vous devrez installer les packages libcgroup et démarrer le service associé. Vous devrez également installer les packets bridge-utils, lxc, lxc-lib et lxc-devel comme ci-dessous :

yum install libcgroup
service cgconfig start
Starting cgconfig service: [ OK ]
chkconfig cgconfig on
yum install btrfs-progs
yum install bridge-utils
yum install lxc lxc-libs lxc-devel
Loaded plugins: security
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package lxc.x86_64 0:0.7.5-2.0.4.el6 will be installed
---> Package lxc-devel.x86_64 0:0.7.5-2.0.4.el6 will be installed
---> Package lxc-libs.x86_64 0:0.7.5-2.0.4.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
lxc x86_64 0.7.5-2.0.4.el6 ol6_u3_perso 69 k
lxc-devel x86_64 0.7.5-2.0.4.el6 ol6_u3_perso 14 k
lxc-libs x86_64 0.7.5-2.0.4.el6 ol6_u3_perso 78 k

Transaction Summary
================================================================================
Install 3 Package(s)

Total download size: 161 k
Installed size: 478 k
Is this ok [y/N]: y
Downloading Packages:
(1/3): lxc-0.7.5-2.0.4.el6.x86_64.rpm | 69 kB 00:00
(2/3): lxc-devel-0.7.5-2.0.4.el6.x86_64.rpm | 14 kB 00:00
(3/3): lxc-libs-0.7.5-2.0.4.el6.x86_64.rpm | 78 kB 00:00
--------------------------------------------------------------------------------
Total 1.3 MB/s | 161 kB 00:00
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Installing : lxc-libs-0.7.5-2.0.4.el6.x86_64 1/3
Installing : lxc-0.7.5-2.0.4.el6.x86_64 2/3
Installing : lxc-devel-0.7.5-2.0.4.el6.x86_64 3/3
Verifying : lxc-0.7.5-2.0.4.el6.x86_64 1/3
Verifying : lxc-libs-0.7.5-2.0.4.el6.x86_64 2/3
Verifying : lxc-devel-0.7.5-2.0.4.el6.x86_64 3/3

Installed:
lxc.x86_64 0:0.7.5-2.0.4.el6 lxc-devel.x86_64 0:0.7.5-2.0.4.el6
lxc-libs.x86_64 0:0.7.5-2.0.4.el6

Création d’un bridge réseau

Vous devez reconfigurer le réseau de votre serveur pour créer un bridge nommé virbr0 comme ci-dessous. Le nom du bridge est défini dans le script de création des containers. Suite à quoi vous redémarrerez le réseau et vérifierez la configuration du Bridge :

cat /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static
HWADDR="08:00:27:A4:09:7C"
NM_CONTROLLED=no
ONBOOT=yes
TYPE=Ethernet
BRIDGE=virbr0


cat /etc/sysconfig/network-scripts/ifcfg-virbr0
DEVICE=virbr0
TYPE=Bridge
NM_CONTROLLED=no
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.56.19
NETMASK=255.255.255.0


service network restart
Shutting down interface eth0: bridge virbr0 does not exist!
[ OK ]
Shutting down loopback interface: [ OK ]
Bringing up loopback interface: [ OK ]
Bringing up interface eth0: [ OK ]
Bringing up interface virbr0:
[ OK ]

# ifconfig -a
eth0 Link encap:Ethernet HWaddr 08:00:27: A4:09:7C
inet6 addr: fe80::a00:27ff:fea4:97c/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:125153 errors:0 dropped:0 overruns:0 frame:0
TX packets:21596 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:183871459 (175.3 MiB) TX bytes:1604285 (1.5 MiB)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

virbr0 Link encap:Ethernet HWaddr 08:00:27:A4:09:7C
inet addr:192.168.56.19 Bcast:192.168.56.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fea4:97c/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:55 errors:0 dropped:0 overruns:0 frame:0
TX packets:50 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3670 (3.5 KiB) TX bytes:6292 (6.1 KiB)

brctl show
bridge name bridge id STP enabled interfaces
virbr0 8000.080027a4097c no eth0

Script de création d’un container

Naviguez dans le répertoire /usr/lib64/lxc/templates et créez un fichier lxc-ol6 comme ci-dessous :

cd /usr/lib64/lxc/templates
cat lxc-ol5 | sed 's/ol5/ol6/g ; s/Linux 5/Linux 6/g' > lxc-ol6
chmod 755 lxc-ol6

Vous pouvez modifier le script pour désactiver les services iptables, certmonger, haldaemon, rpcbind, nfslock et nfs en ajoutant les lignes ci-dessous après la section dédiée à dund :

chroot ${rootfs_path} chkconfig iptables off
chroot ${rootfs_path} chkconfig certmonger off
chroot ${rootfs_path} chkconfig haldaemon off
chroot ${rootfs_path} chkconfig rpcbind off
chroot ${rootfs_path} chkconfig nfslock off
chroot ${rootfs_path} chkconfig nfs off

Ajoutez également la section suivante avant la ligne « return 0 » de la fonction configure_ol6() pour modifier le mot de passe de votre container :

rootpw1=1; rootpw2=2
until [ $rootpw1 == $rootpw2 ]
do
echo -en "nEnter root password: "; read -s rootpw1
echo -en "nEnter root password again: "; read -s rootpw2
done
echo "root:"$rootpw1 | chroot ${rootfs_path} chpasswd
echo -e "Password set.n"

cat /etc/init/start-ttys.conf | sed 's/env X_TTY/#env X_TTY/' >
${rootfs_path}/etc/init/start-ttys.conf

Vous êtes prêt à utiliser LXC.

Créer et démarrer un container

Pour créer un container, lancez le script lxc-create comme ci-dessous :

lxc-create -n vm1 -t ol6

Warning:
-------
Usually the template option is called with a configuration
file option too, mostly to configure the network.
eg. lxc-create -n foo -f lxc.conf -t debian
The configuration file is often:

lxc.network.type=macvlan
lxc.network.link=eth0
lxc.network.flags=up

or alternatively:

lxc.network.type=veth
lxc.network.link=br0
lxc.network.flags=up

For more information look at lxc.conf (5)

At this point, I assume you know what you do.
Press to continue ...

Cloning base template /container/ol6-template to /container/vm1 ...
Create a snapshot of '/container/ol6-template' in '/container/vm1'

Enter root password:
Enter root password again: Password set.

Container created : /container/vm1 ...
Container template source : /container/ol6-template
Container config : /etc/lxc/vm1
Network : eth0 (veth) on virbr0
'ol6' template installed
'vm1' created

Note:
Par défaut le container récupère l’adresse IP de la machine virtuelle à l’aide de DHCP. Vous pouvez modifier le script pour changer ce fonctionnement.

Vous pourrez démarrer le container et vous connecter à l’aide des commandes lxc-start et lxc-console comme ci-dessous :

lxc-start -n vm1 -d -o /container/vm1.log
lxc-console -n vm1

Pour vous déconnecter de la console, tapez simplement ce qui suit :

Ctrl+a q

Manipuler le container

Vous pouvez visualiser les processus du container depuis le serveur à l’aide de la commande ci-dessous :

ps -ef --forest
root 6440 6432 0 15:56 ? 00:00:00 _ /sbin/init
root 6743 6440 0 15:56 ? 00:00:00 _ /sbin/dhclient -1 -q -cf /etc/dhcp/dhclient-eth0.conf -lf /var/lib/dhclient/dhclient-eth0.leases -pf /var/run/dhclient-eth0.pid eth0
root 6840 6440 0 15:56 ? 00:00:00 _ /sbin/rsyslogd -i /var/run/syslogd.pid -c 5
root 6893 6440 0 15:56 ? 00:00:00 _ rpc.idmapd
root 6936 6440 0 15:56 ? 00:00:00 _ cupsd -C /etc/cups/cupsd.conf
root 6978 6440 0 15:56 ? 00:00:00 _ /usr/sbin/sshd
root 7057 6440 0 15:56 ? 00:00:00 _ /usr/libexec/postfix/master
postfix 7071 7057 0 15:56 ? 00:00:00 | _ pickup -l -t fifo -u
postfix 7072 7057 0 15:56 ? 00:00:00 | _ qmgr -l -t fifo -u
root 7079 6440 0 15:56 ? 00:00:00 _ /usr/sbin/abrtd
root 7087 6440 0 15:56 ? 00:00:00 _ abrt-dump-oops -d /var/spool/abrt -rwx /var/log/messages
root 7095 6440 0 15:56 ? 00:00:00 _ crond
root 7106 6440 0 15:56 ? 00:00:00 _ /usr/sbin/atd
root 7124 6440 0 15:56 ? 00:00:00 _ login -- root
root 7195 7124 0 15:58 pts/1 00:00:00 | _ -bash
root 7126 6440 0 15:56 pts/2 00:00:00 _ /sbin/mingetty /dev/tty2
root 7128 6440 0 15:56 pts/3 00:00:00 _ /sbin/mingetty /dev/tty3
root 7130 6440 0 15:56 pts/4 00:00:00 _ /sbin/mingetty /dev/tty4
root 7457 6440 0 16:05 ? 00:00:00 _ /sbin/mingetty /dev/tty5
root 7458 6440 0 16:05 ? 00:00:00 _ /sbin/mingetty /dev/tty6

Vous pouvez geler le container à l’aide de lxc-freeze comme ci-dessous :

lxc-info -n vm1
state: RUNNING
pid: 6440


lxc-freeze -n vm1

lxc-info -n vm1
state: FROZEN
pid: 6440


lxc-unfreeze -n vm1

Supprimer le container

Pour supprimer le container, utilisez les commandes lxc-kill et lxc-destroy comme ci-dessous puis supprimez le snapshot Btrfs associé :

# arrete le container
lxc-kill -n vm1

lxc-info -n vm1
state: STOPPED
pid: -1


# supprime le repertoire /etc/lxc/vm1
lxc-destroy -n vm1

btrfs subvolume list /container
ID 260 top level 5 path ol6-template
ID 262 top level 5 path vm1


btrfs subvolume delete /container/vm1
Delete subvolume '/container/vm1'

btrfs subvolume list /container
ID 260 top level 5 path ol6-template

Et encore…

Vous pouvez réaliser, une fois connecté au container, la plupart des opérations que vous pourrez réaliser dans un serveur, y compris installer et désinstaller des packages. LXC propose, quant à lui, plusieurs outils pour fixer des priorités de fonctionnement de vos machines virtuelles. Et cela est déjà une autre histoire que vous aurez envie, forcément, d’investiguer…