Apprentissage de Qemu/LibVirt par l'exemple

Auteur

Valentin Pourchet

- Titre : Apprentissage de Qemu/LibVirt par l'exemple

- Auteur : Valentin Pourchet

- Parution : 23 décembre 2013

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Lana.Bauer. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Installation de Qemu/KVM

- II-A. Création de sa première machine virtuelle (VM)

- II-B. Utilisation de sa VM

- II-C. Niveau performance ?

- III. Gestion en ligne de commande

- III-A. Création de l'image disque

- III-B. Création de la VM

- IV. Gestion du réseau par translation

- V. Petite note pour les invités « BSD »

- VI. Sources utilisées lors de la rédaction de cet article

I - Introduction

Certains travaux nécessitent de travailler sur plusieurs systèmes d'exploitation différents. Plutôt que de monter une salle machine dans ma maison (pas sûr que ma compagne soit d'accord), j'ai donc opté pour une virtualisation sur un serveur dédié OVH qui a le gros avantage de disposer d'une RAM volumineuse de 16 Go (pour une machine en l'an 2012). Travaillant la plupart du temps sous Linux, mon choix s'est donc porté sur la solution Qemu/KVM (Kernel-based Virtual Machine).

II - Installation de Qemu/KVM

Pour que Qemu/KVM ait des performances acceptables, il faut vérifier que votre processeur est compatible avec les extensions de virtualisation. Sous Linux, il est facile de vérifier cela avec la ligne de commande suivante.

egrep '^flags.*(vmx|svm)' /proc/cpuinfo >/dev/null && echo OK || echo KO

Sur mon serveur de test (Kimsufi 16 Go chez OVH) pas de problème de ce côté-là. J'obtiens un beau OK.

Le serveur peut donc supporter la virtualisation hardware. Chez OVH, le noyau par défaut est statique, il n'est donc pas possible d'ajouter dynamiquement des modules (comme le kvm_intel par exemple). Il faut donc suivre cette procédure. La dernière version des noyaux semble intégrer par défaut les modules KVM.

On peut ensuite passer à l'installation des briques logicielles (environ 257 Mo à télécharger) :

- qemu-kvm - virtualisation complète sur les machines x86 ;

- virtinst - programmes pour créer et cloner des machines virtuelles ;

- libvirt-bin - lprogrammes pour la bibliothèque libvirt.

On utilise les versions disponibles dans les dépôts Debian :

sudo apt-get install qemu-kvm virtinst libvirt-bin

Un petit redémarrage de la machine pour être sûr que tous les modules sont chargés avant de poursuivre.

II-A - Création de sa première machine virtuelle (VM)

Nous allons commencer par créer une machine virtuelle avec comme système hôte un Ubuntu Desktop 11.10. Une machine virtuelle a besoin d'un conteneur dans lequel elle va pouvoir s'exécuter : ce conteneur s'appelle une image disque. Ensuite, il faudra installer le système hôte à l'intérieur de cette image disque.

Il est possible d'utiliser la ligne de commande pour effectuer ces opérations (ce qui ouvre la voie à une automatisation par scripts). Nous aborderons cela un peu plus loin dans l'article. Pour commencer, nous allons utiliser le module libvirt-manager qui propose une interface graphique (GTK) permettant d'administrer à distance (via un tunnel SSH) son serveur d'hypervision Qemu/KVM.

On commence par vérifier que le démon d'administration est bien lancé sur le serveur d'hypervision (ce qui devrait être le cas si vous avez suivi les étapes d'installation de ce billet) :

sudo /etc/init.d/libvirt-bin status
Checking status of libvirt management daemon: libvirtd running.

Ensuite il faut ajouter votre utilisateur (nicolargo dans mon cas) dans les groupes « libvirt » et « kvm » :

sudo usermod -a -G libvirt nicolargo
sudo usermod -a -G kvm nicolargo

Sur la machine GNU/Linux cliente (disposant d'une interface graphique), il faut installer les packages (par exemple sous Debian/Ubuntu) :

sudo apt-get install virt-manager

Au lancement du client, il faut cliquer sur le menu File > Add connection…

Puis paramétrer la connexion vers votre serveur :

Notre serveur est alors disponible dans la liste, on peut alors configurer ses propriétés :

On configure le type de réseau que l'on va utiliser. Comme je ne dispose que d'une seule adresse publique sur mon serveur OVH Kimsufi, j'utilise la translation d'adresse (voir l'explication dans un chapitre suivant) qui est configurée par défaut :

Puis on configure les répertoires où l'on pourra trouver les ISO pour l'installation des machines hôtes :

Et voilà le résultat après téléchargement de quelques images ISO depuis le répertoire ~/iso (le serveur disposant d'un accès 100 Mbs direct sur Internet, cela va assez vite !).

On peut passer à la création de la VM proprement dite en cliquant sur le bouton Create a new virtual machine . On accède alors à un wizard :

On entre le nom de la VM (sans espace) :

Puis l'image ISO qui va nous servir pour l'installation du système d'exploitation (le  Browse sur le serveur peut prendre un certain temps) :

On définit ensuite les ressources de la VM (CPU et mémoire). À noter que la limite à 2 Go de RAM sur ma configuration de test :

On donne ensuite la taille de l'image disque qui contiendra notre VM. Je conseille 16 Go pour les OS récents.

On finalise la configuration côté réseau (NAT) et hyperviseur (KVM) :

Une fenêtre avec un déport d'affichage devrait alors apparaître et l'installation du système invité (Ubuntu 11.10) commencer :

Il ne vous reste plus qu'à finaliser l'installation !

II-B - Utilisation de sa VM

Une fois l'installation de la VM effectuée (voir le chapitre précédent). Celle-ci devrait figurer dans la liste proposée par Virtual Machine Manager. Pour la lancer, il faut sélectionner la VM puis cliquer sur le bouton « play » (Power On the virtual machine) :

Et voilà le travail :

II-C - Niveau performance ?

Il ne faut pas s'attendre à des miracles. La virtualisation par Qemu/KVM bien qu'ayant fait de gros progrès dans les dernières versions reste en dessous d'une solution comme VmWare ou Xen. Elle est par contre suffisante dans mon cas où je souhaite valider des procédures et des logiciels système et réseau.

III - Gestion en ligne de commande

III-A - Création de l'image disque

On commence par créer un répertoire ~/vm qui va contenir toutes mes images disques :

mkdir ~/vm

Puis on utilise la commande qemu-img pour générer l'image disque « vierge » :

cd ~/vm
qemu-img create -f qcow2 debian6server.qcow2 16G

Cette dernière commande va donc générer une image disque nommée debian6server.qcow2 de type qcow2 (voir ci-dessous la liste des types disponibles sous Debian 6) avec une taille maximale de 16 gigaoctets.

Sur mon système, la liste des « types » d'images disques est la suivante :

- raw : pas de compression, l'image disque est directement « dumpée » dans un fichier host_device ;

- qcow2 : format par défaut de Qemu (Qemu Image Format) ;

- qcow : ancien format utilisé par Qemu (ne pas utiliser pour la création de nouvelles images disques) ;

- vdi : format compatible avec VirtualBox ;

- vmdk : format compatible avec VMWare ;

- vpc : format compatible avec VirtualPC ;

Il est possible de convertir une image d'un format à un autre. Par exemple, si vous avez une image au format VMWare et que vous voulez la convertir vers un format Qcow2, il suffit de saisir la commande suivante :

qemu-img convert -f vmdk disk.vmdk -O qcow2 disk.qcow2

III-B - Création de la VM

Pour installer la VM, nous avons besoin de l'image ISO du système d'exploitation à installer (Debian 6 server dans mon exemple). On va donc télécharger cette image sur notre serveur (c'est dans ces moments-là que l'on est heureux d'avoir un serveur avec une connexion à 100 Mbps vers Internet…) :

mkdir ~/iso
cd ~/iso
wget http://cdimage.debian.org/debian-cd/6.0.3/i386/iso-cd/debian-6.0.3-i386-CD-1.iso

Maintenant que nous disposons de l'image disque ~/vm/debian6server.qcow2 et du média d'installation ~/iso/debian-6.0.3-i386-CD-1.iso, nous allons créer la machine virtuelle en utilisant la couche d'abstraction libvirt.

Pourquoi utiliser libvirt plutôt que d'utiliser directement les commandes équivalentes Qemu ? Si demain vous décidez de changer votre système de virtualisation, vos procédures/scripts resteront les mêmes. En effet libvirt communique de manière transparente vers un grand nombre de systèmes de virtualisation en proposant en bonus une API de développement (notamment en Python).

On utilise donc la commande suivante pour créer la VM :

virt-install --ram=2047 --name=debian6server --file=/home/nicolargo/vm/debian6server.qcow2 --cdrom=/home/nicolargo/iso/debian-6.0.3-i386-CD-1.iso --hvm --vnc --noautoconsole

Cette commande va donc créer une VM nommée debian6server qui disposera de 2 Go de RAM (d'où l'avantage de faire tourner votre hyperviseur sur une machine disposant de pas mal de RAM / 16 Go dans mon cas sur une Kimsufi 16G).

Si tout est OK, le message suivant devrait s'afficher :

Domain installation still in progress.
You can reconnect to the console to complete the installation process.

Pour l'accès à la console (déport VNC via un tunnel SSH), je vous conseille d'utiliser l'interface d'administration de libvirt que vous pouvez lancer sur un PC client disposant d'une interface graphique.

IV - Gestion du réseau par translation

Mon serveur dispose d'une seule adresse IP publique. Les VM auront donc des adresses IP privées et l'on utilisera la translation d'adresse (NAT) pour permettre au VM de sortir sur Internet (voir ce billet pour la création d'un réseau par NAT).

Certaines configurations sont à faire sur votre serveur :

sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

sudo vi /etc/sysctl.conf
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

Si vous utilisez des règles Iptables, alors il faut ajouter les lignes suivantes dans votre script (attention de bien vérifier que votre script ne repositionne pas la valeur net.ipv4.ip_forward à 0… je me suis fait avoir) :

# Qemu rules (NAT VM and allow VM to DHCP)
/sbin/iptables -t nat -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE
/sbin/iptables -A INPUT -i virbr0 -j ACCEPT
/sbin/iptables -A OUTPUT -o virbr0 -j ACCEPT
/sbin/iptables -A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT
/sbin/iptables -A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT
/sbin/iptables -A INPUT -i virbr0 -p udp --dport 67:68 --sport 67:68 -j ACCEPT
/sbin/iptables -A FORWARD -d 192.168.122.0/24 -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT
/sbin/iptables -A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT
/sbin/iptables -A FORWARD -i virbr0 -o virbr0 -j ACCEPT
echo 1 > /proc/sys/net/ipv4/ip_forward

V - Petite note pour les invités « BSD »

Pour un invité sous OpenBSD, il faut penser à effectuer les actions suivantes pour faire fonctionner correctement la carte réseau :

- arrêter la VM ;

- éditer le fichier /etc/libvirt/qemu/OpenBSD_5.0.xml ;

<interface type='network'>
...
<model type='e1000'>
</interface>

- Relancer la VM.

VI - Sources utilisées lors de la rédaction de cet article

- Le manuel officiel de Qemu

- Le Wiki de libvirt

- Un article de Matthieu Vogelweith

- Le site officiel de libVirt

- KVM par l'exemple chez Frédéric

- Libvirt and IpTables