How to Migrate KVM Virtual Machines Between Hosts Without Shared Storage


3 views

When migrating KVM VMs between standalone hosts, you'll need to transfer two critical components:

  • Virtual disk images (typically qcow2 or raw format)
  • VM configuration XML (from virsh dumpxml)

Here's the complete workflow for a successful migration:

1. Prepare the Source VM

First, shutdown the VM cleanly on the source host:

virsh shutdown vm_name
virsh list --all  # Verify shutdown status

2. Locate and Transfer Disk Files

Find the disk paths from the VM config:

virsh dumpxml vm_name | grep "source file"

Then transfer using rsync (recommended for large files):

rsync -avzP /var/lib/libvirt/images/vm_disk.qcow2 \
user@dest-host:/var/lib/libvirt/images/

3. Export and Transfer VM Configuration

virsh dumpxml vm_name > vm_name.xml
scp vm_name.xml user@dest-host:~/

4. On Destination Host

Define and start the VM:

virsh define vm_name.xml
virsh start vm_name
virsh list --all

For production environments, consider these enhancements:

Network Configuration Alignment

Edit the XML before defining to match destination network names:

<interface type='network'>
    <source network='dest-bridge-name'/>
</interface>

Performance Optimization

Use parallel transfer with multiple rsync sessions:

rsync -avzP --bwlimit=100M /path/to/disks/ \
user@dest-host:/path/to/destination/
  • Permission errors: Ensure libvirt-qemu user has access to disk files
  • UUID conflicts: Remove or modify uuid in XML if migrating clones
  • Failed starts: Check logs with journalctl -u libvirtd

For minimal downtime, consider these approaches:

# Live block copy (requires short downtime)
virsh blockcopy vm_name vda --dest /new/path/image.qcow2 --wait --verbose

When moving KVM virtual machines between hosts that don't share storage, we need to handle both the VM configuration and disk images manually. This process is common in environments where centralized storage solutions like NFS or iSCSI aren't available.

First, identify your VM components:


virsh list --all
virsh dumpxml vm_name > vm_name.xml

For disk images, locate their paths in the XML configuration or use:


qemu-img info /path/to/disk.qcow2

You'll need to move two critical components:

  1. The XML configuration file (vm_name.xml)
  2. The disk image file(s) (disk.qcow2)

Use rsync for efficient transfer:


rsync -avzP /path/to/disk.qcow2 destination_host:/path/to/destination/
rsync -avzP vm_name.xml destination_host:/path/to/destination/

First, define the storage pool where disk images will reside:


virsh pool-define-as --name default --type dir --target /var/lib/libvirt/images
virsh pool-start default
virsh pool-autostart default

Then import the VM:


virsh define /path/to/destination/vm_name.xml

Check the imported VM configuration:


virsh dominfo vm_name
virsh dumpxml vm_name

Start the VM and verify operation:


virsh start vm_name
virsh console vm_name

Common problems and solutions:

  • Disk path mismatch: Edit the XML file before defining
  • Network configuration: Verify bridge names match
  • UUID conflicts: Generate new UUID with uuidgen

Example of XML modification for new paths:


<disk type='file' device='disk'>
  <driver name='qemu' type='qcow2'/>
  <source file='/new/path/to/disk.qcow2'/>
  <target dev='vda' bus='virtio'/>
</disk>

For larger environments, consider:

  • Using virt-v2v for conversions
  • Implementing incremental transfers with qemu-img rebase
  • Exploring libvirt's native migration capabilities with tunnelling

# Example of preparing for incremental transfer
qemu-img create -f qcow2 -b source.qcow2 new.qcow2

Optimize transfer speed with:

  • Compression (use -z with rsync)
  • Parallel transfers for multiple disks
  • Network tuning (MTU, TCP windows)

Example of parallel transfer with GNU parallel:


parallel -j 4 rsync -avzP {} destination_host:/path/ ::: disk1.qcow2 disk2.qcow2