
Ce projet enchaîne toute la formation sur deux hôtes, et chaque étape rend un chiffre. Une machine naît par cloud-init, sert une application, se fait sauvegarder à chaud, perd son disque, revient de sa sauvegarde, puis se déplace sur l'autre hôte sans être arrêtée. À la fin, il ne reste rien. C'est ce parcours-là, pas un score de quiz, qui dit que vous savez exploiter KVM.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Monter un socle partagé que deux hôtes voient de la même façon
- Chronométrer une VM de la commande jusqu'au service qui répond
- Sauvegarder une machine allumée avec
virsh backup-begin - Mesurer un RTO réel et prouver l'intégrité des données restaurées
- Déplacer la machine à chaud, puis vérifier qu'il ne reste aucun résidu
Prérequis
Section intitulée « Prérequis »- Les leçons Cloud-init, Snapshots et sauvegardes et Migration live acquises
- Deux hôtes KVM, physiques ou imbriqués, sur le même segment réseau
- De quoi perdre ce que vous manipulez : ce projet détruit volontairement un disque
La topologie, et pourquoi elle est ainsi
Section intitulée « La topologie, et pourquoi elle est ainsi »Deux hyperviseurs, kvmlab-1 et kvmlab-2, portent chacun un bridge
br0 sur le même segment. C'est ce qui permet à la machine invitée de
garder son adresse en changeant d'hôte : son trafic passe par un pont, pas
par un NAT local.
Un partage NFS porte les disques. Il est exporté par le premier hôte et monté par les deux, au même chemin. Cette symétrie n'est pas cosmétique : sans elle, libvirt voit un disque local côté source et refuse la migration.
| Élément | Valeur dans ce projet |
|---|---|
| Hôte 1 | kvmlab-1, 192.168.190.11 |
| Hôte 2 | kvmlab-2, 192.168.190.12 |
| Partage | /mnt/shared, NFS, monté des deux côtés |
| Machine invitée | appvm, 192.168.190.30, 1 Gio de RAM, disque de 10 Gio |
| Application témoin | un service HTTP qui sert un fichier d'état |
Étape 1 : le socle, réseau et pool
Section intitulée « Étape 1 : le socle, réseau et pool »Un pool de stockage déclaré sur le chemin partagé donne à libvirt un vocabulaire commun aux deux hôtes. Il n'est pas obligatoire pour migrer, mais il rend les volumes inventoriables au lieu d'être des fichiers posés à la main.
virsh pool-define-as capstone dir --target /mnt/sharedvirsh pool-build capstonevirsh pool-start capstonevirsh pool-autostart capstonevirsh pool-info capstoneSur le lab de référence, le pool annonce 28,02 Gio de capacité pour 24,86 Gio disponibles. Retenez ce point de départ : il servira à juger, à la fin, ce que le projet a réellement laissé derrière lui.
Étape 2 : la machine naît en 39 secondes
Section intitulée « Étape 2 : la machine naît en 39 secondes »L'amorce cloud-init porte trois fichiers, et l'un d'eux est souvent oublié.
meta-data est obligatoire : sans lui, la source de données NoCloud n'est
pas détectée du tout, aucun utilisateur n'est créé, le réseau n'est pas
appliqué, et la machine prend un bail DHCP anonyme sans qu'aucun message ne le
signale.
genisoimage -quiet -output /mnt/shared/appvm-seed.iso -volid cidata \ -joliet -rock /mnt/shared/seed-appvmL'ISO se construit depuis un répertoire. Passer les fichiers un par un les
renomme en 8.3, USER_DAT.;1, et cloud-init ne reconnaît plus rien.
La création elle-même se mesure :
virt-install --connect qemu:///system --name appvm \ --memory 1024 --vcpus 2 --cpu host-model \ --disk path=/mnt/shared/appvm.qcow2,format=qcow2,bus=virtio,cache=none,io=native \ --disk path=/mnt/shared/appvm-seed.iso,device=cdrom \ --network bridge=br0,model=virtio --os-variant ubuntu24.04 \ --graphics none --noautoconsole --import| Repère | Mesure |
|---|---|
| Domaine défini et démarré | 2,6 s |
| Service applicatif qui répond | 38,8 s après la commande |
Les 2,6 secondes ne veulent rien dire pour un exploitant : ce qui compte est le moment où l'application répond. Chronométrez toujours jusque-là, c'est le seul délai que votre utilisateur constate.
Deux options du disque méritent d'être remarquées. --cpu host-model est
posé explicitement, parce que virt-install mettrait sinon host-passthrough
et la machine ne pourrait pas migrer à l'étape 7. Et io=native exige
cache=none : QEMU refuse la combinaison inverse.
Étape 3 : ce que l'agent invité rend à l'hôte
Section intitulée « Étape 3 : ce que l'agent invité rend à l'hôte »Sans agent, l'hôte ne sait de la machine que ce qu'il lui a donné. Avec lui, il l'interroge.
virsh domifaddr appvm --source agentvirsh domfsinfo appvm enp1s0 52:54:00:e3:63:cc ipv4 192.168.190.30/24
Mountpoint Name Type Target / vda1 ext4 vda /boot vda16 ext4 vda /boot/efi vda15 vfat vdaL'adresse est rendue sans DHCP à consulter ni console à ouvrir, et la carte des systèmes de fichiers vient de l'intérieur de la machine. C'est ce même canal qui permettra, à l'étape 5, de figer les écritures le temps d'un cliché cohérent.
Étape 4 : mesurer les entrées-sorties là où elles comptent
Section intitulée « Étape 4 : mesurer les entrées-sorties là où elles comptent »Première tentation, et première erreur : mesurer depuis l'hôte. QEMU refuse, et il a raison.
qemu-img bench -f qcow2 -c 2000 -w /mnt/shared/appvm.qcow2qemu-img: Could not open '/mnt/shared/appvm.qcow2': Failed to get "write" lockIs another process using the image?Le disque d'une machine allumée ne se mesure pas depuis l'hôte. Le verrou protège exactement ce qu'il faut : deux écrivains sur un même qcow2 le corrompent. La mesure se prend dans l'invité, où elle a d'ailleurs plus de sens, puisque c'est ce que l'application voit.
dd if=/dev/zero of=/var/temoin/bench.bin bs=1M count=256 oflag=directdd if=/var/temoin/bench.bin of=/dev/null bs=1M iflag=direct| Sens | Résultat | Ce qu'il mesure |
|---|---|---|
| Écriture | 256 Mio en 6,65 s, 40,4 Mo/s | le chemin complet jusqu'au stockage |
| Lecture | 256 Mio en 0,096 s, 2,8 Go/s | le cache, pas le disque |
Étape 5 : sauvegarder à chaud, sans couper le service
Section intitulée « Étape 5 : sauvegarder à chaud, sans couper le service »virsh backup-begin copie le disque d'une machine en fonctionnement. En
mode push, libvirt écrit lui-même le fichier de destination.
cat > backup.xml <<'XML'<domainbackup mode='push'> <disks> <disk name='vda' backup='yes' type='file'> <target file='/mnt/shared/backup2/vda-complet.qcow2'/> <driver type='qcow2'/> </disk> </disks></domainbackup>XML
virsh backup-begin appvm --backupxml backup.xmlvirsh domjobinfo appvm --completedLe résultat, mesuré :
| Repère | Mesure |
|---|---|
| Durée annoncée par libvirt | 6 282 ms |
| Volume parcouru | 10,000 Gio, soit le disque entier |
| Fichier produit | 2,41 Gio |
qemu-img check | No errors, 24,08 % alloué |
| Service pendant l'opération | debout, sans interruption |
Deux choses à retenir de ce tableau. Le volume parcouru est la taille
virtuelle, pendant que le fichier produit ne pèse que ce qui est réellement
alloué : la sauvegarde d'un disque provisionné large coûte donc du temps
proportionnel à sa taille annoncée, et de l'espace proportionnel à son
contenu. Et une sauvegarde qui n'a pas passé qemu-img check n'est pas une
sauvegarde, c'est un fichier.
Étape 6 : la panne, et le RTO qu'elle révèle
Section intitulée « Étape 6 : la panne, et le RTO qu'elle révèle »Une sauvegarde ne vaut que restaurée. On détruit donc pour de vrai.
-
Arrêter et effacer la machine et son disque de production.
Fenêtre de terminal virsh destroy appvmvirsh undefine appvmrm -f /mnt/shared/appvm.qcow2 -
Constater que le service ne répond plus. C'est le point de départ du chronomètre : l'incident commence quand l'utilisateur le voit.
-
Restaurer le disque et la définition, puis démarrer.
Fenêtre de terminal cp /mnt/shared/backup/appvm-base.qcow2 /mnt/shared/appvm.qcow2virsh define /mnt/shared/backup/appvm.xmlvirsh start appvm -
Vérifier l'intégrité par une empreinte prise avant l'incident, jamais par un simple « ça redémarre ».
Fenêtre de terminal sha256sum /var/temoin/commandes.txt
| Repère | Mesure |
|---|---|
| RTO, de la commande de restauration au service qui répond | 16,2 s |
| Empreinte avant l'incident | 3822e7c9e7f6… |
| Empreinte après restauration | 3822e7c9e7f6… |
| Verdict | identique |
Le RTO est plus court que la création initiale, 16 secondes contre 39, et la raison est instructive : la restauration ne rejoue pas cloud-init. Elle repart d'un disque déjà initialisé. C'est un argument concret pour sauvegarder l'état plutôt que de compter sur une reconstruction.
Étape 7 : déplacer la machine sans la couper
Section intitulée « Étape 7 : déplacer la machine sans la couper »La machine tourne, elle porte ses données restaurées, et elle doit changer d'hôte sans que personne ne le remarque.
virsh migrate --live --verbose --persistent --undefinesource \ appvm qemu+ssh://root@192.168.190.12/system| Repère | Mesure |
|---|---|
| Durée totale vue du pilote | 3,1 s |
| Temps interne QEMU | 1 973 ms, 3 itérations |
| Mémoire transférée | 425,6 Mio |
| Disque transféré | aucun, le partage étant commun |
| Coupure | 91 ms |
La machine est ensuite absente du premier hôte et présente sur le second, son service répond toujours, et elle a gardé son adresse. C'est le bridge commun qui le permet.
Si la commande échoue avant même de parler du processeur, regardez le transport : la confiance SSH est directionnelle, et l'avoir établie dans un sens ne dit rien du retour.
Étape 8 : ne rien laisser derrière
Section intitulée « Étape 8 : ne rien laisser derrière »Un exercice qui ne se démonte pas devient une dette. Le contrôle final porte sur ce qui reste, pas sur ce qui a marché.
virsh destroy appvm ; virsh undefine appvm --remove-all-storagevirsh pool-destroy capstone ; virsh pool-undefine capstonevirsh list --all --name ; virsh pool-list --all --nameSur le lab de référence, les deux hôtes rendent zéro domaine et zéro pool. Vérifiez aussi l'espace repris sur le partage : un pool supprimé ne supprime pas les fichiers qu'il indexait, et c'est la cause la plus commune d'un stockage qui se remplit sans que personne ne sache pourquoi.
Le tableau de bord du projet
Section intitulée « Le tableau de bord du projet »Voici l'ensemble des mesures, prises sur deux hôtes Ubuntu 24.04 sous libvirt 10.0.0 et QEMU 8.2.2, avec une machine de 1 Gio de RAM et un disque de 10 Gio. Vos chiffres différeront ; ce qui doit se retrouver, ce sont les ordres de grandeur et les rapports entre eux.
| Étape | Mesure | Ce qu'elle vous dit |
|---|---|---|
| Création du domaine | 2,6 s | le temps de libvirt, pas le vôtre |
| Machine utilisable | 38,8 s | le seul délai que l'utilisateur constate |
| E/S en écriture | 40,4 Mo/s | la référence à comparer après réglage |
| Sauvegarde à chaud | 6,3 s pour 10 Gio parcourus | proportionnelle à la taille annoncée |
| Fichier de sauvegarde | 2,41 Gio | proportionnel au contenu réel |
| RTO | 16,2 s | plus court que la création, cloud-init n'étant pas rejoué |
| Intégrité | SHA256 identique | la seule preuve qui compte |
| Coupure de migration | 91 ms | invisible pour la plupart des applications |
| Résidus | 0 domaine, 0 pool | l'exercice est réellement terminé |
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez ce que le projet a ancré, en particulier les rapports entre les mesures : c'est leur lecture, plus que les chiffres eux-mêmes, qui sert sur une infrastructure réelle.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
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
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »- Le chronomètre qui compte part de la commande et s'arrête quand l'application répond : 38,8 s ici, là où le domaine était défini en 2,6 s.
meta-dataest obligatoire pour NoCloud, et l'ISO se construit depuis un répertoire : deux oublis silencieux qui font échouer tout le reste.- Ce qui doit survivre à un redémarrage s'écrit en unité systemd, jamais
dans
runcmd, qui ne joue qu'une fois. - Le disque d'une machine allumée ne se mesure pas depuis l'hôte : QEMU pose un verrou d'écriture, et la mesure se prend dans l'invité.
- Une lecture à 2,8 Go/s mesure un cache, pas un disque. Seule l'écriture directe traverse toute la chaîne.
virsh backup-beginparcourt la taille virtuelle et écrit la taille allouée : le temps dépend de l'une, l'espace de l'autre.- Une sauvegarde se prouve par une empreinte prise avant l'incident, jamais par une machine qui redémarre.
- Un RTO de 16 s contre 39 s de création initiale : restaurer un disque déjà initialisé est plus rapide que reconstruire.
- Le projet n'est fini que quand il ne reste aucune ressource : un pool supprimé ne supprime pas les fichiers qu'il indexait.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Formation Proxmox VE : La même pile KVM et libvirt, avec le clustering et la bascule automatique que ce projet fait à la main.
- Restic : Porter la sauvegarde mesurée ici vers un dépôt déduplicable et chiffré, hors de l'hyperviseur.