Virtualisation avec XEN sous Debian

XEN est un hyperviseur qui permet de créer des machine virtuelles auxquelles sont attribuées des ressources fixes et dédiées (CPU, RAM, disque ...). XEN s'installe sur un système déjà configuré qui devient alors le "Domain Host" (ou Dom0), les machines virtuelles créées sur ce domaine sont des "Domain Guest" (ou DomU)

Le but est ici de mettre en place un Dom0 sous Linux Debian et de créer des DomU également sous Debian. Il est cependant possible d'installer n'importe quel OS sur un DomU (Windows, Solaris, autre distribution Linux ...)

Table des matières

1. Configuration du Domain Host
2. Configuration du Domain Guest
3. Duplication d'un Domain Guest

Configuration du Domain Host

Nous partons d'une installation standard de Debian pour installer le Domain Host. A partir d'ici, nous considérons que le système actuel est correctement paramétré et fonctionne normalement.
En mode "testing" sous Debian, XEN a le bon goût d'être disponible directement en paquets. Pour éviter de nombreuses heures de galère, nous allons utiliser les paquets mis à notre disposition.

Si ce n'est pas déjà le cas, nous allons modifier les sources d'APT pour pointer vers le repository de "testing":

cat /etc/apt/sources.list
deb ftp://ftp.fr.debian.org/debian testing main contrib non-free
deb http://security.debian.org testing/updates main contrib non-free

Puis une bonne mise à jour du Système :)
apt-get update
apt-get dist-upgrade

Passons ensuite à l'installation de XEN:
apt-get install xen-hypervisor-3.2-1-i386 xen-tools xen-utils-3.2-1 libc6-xen linux-image-2.6-xen-686 linux-image-2.6.18-6-xen-vserver-686

XEN nécessite des options spéciales au niveau du noyau Linux pour fonctionner. Une fois converti en Dom0, le système actuel démarrera donc sur une version modifiée du noyau. De même, XEN utilise une version modifié de la libc6, heureusement disponible également sous forme pckagée. Nous installons ici deux versions du noyau modifié pour XEN car les DomU utiliserons également une version modifiée du noyau mais légérement différente. Les paquets mis à disposition par Debian font la distinction entre les deux types de noyau.

Théoriquement, l'installation des paquets modifie automatiquement le boot loader pour utiliser le nouveau noyau si on utilise GRUB. Le système bootera également avec LILO mais dans notre cas, nous partirons du principe que le boot loader est GRUB.
Une petite vérification:

cat /boot/grub/menu.lst
title Xen 3.2-1-i386 / Debian GNU/Linux, kernel 2.6.18-6-xen-686
root (hd0,0)
kernel /boot/xen-3.2-1-i386.gz dom0_mem=3145728
module /boot/vmlinuz-2.6.18-6-xen-686 root=/dev/cciss/c0d0p1 ro console=tty0
module /boot/initrd.img-2.6.18-6-xen-686

Comme expliqué plus haut, XEN permet d'attribuer des ressources physiques dédiées à chaque machine virtuelle. Dans cette optique, nous souhaitons attribuer une partie de la RAM disponible au Domain Host puis partager la RAM restante entre les différentes machines virtuelles créées. Pour cela, le paramètre dom0_mem est passé au boot du noyau pour limiter la mémoire allouée au Domain Host. Dans notre exemple, le serveur dispose de 5Go de RAM et nous souhaitons allouer 3Go au Domain Host. Il suffit d'éditer le fichier /boot/grub/menu.lst pour placer le paramètre en conséquence (en octets).

Un autre point particulier de la virtualisation avec XEN est la gestion des interfaces réseau. Chaque machine virtuelle dispose en effet d'une ou plusieurs interfaces réseau qui sont reliées aux interfaces physiques du Domain Host par le biais d'interfaces virtuelles. Il existe plusieurs façons de gérer les intefaces virtuelles, la plus simple étant le mode "bridge". Dans ce cas de figure, des interfaces xenbrX sont créées par XEN pour se substituer aux interfaces ethX. Un pont pethX est également créé par XEN pour chaque interface réseau physique ainsi que des interfaces virtuelles vifX.Y. Ces interfaces virtuelles correspondent aux interfaces réseaux configurées pour chaque Domain Guest et sont gérées par le Domain Host.

Fort heureusement, XEN est livré avec des scripts qui configurent toutes les interfaces automatiquement au démarrage de l'hyperviseur. Par défaut, ils sont prévus pour le cas où vous possédez une seule interface réseau (celle qui est utilisée pour router le traffic par défaut), ils nécessiteront donc quelques adaptations pour fonctionner avec plusieurs interfaces mais dans la mahjorité des cas, ils sont utilisables en l'état.

Pour utiliser XEN en mode bridge, nous allons faire une modification dans le fichier /etc/xen/xend-config.sxp:
# It is possible to use the network-bridge script in more complicated
# scenarios, such as having two outgoing interfaces, with two bridges, and
# two fake interfaces per guest domain. To do things like this, write
# yourself a wrapper script, and call network-bridge from it, as appropriate.
#
#(network-script network-dummy)
(network-script network-bridge)

# If you are using only one bridge, the vif-bridge script will discover that,
# so there is no need to specify it explicitly.
#
(vif-script vif-bridge)


En même temps, nous allons vérifier les ressources CPU allouées au Domain Host:
(dom0-cpus 0)

Ce paramètre permet de spécifier combien de CPU (ou combien de coeurs) sont alloués au Domain Host. Si la valeur est fixé à zéro, le Domain Host utilisera tous les CPU à sa disposition.

Il est temps de redémarrer pour prendre en compte le nouveau noyau et démarrer XEN. Si tout se passe bien, votre installation est maintenant un Domain Host XEN! Pour le vérifier:

xm list
Name ID Mem VCPUs State Time(s)
Domain-0 0 3017 2 r----- 2331.2


Au passage, on vérifie que les ressources ont bien été limitées en terme de RAM (dans notre exemple 3Go) pour le Dom0 ainsi que l'état des bridges XEN:

free
total used free shared buffers cached
Mem: 3089408 1100588 1988820

brctl show
bridge name bridge id STP enabled interfaces
xenbr0 8000.feffffffffff no peth0
vif0.0
xenbr1 8000.feffffffffff no peth1
vif0.1


Passons maintenant à la configuration des Domain Guests

Configuration du Domain Guest

Pour configurer les Domain Guest, nous allons commencer par créer une installation Linux de base afin de pouvoir la dupliquer facilement lorsque nous aurons besoin de créer une nouvelle machine virtuelle.

La méthode la plus simple est de créer des images qui seront utilisées en tant que système de fichiers. Pour plus de flexibilité, l'idéal est d'utiliser des volumes logiques LVM qui permettent d'ajuster la taille des systèmes de fichiers en cas de besoin. Pour la suite, nous partirons du principe que nous manipulons des volumes logiques. Si il n'existe pas de LVM sur le Dom0, il suffit de remplacer les volumes logiques par des images:

(Exemple pour un filesystem de 3Go et un espace swap de 1Go):
dd if=/dev/zero of=vm_base.img bs=1024k count=3000
dd if=/dev/zero of=vm_base-swap.img bs=1024k count=1000


Reprenons l'installation du DomU avec des volumes LVM ...

Création du volume logique (ici le Volume Group est vg0):
lvcreate -L 3G vg0 -n VM-base
mkfs.ext3 /dev/vg0/VM-base

Installation d'un système de base:
mount -o loop /dev/vg0/VM-base /mnt/
debootstrap --arch i386 etch /mnt/ http://ftp2.fr.debian.org/debian


Maintenant que les packages de base sont installés, nous allons nous positionner dans le nouvel environnement et faire les modifications nécessaire pour qu'il devienne un Domain Guest XEN.

Installation des packages pour le Domain Guest de référence:
cd /mnt
chroot .
apt-get install locales console-data console-common dnsutils debian-keyring
apt-get libc6-xen udev linux-modules-2.6.18-6-xen-vserver-686 ssh
dpkg-reconfigure locales
dpkg-reconfigure console-data

On modifie ensuite la configuration des partitions du Domain Guest:

vi /etc/fstab
proc /proc proc defaults 0 0
/dev/hda1 / ext3 defaults 1 2
/dev/hda2 none swap sw 0 0

Puis on modifie la configuration réseau:

vi /etc/network/interfaces
auto lo
iface lo inet loopback
address 127.0.0.1
netmask 255.0.0.0


Et enfin le fichier de hosts:

vi /etc/hosts
127.0.0.1 localhost.localdomain localhost



A partir de la, nous avons une image d'un système de base qui pourra servir a dupliquer des machines virtuelles sur les Domain Guest.
Ce système pourra ensuite être adapté en fonction des besoins sur le Domain Guest.

Configurons le premier Domain Guest xen

Sur le Domain Host, on créé les volumes du Domain Guest.
Le but est de dupliquer le système de base configuré précédemment, nous allons donc créer un volume logique de taille identique et faire une copie par blocs:

lvcreate -L 3G vg0 -n VM1-root
Logical volume "VM1-root" created

dd if=/dev/vg0/VM-base of=/dev/vg0/VM1-root
6291456+0 enregistrements lus
6291456+0 enregistrements écrits
3221225472 bytes (3,2 GB) copied, 276,221 s, 11,7 MB/s

lvdisplay
--- Logical volume ---
LV Name /dev/vg0/VM1-root
VG Name vg0
LV UUID zOYSkI-jxLS-FHzf-4LF7-Hm27-hgOL-9Mm3KB
LV Write Access read/write
LV Status available
# open 1
LV Size 3,00 GB
Current LE 768
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 254:4



Le volume qui sera utilisé comme espace de swap est par contre propre à chaque machine virtuelle. On le créé à part:

lvcreate -L 1G vg0 -n VM1-swap
Logical volume "VM1-swap" created

mkswap /dev/vg0/VM1-swap
Setting up swapspace version 1, size = 1073737 kB
no label, UUID=81eeae94-4fc6-404e-940a-6c14524fc3a8



Une fois les volumes créés, on peut passer à la configuration du Domain Guest.
Sur le Domain Host, on créé un fichier de configuration que l'on initialise avec les données suivantes:

vi /etc/xen/VM1:
name = "LinuxVM1"
kernel = "/boot/vmlinuz-2.6.18-6-xen-vserver-686"
ramdisk = "/boot/initrd.img-2.6.18-6-xen-vserver-686"
root ="/dev/hda1"
memory = 1024
cpus = "1"
disk = ['file:/dev/vg0/VM1-root,hda1,w','file:/dev/vg0/VM1-swap,hda2,w']
vif = ['ip=10.33.0.111, bridge=xenbr0', 'ip=192.168.0.111, bridge=xenbr1']
extra="3"



Quelques précisions sur les options:

C'est le grand moment, il est temp de tester de Domain Guest ainsi configuré!
xm create -c VM1 (avec VM1, le nom du fichier de configuration)

L'option -c permet d'avoir un mode console sur la machine virtuelle. L'initialisation du Domain Guest défile donc jusqu'au login. Première chose à faire: se connecter en root et changer le mot de passe (il se peut même qu'aucun mot de passe ne soit réclamé à la première connexion).

On en profite également pour mettre à jour le fichier /etc/hostname et surtout la configuration réseau:
vi /etc/network/interfaces

auto eth0
iface eth0 inet static
address 10.33.0.113
netmask 255.255.255.0
broadcast 10.33.0.255
network 10.33.0.0
gateway 10.33.0.254

auto eth1
iface eth1 inet dhcp



Depuis le Domain Host, on peut vérifier l'état de tous les domaines, leur durée de vie, ainsi que les ressources allouées à chaque domaine:

xm list
Name ID Mem VCPUs State Time(s)
Domain-0 0 3017 2 r----- 2974115.0
LinuxVM1 8 1024 1 -b---- 6.1


Etant donné que nous sommes en mode console, nous ne pouvons pas quitter la machine virtuelle depuis le Domain Guest. Il faut donc la quitter depuis le Domain Host:

xm destroy LinuxVM3 (avec LinuxVM1, le nom donné au Domain Guest)

On peut maintenant démarrer le Domain Guest sans console et s'y connecter en SSH:

xm create VM1
ssh root@10.33.0.111


Si la connexion ne passe pas, il suffit de se reconnecter au Domain Guest en mode console et de vérifier la configuration.

Si tout est OK, il ne reste plus qu'à configurer Xen pour démarrer les machines virtuelles automatiquement au démarrage. Pour chaque machine virtuelle, on ajoute un lien dans le gestionnaire de domaines de Xen. Exemple:

cd /etc/xen/auto/
ln -s ../VM1



Duplication d'un Domain Guest