LightcodeSysadmin Open Source

Introduction à libvirt

libvirt est une librairie contenant des outils pour la virtualisation, permettant notamment la création de machine virtuelle, la gestion du stockage ainsi que du réseau. libvirt est utilisable avec plusieurs hyperviseur tel que Xen, KVM, Qemu, ESXi… libvirt permet également de s’interfacer avec de multiples langages de programmation. Ce premier article décrira la mise en place d’un serveur de virtualisation simple avec libvirt que nous étendrons au fur et à mesure.

Introduction

libvirt est une interface entre l’utilisateur, un langage de programmation et les outils permettant la virtualisation. En effet, libvirt permet de gérer un hyperviseur, des unités de stockage, le réseau… Cet outil n’intègre pas d’hyperviseur, vous devrez installer le votre. Pour ma part, j’ai choisi pour mes articles d’utiliser KVM.

Dans cet article, je parlerais de “domaines”, c’est le terme qui est utilisé par libvirt pour parler de machine virtuelle. Il y a deux moyens d’interagir avec libvirt, soit grâce à un langage de programmation comme Python, C++ ou Java. L’autre moyen est d’utiliser l’outil en ligne de commande appelé virsh.

Installation

Pour installer libvirt, j’ai choisi de le compiler à partir des sources pour profiter des dernières fonctionnalités qui ne sont pas présentes dans les versions des dépôts de la distribution choisie. Par exemple, la version des dépôts de Debian Wheezy ne permet pas d’ajouter des volumes dans un domaine. L’installation par les dépôts permets toutefois d’avoir une installation plus simple et de pouvoir installer simplement les utilitaire de libvirt disponible tel que virt-install. La distribution que j’ai choisi d’utiliser est Debian Wheezy.

Installation par compilation

Il faut d’abord télécharger les sources sur libvirt.org.

Par exemple, j’ai téléchargé la version 1.1.4, je l’extrais et me rend dans le dossier :

$ wget http://libvirt.org/sources/libvirt-1.1.4.tar.gz
$ tar xvzf libvirt-1.1.4.tar.gz
$ cd libvirt-1.1.4

Avant la compilation, il faut installer les dépendances, en voici quelques unes :

# apt-get install -y libxml2-dev libyajl-dev libgnutls-dev \
    libdevmapper-dev libcurl4-gnutls-dev python-dev libnl-dev

Il est possible qu’il faille en ajouter, notamment si vous décidez d’activer des modules supplémentaires. Il faut maintenant configurer le logiciel avant de le compiler :

# ./configure --prefix=/usr --localstatedir=/var --sysconfdir=/etc --with-storage-iscsi \

L’option --with-storage-iscsi est une fonctionnalité de libvirt permettant de gérer les pools de stockage iSCSI que j’ai décidé d’activer.

Pour connaître la liste des options, n’hésitez pas à entrer cette commande :

$ ./configure --help

Une fois le logiciel configuré, il faut maintenant le compiler et l’installer :

# make && make install

Pour que le service démarre automatiquement, il faut ajouter le fichier libvirt-bin aux fichiers de démarrage :

# wget http://uploads.lightcode.fr/articles/26-Introduction-a-libvirt/libvirt-bin.init \
    -O /etc/init.d/libvirt-bin
# chmod +x /etc/init.d/libvirt-bin
# update-rc.d libvirt-bin defaults

Ajouter un fichier /etc/default/libvirt-bin :

start_libvirtd="yes"
libvirtd_opts="-d"

Il est possible d’ajouter une auto-complétion des commandes en exécutant ces commandes :

# wget http://uploads.lightcode.fr/articles/26-Introduction-a-libvirt/virsh.completion \
    -O /etc/bash_completion.d/virsh
# chmod +x /etc/bash_completion.d/virsh

Il sera nécessaire de recharger sa console pour que ce soit pris en compte.

Installation via les dépôts

Dans le cas d’une installation via les dépôts, une seule commande suffit :

# apt-get install libvirt-bin virtinst

Gestion des réseaux

Cette étape n’est pas obligatoire pour créer machines virtuelles. Mais je vous conseille de les utiliser lorsque que vous voulez mettre les machines virtuelles en réseau. libvirt permet de créer des réseaux de plusieurs types :

  • bridge : les interfaces réseaux des machines virtuelles sont connectées à un switch virtuel (ou bridge) créé avec des logiciels comme brctl ou Open vSwitch ;
  • nat : les machines sont connectées à un NAT et reçoivent une adresse IP qui sera translaté vers un réseau de sortie ;
  • route : le trafic des machines est routé sur le réseau extérieur ;

Les réseaux dans libvirt sont définis à l’aide de fichier XML, comme toutes les ressources. Voici un exemple de configuration du réseau net-br0, dans le fichier net-br0.xml :

<network>
  <name>net-br0</name>
  <forward mode="bridge" />
  <bridge name="br0" />
</network>

Les bridges utilisent le programme Linux brctl, il faut ajouter le bridge manuellement :

# brctl addbr br0

Pour ajouter ce réseau à libvirt :

# virsh net-define net-br0.xml
# virsh net-start net-br0
# virsh net-autostart net-br0

De même, la configuration du domaine, on ajoutera ces lignes dans la balise <devices> :

<interface type="network">
  <mac />
  <source network="net-br0" />
</interface>

Gestion du stockage

L’utilisation du stockage dans libvirt est également facultative. Il faut créer un pool dans lequel on créera des volumes. Les volumes sont les unités de stockage qui seront connectées aux domaines.

  • dir : le mode répertoire permet de stocker les fichiers dans un dossier sur un disque dur ;
  • iscsi : dans le mode iSCSI, la cible sera le pool et chaque LUN associé sera un volume. Ici, il n’est pas possible de créer de volume depuis la libvirt ;

Voici la documentation pour créer des pools et des volumes. Par exemple, on définit pool-local dans le ficher pool-local.xml qui décrit un pool de type “répertoire” :

<pool type="dir">
  <name>pool-local</name>
  <target>
    <path>/var/kvm/storage/pool-local</path>
  </target>
</pool>

Pour ajouter ce pool à libvirt :

# virsh pool-define pool-local.xml
# virsh pool-start pool-local
# virsh pool-autostart pool-local

Pour ajouter un volume à ce pool :

# virsh vol-create-as pool-local vm01-main.qcow2 12G --format qcow2
  • pool-local est le nom du pool ;
  • vm01-main.qcow2 est le nom du volume ;
  • 12G est la taille du disque ;
  • --format qcow2 est le format du fichier ;

Pour ajouter le disque dans le domaine, il faut ajouter ces lignes dans le fichier de définition de la VM :

<disk type="volume" device="disk">
  <driver name="qemu" type="qcow2" />
  <source pool="pool-local" volume="vm01-main.qcow2" />
  <target dev="vda" bus="virtio" />
</disk>

Le disque tel qu’il est défini ici ne fonctionnera pas si l’OS invité est Windows (sauf en utilisant des drivers). Pour définir le disque correctement sous Windows, il faut mettre un bus de données qu’il connaît, par exemple du S-ATA :

<disk type="volume" device="disk">
  <driver name="qemu" type="qcow2"/>
  <source pool="pool-local" volume="vm01-main.qcow2" />
  <target dev="hdb" bus="sata"/>
</disk>

Création de VMs

Définition du domaine

C’est lors de la définition du domaine que l’on va pouvoir décrire le matériel de la VM, ainsi que son nom. La définition du domaine varie d’un hyperviseur à l’autre, voici un exemple de définition sous KVM inspiré de la documentation :

<domain type="kvm">
  <name>testvm1</name>
  <memory>131072</memory>
  <vcpu>1</vcpu>
  <os>
    <type arch="x86_64" machine="pc-1.1">hvm</type>
    <boot dev="hd" />
  </os>
  <features>
    <acpi />
    <apic />
    <pae />
  </features>
  <clock offset="utc" />
  <devices>
    <emulator>/usr/bin/kvm</emulator>
    <!-- Insérer ici les différents devices qu'on a vu (réseau et stockage) -->
    <graphics type="vnc" port="-1" autoport="yes" listen="0.0.0.0" keymap="fr" />
  </devices>
</domain>

Il faudra ajouter à ce fichier, les différents éléments que nous avons vus comme le stockage ou le réseau. Il faut ensuite passer à l’installation du système d’exploitation.

Installation de l’OS

Une méthode classique pour installer un OS est d’utiliser d’une image ISO. Pour ajouter un lecteur DVD virtuel à notre VM, on le définit dans la balise <device> de notre domaine :

<disk type="file" device="cdrom">
  <source file="/path/to/image.iso" />
  <target dev="hda" />
  <readonly />
</disk>

Il faut ensuite éditer la balise <os> pour forcer le boot sur le DVD :

<os>
  <!-- Autre propriétés... -->
  <boot dev="cdrom" />
  <boot dev="hd" />
</os>

Il faut mettre les balises dans l’ordre de préférence de démarrage. Dans ce cas, le domaine va essayer de démarrer sur le DVD (cdrom) puis sur le disque dur (hd). Pour poursuivre l’installation, vous devez démarrer la VM en l’ajoutant à libvirt :

# virsh define vmtest1.xml
# virsh start vmtest1

La commande virsh vncdisplay vmtest1 vous permettra de connaître le numéro d’écran sur lequel connecter un client VNC. Exemple avec l’outils gvncviewer :

$ gvncviewer server.example:0

Note : le 0 ici représente le numéro d’écran VNC et non un port TCP ou UDP.

Conclusion

Nous avons vu dans cet article que libvirt est une librairie de virtualisation et que celui-ci permet de gérer les pools de stockage et les réseaux de manière simple. Nous avons également traiter l’installation d’un OS à partir d’une image ISO.