Aller au contenu
English
English
Virtualisation medium

Stockage KVM/libvirt : pools, volumes et formats

50 min de lecture

Logo KVM

Où sont stockés les disques de vos VMs ? Quel format choisir entre RAW et QCOW2 ? Ce guide explique le modèle de stockage libvirt : les pools (conteneurs) et les volumes (disques), pour que vous sachiez toujours où sont vos données.

ConceptCe que c'estExemple
PoolConteneur de disques/var/lib/libvirt/images/
VolumeUn disque individuelubuntu-test.qcow2

Ces deux points suffisent, le stockage libvirt ne demande aucun paquet supplémentaire. Le second compte plus qu'il n'y paraît : sans LIBVIRT_DEFAULT_URI, virsh ouvre une session utilisateur qemu:///session, qui porte ses propres pools et ne voit pas ceux du système. Un pool default introuvable vient presque toujours de cette confusion de connexion.

  • La différence entre storage pool et volume
  • Les types de pools (directory, LVM, ZFS...)
  • Choisir entre RAW et QCOW2
  • Créer et gérer des pools et volumes avec virsh

libvirt abstrait le stockage en deux niveaux. Un pool est un espace de rangement déclaré à libvirt : un répertoire, un Volume Group LVM ou un dataset ZFS. Un volume est un disque individuel qui vit dans ce pool. Cette séparation permet à libvirt de connaître la capacité restante avant de créer un disque, et d'appliquer au fichier créé les permissions attendues par l'hyperviseur.

Architecture stockage libvirt : un Storage Pool contient plusieurs volumes (disques qcow2/raw)

Pourquoi cette abstraction ?

  • Uniformité : mêmes commandes quel que soit le backend (fichier, LVM, ZFS)
  • Gestion : libvirt sait où trouver les disques, leur taille, leur disponibilité
  • Portabilité : les VMs référencent des volumes, pas des chemins absolus

Le type de pool se choisit au moment de sa définition et ne se change plus ensuite : pour en changer, il faut redéfinir le pool. Lisez la colonne « Cas d'usage » avant la colonne « Complexité », c'est elle qui tranche. La colonne « Type » donne le mot-clé exact attendu par virsh, qui ne colle pas toujours au nom courant de la technologie : un pool LVM se déclare logical, un partage NFS se déclare netfs. Écrire lvm ou nfs fait échouer la commande sur Invalid value for attribute 'type' in element 'pool'. dir, zfs et iscsi, eux, s'écrivent tels quels. La liste complète des types reconnus par votre version est donnée par virsh pool-capabilities, qui les énumère sous forme d'éléments <pool type='...'>.

TypeBackendCas d'usageComplexité
dirRépertoireLab, homelabSimple
logicalVolume Group LVMProduction, performanceMoyen
zfsDataset ZFSNAS, snapshots natifsMoyen
iscsiTarget iSCSISAN, datacenterAvancé
netfsPartage NFS ou CIFSStockage partagéMoyen

Après installation de libvirt, le pool default pointe vers /var/lib/libvirt/images/.

C'est la première commande à lancer en cas de problème de stockage. L'option --all est importante : sans elle, virsh masque les pools inactifs, et un pool défini mais non démarré passe inaperçu. Deux colonnes comptent ensuite, State doit valoir active pour que les volumes soient utilisables, et Autostart doit valoir yes pour que le pool revienne après un redémarrage de l'hôte.

Fenêtre de terminal
virsh pool-list --all

Sortie réelle :

Name State Autostart
-------------------------------
default active yes

pool-info répond à la question qui provoque le plus d'échecs de création de VM : reste-t-il assez de place ? Regardez Available avant toute création de volume. Ces chiffres reflètent le système de fichiers sous-jacent, pas une réservation propre à libvirt : sur un pool de type répertoire, ils bougent dès que n'importe quel autre processus écrit sur la même partition.

Fenêtre de terminal
virsh pool-info default

Sortie réelle :

Name: default
UUID: 20e70471-c81e-484a-9b5f-dac1e4c856a5
State: running
Persistent: yes
Autostart: yes
Capacity: 294,73 GiB
Allocation: 177,23 GiB
Available: 117,50 GiB

Décryptage :

ChampSignification
State: runningLe pool est actif et utilisable
Persistent: yesDéfini de façon permanente
Autostart: yesDémarre automatiquement au boot
CapacityTaille totale du stockage
AllocationEspace utilisé
AvailableEspace libre

Le XML est la source de vérité du pool, celle qui est écrite sur disque et rejouée au démarrage de libvirt. On le consulte pour deux raisons : retrouver le chemin réel derrière un nom de pool, et vérifier les permissions appliquées au répertoire cible, qui expliquent la plupart des erreurs Permission denied au démarrage d'une VM.

Fenêtre de terminal
virsh pool-dumpxml default

Sortie réelle :

<pool type='dir'>
<name>default</name>
<uuid>20e70471-c81e-484a-9b5f-dac1e4c856a5</uuid>
<capacity unit='bytes'>316464824320</capacity>
<allocation unit='bytes'>190303780864</allocation>
<available unit='bytes'>126161043456</available>
<source>
</source>
<target>
<path>/var/lib/libvirt/images</path>
<permissions>
<mode>0711</mode>
<owner>0</owner>
<group>0</group>
</permissions>
</target>
</pool>

Points clés :

  • type='dir' : pool de type répertoire
  • <path>/var/lib/libvirt/images</path> : emplacement des fichiers disque

Le pool default vit sur la partition système, ce qui devient un problème dès que les disques de VM pèsent des dizaines de gigaoctets. Créer un pool dédié sur un autre disque isole cette croissance. La séquence est toujours la même quel que soit le type : définir, construire, démarrer, activer au boot. Sauter l'étape pool-autostart est l'oubli classique, le pool disparaît alors au redémarrage et les VMs refusent de démarrer.

Pour stocker les VMs ailleurs, par exemple sur un disque dédié, il suffit d'un répertoire et des quatre commandes virsh de la séquence. Le mode 711 posé sur ce répertoire n'est pas décoratif : il accorde le droit de traverse sans le droit de lister, ce qui suffit au processus QEMU pour ouvrir un disque dont il connaît le chemin. C'est le mode que porte déjà le pool default, comme le montre son XML plus haut.

  1. Créer le répertoire

    Fenêtre de terminal
    sudo mkdir -p /data/vms
    sudo chown root:root /data/vms
    sudo chmod 711 /data/vms
  2. Définir le pool

    Fenêtre de terminal
    virsh pool-define-as vms dir --target /data/vms

    Sortie : Pool vms defined

  3. Construire le pool (initialise le répertoire si nécessaire)

    Fenêtre de terminal
    virsh pool-build vms
  4. Démarrer le pool

    Fenêtre de terminal
    virsh pool-start vms
  5. Activer le démarrage automatique

    Fenêtre de terminal
    virsh pool-autostart vms
  6. Vérifier

    Fenêtre de terminal
    virsh pool-list --all
    Name State Autostart
    -------------------------------
    default active yes
    vms active yes

Un pool logical ne crée pas le Volume Group, il adopte un VG existant. Deux options le distinguent du pool répertoire : --source-name désigne le nom du VG côté LVM, --target le chemin sous lequel ses volumes apparaissent, ici /dev/vg_vms. L'étape pool-build disparaît de la séquence puisque le groupe est déjà construit ; il reste à démarrer le pool et à l'activer au boot.

Fenêtre de terminal
# Supposons un VG nommé "vg_vms"
virsh pool-define-as lvm-pool logical --source-name vg_vms --target /dev/vg_vms
virsh pool-start lvm-pool
virsh pool-autostart lvm-pool

Le format se choisit à la création du volume et conditionne les fonctionnalités disponibles pour toute la vie du disque. La ligne de partage est nette : QCOW2 apporte les snapshots et l'allocation à la demande, RAW ne fait rien d'autre que stocker des octets, et va donc légèrement plus vite. Un changement d'avis reste possible après coup avec qemu-img convert, mais impose d'arrêter la VM et de disposer du double de l'espace le temps de la conversion.

FormatAvantagesInconvénientsCas d'usage
RAWPerformance maximale, simplePas de snapshots, taille fixeProduction I/O intensif
QCOW2Snapshots, thin provisioning, compressionLéger surcoût en I/OLab, dev, la plupart des cas

Le fichier RAW ne contient aucune métadonnée : chaque octet du fichier correspond à un octet vu par la machine virtuelle. Cette correspondance directe explique à la fois sa vitesse et son absence de fonctionnalités. Conséquence pratique, un disque RAW se monte directement sur l'hôte avec losetup sans outillage particulier, ce qui aide au dépannage d'une VM qui ne démarre plus.

  • Fichier = image bit-à-bit du disque
  • Taille du fichier = taille du disque (pas de thin provisioning par défaut)
  • Aucune fonctionnalité avancée

QCOW2 place une table d'indirection entre le disque vu par la VM et le fichier posé sur l'hôte : un bloc n'existe dans le fichier qu'à partir du moment où la machine y écrit. Tout le reste en découle. Le fichier peut annoncer 20 GiB et n'en peser que 2, un snapshot se réduit à figer la table et à écrire ailleurs, et la compression comme le chiffrement s'appliquent bloc par bloc. Le prix est une indirection de plus à chaque accès.

  • Thin provisioning : le fichier grandit à la demande
  • Snapshots : points de sauvegarde intégrés
  • Compression : optionnelle, réduit l'espace
  • Chiffrement : support natif (LUKS)
  • Backing files : chaînage pour les clones

qemu-img info lit le fichier sans passer par libvirt, ce qui en fait le recours quand un volume n'apparaît dans aucun pool. Deux lignes portent l'essentiel : virtual size annonce ce que voit la VM, disk size ce que le fichier occupe réellement sur l'hôte. L'écart entre les deux mesure le provisionnement fin ; sur un disque RAW pleinement alloué, les deux valeurs se rejoignent.

Fenêtre de terminal
qemu-img info /chemin/vers/disque.qcow2

Exemple de sortie :

image: ubuntu-test.qcow2
file format: qcow2
virtual size: 20 GiB (21474836480 bytes)
disk size: 2.1 GiB
cluster_size: 65536
Format specific information:
compat: 1.1
compression type: zlib
lazy refcounts: false
refcount bits: 16
corrupt: false
extended l2: false

Décryptage :

ChampSignification
virtual sizeTaille vue par la VM (20 GiB)
disk sizeEspace réellement utilisé sur le disque (2.1 GiB)
cluster_sizeTaille des blocs d'allocation
compat: 1.1Version du format QCOW2

Le ratio disk size / virtual size montre le thin provisioning en action.

Les commandes vol-* manipulent les disques à l'intérieur d'un pool. Toutes exigent de savoir dans quel pool chercher, soit en argument positionnel, soit via --pool. C'est la source d'erreur la plus fréquente de cette famille de commandes : un volume introuvable signifie presque toujours qu'on interroge le mauvais pool.

Cette commande lit l'état connu de libvirt, pas le contenu réel du répertoire. Un fichier .qcow2 copié à la main dans le répertoire du pool n'apparaît donc pas ici tant que virsh pool-refresh <pool> n'a pas été lancé, et c'est la cause numéro un d'un volume que l'on voit avec ls mais pas avec virsh. La colonne Path donne le chemin absolu, utile pour enchaîner sur qemu-img.

Fenêtre de terminal
virsh vol-list default

Sortie exemple (pool avec des VMs) :

Name Path
-----------------------------------------------------
ubuntu-test.qcow2 /var/lib/libvirt/images/ubuntu-test.qcow2
debian-srv.qcow2 /var/lib/libvirt/images/debian-srv.qcow2

Créer un volume par virsh plutôt que par qemu-img présente un avantage : libvirt applique automatiquement le propriétaire et les permissions attendus par le pool, ce qui évite les erreurs d'accès au démarrage de la VM. La taille annoncée est une capacité maximale, pas une réservation : en QCOW2, le fichier ne pèse que quelques centaines de kilooctets juste après sa création.

Fenêtre de terminal
virsh vol-create-as default test-disk.qcow2 10G --format qcow2

Options :

ParamètreSignification
defaultNom du pool
test-disk.qcow2Nom du volume
10GTaille (G = GiB)
--format qcow2Format du disque

Deux champs se comparent dans la sortie : Capacity est la taille vue par la machine virtuelle, Allocation l'espace réellement consommé sur l'hôte. Sur un volume QCOW2 fraîchement créé de 10 GiB, l'allocation tient dans quelques centaines de kilooctets. C'est le contrôle le plus rapide pour savoir si le provisionnement fin fonctionne comme prévu.

Fenêtre de terminal
virsh vol-info test-disk.qcow2 --pool default

vol-delete agit sur le fichier, pas sur la définition du pool : le disque quitte le système de fichiers dans la seconde, sans confirmation. Deux vérifications avant de la lancer, virsh vol-list pour confirmer le pool visé, et virsh domblklist <vm> pour s'assurer qu'aucun domaine ne pointe encore dessus. Un disque retiré sous une VM qui tourne provoque des erreurs d'entrée/sortie dans l'invité.

Fenêtre de terminal
virsh vol-delete test-disk.qcow2 --pool default

Deux chemins pour le même résultat : qemu-img agit sur le fichier, virsh vol-resize passe par le pool et met à jour la vue de libvirt dans la foulée. Dans les deux cas, réduire n'est pas symétrique d'agrandir, qemu-img resize refuse une taille inférieure tant qu'on ne lui passe pas --shrink, parce que l'opération efface ce qui dépasse. Et agrandir le conteneur ne dit rien au système installé dedans.

Pour agrandir un disque QCOW2 :

Fenêtre de terminal
# Avec qemu-img (VM arrêtée)
qemu-img resize /var/lib/libvirt/images/vm.qcow2 +10G
# Ou avec virsh
virsh vol-resize vm.qcow2 30G --pool default

Savoir où libvirt range ses fichiers sert dans deux situations : sauvegarder une configuration avant une manipulation risquée, et comprendre pourquoi un pool supprimé réapparaît après un redémarrage. Retenez la séparation : /etc/libvirt/ contient les définitions XML, /var/lib/libvirt/images/ contient les données. N'éditez jamais ces XML à la main pendant que le service tourne, libvirt les réécrit et vos modifications sont perdues ; passez par virsh edit ou par les commandes pool-define.

FichierEmplacementContenu
Définitions des pools/etc/libvirt/storage/XML des pools
Pool default/var/lib/libvirt/images/Disques des VMs
Définitions des VMs/etc/libvirt/qemu/XML des domains
Fenêtre de terminal
# Voir les définitions de pools
ls /etc/libvirt/storage/
# Sortie :
# autostart/
# default.xml

Les trois tableaux ci-dessous suivent la découpe de l'outillage : virsh pool-* pour les conteneurs de disques, virsh vol-* pour les disques eux-mêmes, qemu-img pour tout ce qui touche au contenu d'un fichier disque en dehors de libvirt.

Deux paires de commandes se ressemblent et ne font pas du tout la même chose. pool-destroy arrête le pool sans rien effacer, pool-undefine supprime sa définition mais laisse les fichiers en place. Aucune des deux ne détruit de données. pool-refresh est celle qu'on oublie : elle resynchronise la vue de libvirt avec le contenu réel du répertoire.

CommandeDescription
virsh pool-list --allLister tous les pools
virsh pool-list --detailsLister avec capacité/allocation
virsh pool-info <pool>Détails d'un pool
virsh pool-dumpxml <pool>Configuration XML
virsh pool-define-as <nom> <type> --target <path>Créer un pool
virsh pool-start <pool>Démarrer
virsh pool-autostart <pool>Activer au boot
virsh pool-destroy <pool>Arrêter
virsh pool-undefine <pool>Supprimer la définition
virsh pool-refresh <pool>Rafraîchir (rescan)

Ici, en revanche, vol-delete efface le fichier immédiatement, sans confirmation ni corbeille : c'est la différence majeure avec les commandes de pool. Notez aussi la position de --pool, qui varie d'une commande à l'autre : vol-list prend le pool en argument positionnel alors que vol-info et vol-delete attendent l'option nommée.

CommandeDescription
virsh vol-list <pool>Lister les volumes
virsh vol-info <vol> --pool <pool>Infos d'un volume
virsh vol-create-as <pool> <nom> <taille> --format <fmt>Créer
virsh vol-delete <vol> --pool <pool>Supprimer
virsh vol-resize <vol> <taille> --pool <pool>Redimensionner
virsh vol-clone <src> <dst> --pool <pool>Cloner

qemu-img travaille directement sur les fichiers, hors de toute notion de pool. Règle de sécurité qui vaut pour les quatre commandes : la machine virtuelle doit être arrêtée. Modifier un disque pendant que QEMU l'utilise corrompt l'image de façon irrécupérable. qemu-img info reste sans danger en lecture seule, mais peut afficher des valeurs périmées sur un disque en cours d'écriture.

CommandeDescription
qemu-img info <fichier>Informations du disque
qemu-img create -f qcow2 <fichier> <taille>Créer un disque
qemu-img resize <fichier> +10GAgrandir
qemu-img convert -O qcow2 <src> <dst>Convertir le format

Ces cinq messages couvrent la quasi-totalité des blocages sur le stockage libvirt. Trois d'entre eux se diagnostiquent avec la même commande, virsh pool-list --all : un pool absent, arrêté ou plein produit des symptômes différents pour une cause voisine. Le Permission denied est le plus trompeur, il vient rarement de l'utilisateur qui lance virsh mais des droits du répertoire cible, que le processus QEMU doit pouvoir traverser.

ErreurCauseSolution
Pool not foundPool inexistant ou pas démarrévirsh pool-list --all, virsh pool-start
Vol not foundVolume inexistantvirsh vol-list <pool>
Permission deniedDroits insuffisants sur le répertoireVérifier permissions (chmod 711)
Not enough spacePool pleinLibérer de l'espace ou utiliser un autre pool
Volume is in useVM utilise le disqueArrêter la VM avant suppression

À parcourir avant de déclarer un hôte prêt, et surtout après toute manipulation de pool. Les deux premières lignes sont celles qui provoquent réellement des pannes : un pool sans autostart ne remonte pas au redémarrage et toutes ses machines refusent alors de démarrer, et un pool plein fait échouer les écritures d'un disque en provisionnement fin alors que virsh affichait une taille confortable.

  • Pool default actif et autostart (virsh pool-list --all)
  • Espace suffisant disponible (virsh pool-info default)
  • Format QCOW2 pour la plupart des VMs
  • Permissions correctes sur le répertoire du pool
  • Sauvegardes des disques importants planifiées

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  1. Pool = conteneur de disques (répertoire, LVM, ZFS...). Volume = un disque individuel.

  2. Le pool default (/var/lib/libvirt/images/) suffit pour débuter.

  3. QCOW2 = le format recommandé (thin provisioning, snapshots). RAW = performance max mais pas de fonctionnalités.

  4. virsh pool-* pour gérer les pools, virsh vol-* pour les volumes.

  5. qemu-img info pour voir les vraies infos d'un disque (taille virtuelle vs réelle).

  6. Redimensionner le fichier disque ≠ étendre le filesystem (à faire dans la VM).

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens ce site gratuitement, sans publicité, sans profilage et sans compte à créer. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn