Aller au contenu
English
Virtualisation medium

Migration live KVM : déplacer une VM sans l'arrêter

45 min de lecture

Logo KVM

Une migration live déplace une machine allumée d'un hôte à un autre, sans l'arrêter. Son principe est simple, sa réussite dépend de trois conditions qui se vérifient avant de lancer la commande : un processeur que la destination sait fournir, un stockage qu'elle sait atteindre, et un transport ouvert entre les deux. Ce guide montre comment les contrôler, et pourquoi la première est celle qui échoue le plus souvent.

  • Vérifier la compatibilité processeur avant de tenter quoi que ce soit
  • Comprendre pourquoi host-passthrough interdit la migration, et qu'il est le défaut
  • Choisir entre stockage partagé et copie du disque pendant la migration
  • Employer --auto-converge et --postcopy quand la machine écrit trop vite
  • Lire l'avancement d'une migration et savoir quand elle ne convergera pas
  • Deux hôtes KVM, ou un hôte et une destination joignable
  • Les guides Performances et Accès distant acquis
  • Une VM de test, jamais une machine de production pour un premier essai

Le processeur décide, et il décide avant tout le reste

Section intitulée « Le processeur décide, et il décide avant tout le reste »

Une migration live déplace un système en cours d'exécution. Le noyau invité a déjà interrogé son processeur, mémorisé les instructions disponibles, et peut-être choisi des chemins de code en conséquence. Lui retirer une instruction en plein vol le ferait planter, ce que libvirt refuse par principe.

virsh cpu-compare répond à la question exacte : cet hôte sait-il fournir ce processeur ? Écrivez la définition à tester dans un fichier, puis interrogez la destination.

Fenêtre de terminal
# Le processeur de l'hôte, comparé à lui-même, pour valider la méthode :
virsh capabilities | sed -n '/<cpu>/,/<\/cpu>/p' > hote.xml
virsh cpu-compare hote.xml
CPU described in hote.xml is identical to host CPU

Trois réponses possibles, et une seule est confortable :

RéponseCe que cela veut dire
supersetL'hôte offre plus que demandé : la migration passe
identicalL'hôte offre exactement ce qui est demandé
incompatibleIl manque au moins une chose : la migration échouera

Un cas qui surprend, et qui explique beaucoup d'échecs

Section intitulée « Un cas qui surprend, et qui explique beaucoup d'échecs »

Sur l'hôte de ce guide, un Alder Lake de 12e génération, demander le modèle Skylake-Client-IBRS en correspondance exacte donne :

CPU described in local.xml is incompatible with host CPU

Or c'est précisément le modèle que host-model déduit pour cet hôte. La contradiction n'est qu'apparente, et sa cause est instructive : le modèle QEMU Skylake-Client-IBRS inclut les instructions TSX, hle et rtm, qu'Intel a retirées de ses processeurs récents. L'hôte ne les a pas :

Fenêtre de terminal
cat > exact.xml <<'XML'
<cpu match="exact">
<model>Skylake-Client-IBRS</model>
</cpu>
XML
virsh cpu-compare exact.xml

L'hôte ne les a pas, ce qui se vérifie en deux lignes :

Fenêtre de terminal
grep -cw hle /proc/cpuinfo # 0
grep -cw rtm /proc/cpuinfo # 0

host-model le sait et l'écrit noir sur blanc dans ses capacités :

<feature policy='disable' name='hle'/>
<feature policy='disable' name='rtm'/>

C'est toute la différence entre demander un modèle et partir d'un modèle. host-model prend le plus proche comme base, puis ajoute ce qui manque et retire ce qui n'existe pas. Une définition en match='exact' n'a pas cette souplesse, et casse dès qu'une seule instruction diffère.

Le piège du défaut : vos VM sont probablement non migrables

Section intitulée « Le piège du défaut : vos VM sont probablement non migrables »

C'est le constat le plus utile de ce guide, et il ne demande aucune installation pour être vérifié :

Fenêtre de terminal
virt-install --name lecture --memory 512 --vcpus 1 --disk none \
--import --osinfo ubuntu24.04 --print-xml | grep '<cpu'
<cpu mode="host-passthrough"/>

virt-install pose host-passthrough par défaut, et le résultat est identique avec --osinfo generic ou rhel9.4. Or ce mode expose le processeur exact de l'hôte : la machine ne peut alors migrer que vers un hôte au processeur identique.

Le stockage : partagé, ou copié pendant le trajet

Section intitulée « Le stockage : partagé, ou copié pendant le trajet »

La mémoire se transfère toujours par le réseau. Le disque, lui, dépend de ce que les deux hôtes voient.

SituationCommandeCe qui circule
Stockage partagé (NFS, iSCSI, Ceph)virsh migrate --liveLa mémoire seulement
Stockage local des deux côtés--copy-storage-allLa mémoire et tout le disque
Destination ayant déjà une base commune--copy-storage-incLa mémoire et les différences

Dans le premier cas, la commande se réduit à son expression la plus simple :

Fenêtre de terminal
virsh migrate --live --verbose --persistent --undefinesource \
appvm qemu+ssh://root@192.168.190.12/system

Dans le second, le disque de destination doit préexister : QEMU y écrit, il ne le crée pas.

Fenêtre de terminal
# Sur la destination, créer un disque vide de la même taille virtuelle :
sudo qemu-img create -f qcow2 /var/lib/libvirt/images/appvm.qcow2 10G
# Puis, sur la source :
virsh migrate --live --verbose --persistent --undefinesource \
--copy-storage-all appvm qemu+ssh://root@192.168.190.11/system

Avec un stockage partagé, la migration d'une VM de 4 Gio de RAM transfère quelques gigaoctets. Avec --copy-storage-all sur un disque de 100 Gio, elle en transfère cent de plus, et la durée change d'ordre de grandeur.

Une migration live copie la mémoire pendant que l'invité continue de la modifier. libvirt repasse donc sur les pages salies, puis recommence, jusqu'à ce que le reste soit assez petit pour une bascule imperceptible. Sur une machine qui écrit intensément, ce reste ne diminue jamais : la migration ne converge pas et tourne indéfiniment.

Deux options traitent ce cas, et elles ne font pas le même compromis :

Fenêtre de terminal
virsh migrate --live --auto-converge ma-vm qemu+ssh://hote2/system
virsh migrate --live --postcopy ma-vm qemu+ssh://hote2/system
  • --auto-converge ralentit progressivement les vCPU de l'invité pour que la copie rattrape son retard. La machine reste sur l'hôte d'origine jusqu'au bout, mais elle est volontairement bridée pendant la manoeuvre.
  • --postcopy bascule la machine tôt sur la destination, puis va y chercher les pages manquantes à la demande. La bascule est rapide, mais une coupure réseau pendant cette phase laisse la mémoire répartie entre deux hôtes, et la machine est perdue.

Le choix se fait donc sur le risque accepté : auto-converge dégrade les performances, postcopy accepte une fenêtre de fragilité.

Fenêtre de terminal
virsh domjobinfo appvm
Fenêtre de terminal
virsh domjobabort appvm

domjobinfo donne la mémoire restante, le débit et le nombre d'itérations. Une mémoire restante qui ne décroît plus d'une itération à l'autre est le signal qu'il faut soit ajouter une option de convergence, soit renoncer.

Ce que la migration donne réellement, mesuré sur deux hôtes

Section intitulée « Ce que la migration donne réellement, mesuré sur deux hôtes »

Les chiffres ci-dessous viennent d'un lab à deux hyperviseurs, joué le 19 septembre 2026 sous libvirt 10.0.0 et QEMU 8.2.2, avec une VM invitée de 1 Gio de RAM et un disque de 10 Gio. La coupure est mesurée deux fois, par ce que QEMU déclare et par une sonde ICMP à 10 ms lancée depuis un poste tiers.

MesureStockage partagé--copy-storage-all
Durée totale, vue du pilote2,86 s9,48 s
Temps interne QEMU1 886 ms8 522 ms
Mémoire transférée429 Mio437 Mio
Disque transféréaucun2,3 Gio
Itérations33
Coupure annoncée par QEMU63 ms147 ms
Coupure vue du client6 pings sur 8 119non relevée

Les 63 ms annoncés et les 6 pings perdus à 10 ms d'intervalle décrivent le même événement : le chiffre de QEMU est donc utilisable tel quel pour dimensionner une fenêtre de maintenance.

Le même test, joué vers un hôte au processeur volontairement plus étroit, donne deux messages très inégaux selon le mode CPU de la machine.

Fenêtre de terminal
error: operation failed: job 'migration out' failed: Channel error: Input/output error

C'est ce que rend une VM en host-passthrough : une erreur d'entrée-sortie, qui ne nomme ni la cause ni le remède. La même migration, sur une machine en host-model, rend au contraire la liste exacte de ce qui manque :

Fenêtre de terminal
error: operation failed: guest CPU doesn't match specification: missing features:
ss,pclmuldq,fma,pcid,movbe,aes,xsave,avx,f16c,rdrand,fsgsbase,bmi1,avx2,smep,
bmi2,erms,invpcid,rdseed,adx,smap,clflushopt,clwb,sha-ni,pku,waitpkg,gfni,vaes,
vpclmulqdq,rdpid,movdiri,movdir64b,fsrm,md-clear,serialize,spec-ctrl,stibp,
flush-l1d,ssbd,avx-vnni,fsrs,xsaveopt,xsavec,xgetbv1,xsaves,pdpe1gb,rdtscp,abm,
3dnowprefetch,ibpb,ibrs,amd-stibp,amd-ssbd,rdctl-no,ibrs-all,mds-no,
sbdr-ssdp-no,fbsdp-no,psdp-no,vmx-apicv-register,vmx-apicv-vid,vmx-xsaves,
vmx-tsc-scaling,vmx-enable-user-wait-pause,vmx-posted-intr

host-model ne rend pas seulement une machine plus déplaçable : il rend son refus lisible. C'est un argument de plus, et il ne coûte rien.

Il faut dire l'autre moitié du résultat : dans ce test, host-model n'a pas sauvé la migration non plus. La destination n'avait réellement pas ces instructions. host-model ouvre la migration vers un hôte au moins équivalent, pas vers n'importe lequel.

Ce constat s'est vérifié par accident, ce qui en dit la fréquence. La première tentative de migration a échoué sans jamais atteindre la question du processeur, faute de confiance SSH dans le sens utilisé :

Fenêtre de terminal
error: Cannot recv data: Host key verification failed.: Connection reset by peer

La confiance SSH est directionnelle. L'avoir établie de l'hôte 1 vers l'hôte 2 ne dit rien du chemin inverse, et une migration de retour échouera sur ce message. Établissez-la dans les deux sens avant d'annoncer une fenêtre de maintenance.

Ce que --auto-converge fait, et ce qu'il ne promet pas

Section intitulée « Ce que --auto-converge fait, et ce qu'il ne promet pas »

Un processus salissant 320 Mio en boucle dans une VM de 1 Gio, avec un débit de migration plafonné à 5 Mio/s, reproduit la non-convergence à coup sûr. domjobinfo la nomme sans ambiguïté :

Job type: Unbounded
Data processed: 2.417 GiB
Data remaining: 67.355 MiB
Iteration: 7
Expected downtime: 64859 ms

2,4 Gio transférés pour 1 Gio de mémoire, et une coupure prévue de 65 secondes si la bascule avait lieu maintenant. Ce dernier chiffre est le meilleur signal d'arrêt : personne n'accepte 65 secondes de gel.

Relancée avec --auto-converge, la même migration montre le mécanisme en clair. Le moniteur QEMU expose le taux de bridage appliqué aux vCPU :

Fenêtre de terminal
virsh qemu-monitor-command appvm --hmp "info migrate" | grep throttle
Temps écouléBridage vCPUMémoire restante
+30 s40 %43 Mio
+60 s50 %219 Mio
+180 s60 %232 Mio
+300 s70 %247 Mio

Le bridage monte réellement, par paliers, et le taux de salissure retombe au niveau du débit de transfert. Mais après quatorze minutes et 70 % de vCPU confisqués, cette migration-là n'avait toujours pas convergé.

Le renoncement, lui, est sans dommage : après domjobabort, la machine est restée sur son hôte d'origine, en fonctionnement, et son service répondait toujours.

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

  • La migration échoue le plus souvent sur le processeur, et cela se vérifie avant avec virsh cpu-compare.
  • virt-install pose host-passthrough par défaut, quel que soit l'--osinfo : vos machines sont probablement non migrables sans que personne ne l'ait décidé.
  • Un modèle demandé en match='exact' peut être refusé alors même que host-model le prend comme base : les instructions TSX retirées des processeurs Intel récents en sont l'exemple courant.
  • Sans stockage partagé, --copy-storage-all fait aussi transiter tout le disque : la durée change d'ordre de grandeur.
  • Une machine qui écrit plus vite que le réseau ne converge pas. --auto-converge la bride, --postcopy bascule tôt et accepte une fenêtre de fragilité.
  • Une mémoire restante stable d'une itération à l'autre dans domjobinfo signale une migration qui n'aboutira pas. Expected downtime chiffre ce que coûterait la bascule : 65 secondes dans le lab de ce guide.
  • Un partage NFS n'est vu comme partagé que si les deux hôtes le montent, y compris celui qui l'exporte, sinon libvirt refuse par « Unsafe migration ».
  • La confiance SSH est directionnelle : l'établir dans un sens ne permet pas la migration de retour.
  • domjobinfo ne compte pas le disque copié par --copy-storage-all : seule la durée trahit les gigaoctets supplémentaires.
  • --auto-converge bride les vCPU par paliers, jusqu'à 70 % dans ce lab, sans garantir la convergence pour autant.
  • Dépannage réseau KVM : Le transport est la première cause d'échec d'une migration, avant le processeur.
  • Examen final : Vérifier ce qui est acquis sur l'ensemble du parcours.

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracking. 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