Vai al contenuto
EuroVPSEuroVPS

Live migration di un guest KVM con il suo storage, passo passo

Come spostare una macchina virtuale KVM in esecuzione e il suo disco tra host con libvirt: controlli di compatibilità, preparazione della destinazione, il comando, e quando andare a freddo.

Di EuroVPS Engineering

5 min di lettura
Live migration di un guest KVM con il suo storage, passo passo

Spostare una macchina virtuale in esecuzione tra host senza storage condiviso sembra magia finché non lo avete fatto qualche volta. Poi diventa una checklist: confermate che gli host sono compatibili, preparate la destinazione perché il guest trovi tutto ciò che si aspetta, lanciate un comando, e sappiate quando non provarci. Ecco quella checklist per KVM puro con libvirt.

Cosa succede davvero durante una live migration

Con --copy-storage-all, libvirt chiede a QEMU sulla destinazione di creare il guest, poi trasmette il disco mentre il guest continua a girare e a scrivere. Una volta che il disco è in mirror, la memoria viene copiata a round: ogni round invia le pagine che il guest ha sporcato durante il precedente. Quando l'insieme di pagine sporche rimanente è abbastanza piccolo da essere inviato entro il downtime consentito, il guest viene messo in pausa, le ultime pagine e lo stato dei device passano dall'altra parte, e riprende sulla destinazione. La pausa è di solito di qualche centinaio di millisecondi. Le connessioni di rete sopravvivono perché il guest mantiene il suo MAC e il suo indirizzo IP, e lo switch impara la nuova posizione dai primi pacchetti del guest.

Tutto ciò che può andare storto è una discrepanza tra ciò che il guest si aspetta e ciò che la destinazione offre. Quindi controllate prima quello.

Passo uno: decidete live o a freddo

La live migration è lo strumento giusto quando sorgente e destinazione sono compatibili e il tasso di scrittura del guest è moderato. È lo strumento sbagliato quando cambia tutto insieme: una generazione di CPU diversa, un layout di rete diverso e una release dell'hypervisor diversa nello stesso spostamento. Allora il percorso sicuro è a freddo: spegnete il guest in modo pulito, copiate il disco, definitelo sul target, avviatelo, e tenete la sorgente intatta come rollback.

Anche un database primario con un tasso di pagine sporche molto alto potrebbe non convergere mai. Misurate prima di provare:

virsh domdirtyrate-calc <guest> --seconds 5
virsh domstats <guest> --dirtyrate

Passo due: controllate la compatibilità della CPU

Il modello di CPU del guest deve esistere sulla destinazione. Se il guest usa host-passthrough, le CPU dei due host devono di fatto coincidere. Confrontate la definizione del guest con l'host di destinazione:

virsh dumpxml <guest> > guest.xml                       # on the source
xmllint --xpath '//cpu' guest.xml > guest-cpu.xml
virsh hypervisor-cpu-compare guest-cpu.xml              # on the destination

identical o superset significa via libera. incompatible significa o cambiare il guest a un modello di CPU con nome supportato da entrambi gli host (al suo prossimo riavvio) o spostarlo a freddo.

Passo tre: preparate la rete di destinazione

Ogni bridge, o VLAN su un bridge, a cui si collegano le interfacce del guest deve esistere sulla destinazione con lo stesso nome, e deve portare le stesse VLAN sull'uplink:

virsh domiflist <guest>      # on the source: which bridges
ip -br link show type bridge # on the destination: do they exist?

Un bridge mancante fa fallire la migrazione in modo pulito all'inizio. Un bridge che esiste ma siede su un uplink senza la VLAN migra con successo e lascia il guest irraggiungibile, che è peggio. Controllate anche il lato switch.

Passo quattro: preparate lo storage di destinazione

La destinazione ha bisogno di un posto dove far atterrare il disco, a un percorso che libvirt gestisce come storage pool:

virsh pool-define-as images dir --target /var/lib/libvirt/images
virsh pool-start images && virsh pool-autostart images

Per la maggior parte dei layout libvirt crea da sé l'immagine di destinazione. Per quelli insoliti, createla in anticipo con esattamente la stessa dimensione virtuale e lo stesso formato della sorgente:

qemu-img info --output=json /var/lib/libvirt/images/<guest>.qcow2   # note virtual-size
qemu-img create -f qcow2 /var/lib/libvirt/images/<guest>.qcow2 <virtual-size>

Passo cinque: migrate

Dall'host sorgente, con accesso SSH a chiave verso la destinazione come utente libvirt:

virsh migrate --live --persistent --undefinesource \
  --copy-storage-all --auto-converge --verbose \
  <guest> qemu+ssh://<destination>/system
  • --live mantiene il guest in esecuzione.
  • --copy-storage-all fa il mirror dell'intero disco. (--copy-storage-inc esiste per dischi la cui immagine base è già sulla destinazione.)
  • --auto-converge rallenta leggermente la CPU del guest se la memoria viene sporcata più in fretta di quanto possa essere inviata, così anche i guest impegnati finiscono.
  • --persistent e --undefinesource spostano la definizione insieme al guest, così non ricompare sul vecchio host al prossimo riavvio.

Usiamo il percorso di migrazione diretto invece di --tunnelled quando lo storage viene copiato. Mentre gira, seguite l'avanzamento da un secondo terminale:

virsh domjobinfo <guest>

domjobinfo mostra i dati rimanenti, il dirty rate e il downtime previsto. Se chiaramente non sta convergendo, virsh domjobabort <guest> ferma il job e lascia il guest in esecuzione sulla sorgente, intatto.

Passo sei: verificate all'arrivo

Controllate, dall'esterno del guest:

virsh list --all                      # running on the destination only
virsh domblklist <guest>              # disk at the expected path
virsh domifaddr <guest> --source arp  # address visible on the network

Se il guest è un load balancer o una replica di database, confermate che ha ripreso il suo ruolo (stato VRRP, thread di replica) invece di darlo per scontato.

Solo dopo, rimuovete la vecchia immagine del disco dalla sorgente, o meglio, tenetela fino al prossimo ciclo di manutenzione.

La vostra checklist

  • Live o a freddo deciso di proposito, con il dirty rate misurato per i guest impegnati.
  • Modello di CPU confrontato con l'host di destinazione.
  • Ogni bridge e VLAN presente sulla destinazione, compresi gli uplink dello switch.
  • Uno storage pool sulla destinazione, spazio libero a sufficienza, e un'immagine pre-creata dove il layout lo richiede.
  • Il comando migrate eseguito con copia dello storage e auto converge, seguito con domjobinfo.
  • Il guest verificato dall'esterno, e la copia sorgente conservata finché non siete sicuri.

Se volete spostare guest senza spegnerli, o avete bisogno di una via d'uscita dal vostro hypervisor attuale, siamo lieti di aiutarvi.

cta: Parla con un ingegnere

Related

  • /what-we-do/data-web/live-migration-hypervisor-exits/
  • /what-we-do/storage-compute/private-cloud-olvm/
  • /what-we-do/network/layer-2-extension/

Pubblicato il 4 agosto 2026.

Tutte le note dal campo