Virtualisation avec KVM via libvirt

De HomeServer.DIY.
Version du 17 septembre 2013 à 22:40 par Tom23 (discuter | contributions)
(diff) ← Version précédente | Voir la version courante (diff) | Version suivante → (diff)
Aller à : Navigation, rechercher

Utiliser des machines virtuelles sur un serveur a plusieurs avantages : isolation complète des services, utilisation de plusieurs systèmes d'exploitation en parallèle (typiquement Windows et une ou plusieurs distributions Linux), sauvegardes et restaurations simplifiées. S'il existe plusieurs distributions Linux permettant de manipuler des machines virtuelles au travers d'une interface web (voir la liste des distributions Linux pour ça), il peut être parfois intéressant voire nécessaire de passer par d'autres moyens, un peu plus empiriques certes, notamment avec la sacro-sainte ligne de commande. Un de ces moyens d'y arriver est la libvirt.


Sommaire

Préambule et définitions

Le noyau Linux possède sa propre infrastructure de virtualisation, nommée Kernel Virtualization Module (KVM pour la suite). Utilisée au travers de l'outil qemu, il permet de lancer des machines virtuelles avec des configurations diverses et variées, jusqu'à l'architecture du CPU que qemu peut émuler au besoin. Mais tout puissant qu'il est, le couple qemu/KVM est aussi particulièrement difficile d'accès pour les moins aguerris à la ligne de commande. Juste un exemple de commande qu'il faut lancer pour avoir une vm en ligne :

# /usr/bin/kvm -S -M pc-1.1 -enable-kvm -m 1024 -smp 1,sockets=1,cores=1,threads=1 \
  -name kvm_vox -uuid 06cb6b1d-2f82-e9ff-7d93-14bffbc06e69 -no-user-config -nodefaults \
  -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/kvm_vox.monitor,server,nowait \
  -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown \
  -drive file=/home/kvm_vox/kvm_vox.raw,if=none,id=drive-ide0-0-0,format=raw \
  -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 \
  -netdev tap,fd=20,id=hostnet0 -device e1000,netdev=hostnet0,id=net0,mac=02:00:00:f6:3b:42,bus=pci.0,addr=0x3 \
  -chardev pty,id=charserial0 -vnc 127.0.0.1:0,password -k fr -vga cirrus 

Oui, on peut appeler ça imbuvable. Fort heureusement, Red Hat a lancé un projet qui a permis de grandement simplifier la création et la gestion des machines virtuelles, la libvirt. Cette bibliothèque regroupe plusieurs outils, dont un très puissant qui va très vite devenir vôtre ami, virsh. Pour le reste des fonctionnalités, je vous renvoie au site officiel du projet [ 1 ].

Cet outil va vous servir aussi bien à préparer la configuration réseau de la machine hôte qu'à créer, modifier, importer vos machines virtuelles. Il est aussi utilisable pour manipuler des snapshots, mais ce n'est pas au programme de cette première prise en main.

Dernière précision, la libvirt permet de manipuler différentes technologies de virtualisation (xen, kvm, lxc...). Le jour où vous devez, pour diverses raisons, changer de format de machine virtuelle, vous pourrez continuer à utiliser les mêmes commandes !


Préparation

Il faut bien évidemment un matériel supportant la virtualisation, et donc un CPU possédant les instructions idoines. Pour vérifier cela, on peut utiliser cette commande emprunté à une connaissance Twitter, à savoir Nicolargo (qui a aussi fait une introduction à libvirt sur son blog [ 2 ]) :

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

Pas besoin de beaucoup d'explications, si ça affiche "OK", vous pouvez continuer, si ça affiche "KO", pas de bol. Vous pouvez continuer à lire, mais ça ne restera que de la théorie, vous ne pourrez pas expérimenter correctement le reste de cette introduction au monde merveilleux de la virtualisation.

Cette présentation va se baser sur une Debian Wheezy (7.1), aka l'actuelle version stable au moment où j'écris ces lignes. La plupart des commandes sont effectuées en root, et sont transposables à d'autres distributions (du moment que les logiciels sont les mêmes). L'interface réseau utilise une adresse IPv4 fixe. Ce qui est conseillé pour un serveur hébergeant des services, et donc une ou plusieurs vms dans le cas présent. Les seuls paquets nécessaires au fonctionnement à installer sont libvirt-bin, virtinst, qemu-kvm. Votre gestionnaire de paquets s'en chargera (je suis un grand fan inconditionnel d'apt-get). Dans mon cas, c'est simple :

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

Petite précision avant de commencer vraiment : toutes les commandes virsh données sont tapées depuis le shell de la distribution (bash le plus souvent). Mais virsh peut lui-même fonctionner en mode "shell", simplement en l'invoquant avec virsh sans options ni paramètres. Il suffira ensuite de saisir les commandes sans le 'virsh' devant. Libre à vous de choisir comment vous allez travailler.

On peut maintenant passer aux choses sérieuses.


Mise en place du réseau

Pour commencer, la méthode la plus simple pour relier vos machines à vôtre réseau est de créer un pont, sur lequel toutes vos machines virtuelles vont se brancher. La méthode manuelle consiste à modifier un fichier texte, à savoir le fichier /etc/network/interfaces, et à redémarrer le réseau pour que le bridge soit opérationnel. Plus simple, la création d'un bridge avec virsh se résume à une seule commande :

# virsh iface-bridge eth0 vbr0

C'est déjà beaucoup plus court, n'est-ce pas ? La suite sera un peu plus fournie, notamment la création de l'image disque. C'est d'ailleurs la prochaine étape. Mais avant ça, on termine en activant l'IP forwarding (que je sais pas traduire en français en deux mots), qui consiste à dire au noyau de transférer tous les paquets IP qui ne sont pas directement destinés à la machine hôte. Pour ça, deux méthodes à utiliser conjointement, la première est immédiate, la deuxième permet de garder en mémoire le réglage au fil des différents redémarrages qui parsèmeront la vie de votre serveur.

# echo 1 > /proc/sys/net/ipv4/ip_forward

# echo "net.ipv4.ip_forward=1" >>/etc/sysctl.conf

J'arrêterais ici les réglages, car il est possible de gérer le réseau de plusieurs manières, et pour cette première approche je me base sur deux cas d'utilisation les plus courants :

  • le cas d'un serveur dédié disposant de plusieurs adresses IP publiques pour en attribuer une directement à votre VM (moyennant l'attribution d'une adresse MAC virtuelle associée à une des IP supplémentaires)
  • le cas d'un serveur derrière un routeur NAT, typiquement une machinbox, qui est capable d'attribuer une ip privée par DHCP (il est alors nécessaire de créer une ou plusieurs règles de redirection au niveau du routeur)

Si par exemple vous disposez d'un serveur ne disposant pas de plusieurs adresses IP, il est possible de NATer ces mêmes machines à la manière du routeur, mais directement au niveau de la machine hôte, en ajoutant plusieurs règles à iptables. Nicolargo a détaillé ces fameuses règles.


Image disque

Il faut maintenant créer un disque dur "virtuel", qu'on appelle une image disque. C'est une des rares étapes qui ne se fera pas avec virsh directement. Qemu sait manipuler plusieurs formats, les répandus vmdk (VMWare), vdi (Virtualbox), et moins répandus raw (n'utilise que l'espace réel des données), cloop (reproduit le format des liveCD), qcow2 (format natif de qemu, utilise le Copy-on-write, remplaçant du format qcow utilisé avant). Ce dernier est le format conseillé, car il facilite notamment la prise de snapshots. On commence par créer un dossier qui contiendra l'image disque. J'ai choisi de la mettre dans le dossier /home, qui est souvent, en tout cas dans mon cas, sur la partition la plus étendue du/des disques :

# mkdir /home/vm

Ensuite on se place dedans, et on crée l'image à proprement parler. C'est qemu qui nous donnes les outils, à la fois pour créer mais aussi pour convertir une image :

# cd /home/vm

# qemu-img create -f qcow2 debian7server.qcow2 10G

Le nom et la taille du disque seront à adapter à vos besoins et/ou envies.


Création de la VM

Créer la VM est facile et rapide en soit, mais pour y installer un système d'exploitation (au hasard, Debian 7 -- comme c'est étonnant), il faut récupérer l'image ISO le permettant. Toujours dans le dossier /home/vm, on va créer un sous-dossier "iso", puis télécharger la fameuse image :

# mkdir /home/vm/iso

# cd /home/vm/iso

# wget http://cdimage.debian.org/debian-cd/7.1.0/amd64/iso-cd/debian-7.1.0-amd64-CD-1.iso

La machine d'exemple que j'utilise a un CPU 64bit, et donc j'utilise l'image disque supportant cette architecture; c'est aussi l'architecture utilisée pour le système hôte installé. Vous adapterez donc à votre matériel.

NB : un CPU 64bit peut indépendamment faire tourner des VM 32 et/ou 64bit; un CPU 32bit ne saura faire tourner que des VM 32bit. Bien que les CPU 32bit uniquement avec virtualisation soient rares, il vaut mieux s'en assurer avant de se demander pourquoi ça ne parche pas.

Inutile de rappeler que l'image pesant 650Mo, il est plus pratique d'avoir une grosse connexion (les serveurs dédiés ont l'avantage d'avoir souvent 100Mbps, si ce n'est plus), ou un bon stock de M&Ms. Bref, une fois l'image récupérée, on peut s'atteler à la création de la machine virtuelle. Dans les paquets que je vous avais demandé d'installer au tout début, il y avait un outil appelé virt-install. Voici donc comment s'en servir :

# virt-install --vcpus=2 --ram=1024 --name=debian7server --file=/home/vm/debian7server.qcow2 \
  --cdrom=/home/vm/iso/debian-7.1.0-amd64-CD-1.iso --hvm --vnc --network bridge:vbr0

Dans cette commande, je vous laisse modifier à votre guise le nom de la vm, le nombre de cpus "virtuels" ou la quantité de ram allouée, et bien entendu les images disques et ISO. La machine va donc être créée, démarrée, et l'installation de Debian donc lancée. Pour terminer l'installation, il suffit le lancer un client VNC, soit en local si vous opérez physiquement sur la machine, soit à distance en contactant l'ip de l'hôte.


Création depuis une image disque existante

Il est possible aussi de créer une VM avec une image disque déjà utilisée, sans forcément passer par le fichier de configuration. Au hasard, quand vous utilisez une image disque provenant d'une VM VMWare. Quand on revient du bon côté de la force, c'est un gain de temps appréciable. On en revient donc à virt-install, mais la ligne sera un peu différente :

# virt-install --import --disk path=/home/vm/debian7server.qcow2 --vcpus=2 --ram=1024 \
  --name=debian7server --hvm --vnc --network bridge:vbr0


Réglages et gestion au quotidien

Vous allez me dire que jusqu'à maintenant, nous n'avons pas beaucoup utilisé virsh. C'est vrai. Vous allez donc maintenant voir à quoi, en dehors de la création du bridge, peut servir cet outil. On va commencer par activer le démarrage automatique en même temps que la machine. Autant à la main c'est vraiment long (création d'un script à placer dans init.d, ajout dans insserv), autant là... :

# virsh autostart debian7server

Avouez qu'il est très difficile de faire plus simple. Pour démarrer une vm (un domaine dans le jargon "libvirt"), là encore la commande est des plus triviales :

# virsh start debian7server

Pour la redémarrer, c'est tout aussi évident :

# virsh reboot debian7server

De manière similaire, pour l'arrêter (correctement), il suffit de saisir :

# virsh shutdown debian7server

Pour ceux qui seraient intrigué par le "correctement", virsh envoie un signal ACPI pour que l'OS invité s'arrête normalement, un peu comme quand vous appuyez sur le bouton d'alimentation de votre machine. Si jamais ça ne marche pas et que vous voulez "couper le courant" (ce qui est la seule chose à faire si le système invité ne répond plus), la commande est là encore d'une simplicité déconcertante, même si son nom peut faire peur au premier abord :

# virsh destroy debian7server

Non, vous ne venez pas de détruire votre machine virtuelle, rassurez-vous. C'est l'équivalent du 'poweroff' de Virtualbox si vous voulez.

Pour mettre en pause une machine virtuelle, par exemple au cas où vous voudriez créer une sauvegarde de l'image disque, et pour la remettre en route, ces deux commandes vous serons d'une grande aide :

# virsh suspend debian7server

# virsh resume debian7server

Bref, virsh regorge de paramètres, que vous pouvez découvrir sur la page de manuel [ 3 ].


La configuration XML

Allons un peu plus loin. Une des forces de la libvirt, c'est de stocker les informations nécessaires au fonctionnement de la VM dans un fichier de configuration au format XML. Ce fichier est modifiable et permet d'ajouter ou de modifier les caractéristiques du matériel configuré, ainsi que les périphériques attachés. Pour modifier ce fichier simplement, plutôt que de chercher son emplacement, on invoque là encore virsh (vous voyez qu'on s'en sert plus souvent maintenant) :

# virsh edit debian7server

Cette commande invoque votre éditeur de texte par défaut, vi dans mon cas (pour connaitre les commandes de base de cet éditeur, je vous renvoie à une introduction [ 4 ]). Dans mon cas, sur un serveur dédié avec une IP failover chez OVH, j'ai ajouté l'adresse MAC associée dans la section réservée à la carte réseau, ainsi que le modèle de la carte (apparemment j'avais des soucis si je ne le spécifiais pas) :

(...)
<interface type='bridge'>
 <mac address='02:00:00:2f:7a:61'/>
 <source bridge='vbr0'/>
 <model type='e1000'/>
 <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</interface>
(...)


Avantage, après avoir enregistré la configuration modifiée, virsh la vérifie pour valider les modifications avant de les appliquer. Et inutile de rappeler que ces modifications seront plus efficaces avec la VM éteinte. Ce fichier de configuration XML permet aussi de créer manuellement des machines virtuelles sans forcément lancer une installation. Et là pour le coup, c'est virsh qui fait tout le travail. On commence donc par récupérer une copie du fichier de configuration de notre vm fraichement installée :

# virsh dumpxml debian7server > /home/vm/debian7server.xml

Vous pouvez ensuite modifier ce fichier pour coller aux besoins de la future machine virtuelle. Nom, image disque, réseau, mémoire vive, nombre de CPUs, bref tout ce que peut contenir ce fichier. Ensuite, pour créer la nouvelle VM, il suffit de demander à virsh de se baser sur ce fichier modifié :

# virsh create debian7server.xml

Bien évidemment je conseille de changer le nom du fichier modifié histoire de ne pas se mélanger les pinceaux. A noter que virsh lancera immédiatement la VM après sa création. Si vous voulez simplement la créer, mais sans la démarrer, il vaut mieux utiliser l'option 'define' :

# virsh define debian7server.xml


Interface graphique

Ce tuto est essentiellement tourné vers la ligne de commande, parce que sur un serveur auquel on accède le plus souvent avec un client SSH, c'est la méthode la plus évidente. Mais si par chance vous utilisez une distribution Linux sur votre machine cliente, il existe un client graphique capable aussi bien de manipuler des VMs locales que celles de votre serveur. Car la libvirt, lors de son installation, lance un daemon, accessible à distance, aussi bien en ligne de commande qu'avec le client graphique.

Son doux nom est virt-manager, et est installable par le biais du gestionnaire de paquets, le même qui vous a servi à installer la libvirt. Ou comme il s'agit de travailler en mode graphique, de votre gestionnaire graphique de logiciels.


Interface de Virt Manager
Interface de Virt manager


Pour plus de détails concernant son utilisation, je vous renvoie au site officiel du projet [ 5 ].


Conclusion

Cette introduction au monde merveilleux de la libvirt est maintenant terminée. Vous avez en main le nécessaire pour démarrer correctement. Et ce même si la partie réseau mériterait d'être plus fournie (voir le blog de Nicolargo pour la mise en palce n'un NAT local). La libvirt simplifie grandement les choses, et comme cet article n'est qu'une introduction, je n'ai pas beaucoup fouillé ses possibilités ici. Car le nombre de technologies de virtualisation qu'il supporte est tout simplement hallucinant (la liste est sur le site officiel), tout comme les possibilités au niveau du stockage, et le fait qu'il est administrable en local et à distance aussi bien en ligne de commande qu'au travers de virt-manager ajoute à son charme (même si ce dernier n'est dispo que sous Linux pour l'instant).


Références