In this article, we will show some options for backing up virtual machines on a KVM hypervisor, as well as recovery scenarios. I would like to note that there are no convenient backup tools for KVM, and every administrator uses their own methods and scripts. There are two backup scenarios in KVM: when a VM is stopped (the easiest one, but rarely used) and without stopping the virtual machine.
First of all, it is worth noting that your KVM backup methods mostly depend on the virtual disk type you are using: LVM, RAW (IMG), or QCOW2. I use qcow2 virtual disk format on my KVM hosts. Its advantages:
- The disk size depends on the space it occupies in a virtual machine, it can be easily increased or decreased;
- It supports snapshots.
How to Back Up Powered Off KVM Virtual Machine?
If your project allows a short-term stop of a virtual machine, you can use the easiest backup method. Just copy a disk file and a configuration file of a virtual machine (if there are any configuration changes).
List your virtual machines on KVM using virsh:
# virsh list
Id Name State
----------------------------------------------------
1 test-centos running
4 generic running
You can copy a configuration file of a virtual machine using this command:
# virsh dumpxml VMname > /backup/VM.xml
To backup a virtual machine disk, stop the virtual machine, and copy the disk image file to the backup directory:
# virsh shutdown test-centos
# cp /vz/disk/test-centos.img /backup/
After the disk has been copied, start the virtual machine:
# virsh start test-centos
You can create a separate directory for each VM and make the backup automatic by adding the related commands to a script and configuring tasks in cron. You can use this easy and simple bash script:
#!/bin/bash
data=`date +%Y-%m-%d`
backup_dir=/backup
vm=`virsh list | grep . | awk '{print $2}'| sed 1,2d | tr -s '\n' ' '`
for activevm in $vm
do
mkdir -p $backup_dir/$activevm
# Back up the VM configuration XML file
virsh dumpxml $activevm > $backup_dir/$activevm/$activevm-$data.xml
# Virtual machine disk path
disk_path=`virsh domblklist $activevm | grep vd | awk '{print $2}'`
# Stop the virtual machine
virsh shutdown $activevm
sleep 2
for path in $disk_path
do
# Remove the file name from the path
filename=`basename $path`
# Back up the disk
gzip -c $path > $backup_dir/$activevm/$filename-$data.gz
sleep 2
virsh start $activevm
sleep 2
done
done
/usr/bin/find /backup/ -type f -mtime +7 -exec rm -rf {} \;
Add the script to cron and run it as often as you need it. The script automatically stops a virtual machine, copies the virtual disk file and the configuration file, and starts the virtual machine.
Backup Running Virtual Machine on KVM
In most cases, administrators prefer using a live backup of KVM virtual machines without stopping them. It is harder than the first option and requires some more actions. This option is based on snapshots and its merging with a virtual machine disk file. You can use this option for qcow2 virtual disks. In order to create a virtual machine backup, add a Channel Device with the name org.qemu.guest_agent.0 to the VM (you can add it using a configuration file or virt-manager).
error: argument unsupported: QEMU guest agent is not configured
Add the following settings to the XML configuration file of the virtual machine:
<channel type='unix'>
<target type='virtio' name='org.qemu.guest_agent.0'/>
</channel>
Add it to the Device section, save the configuration, and reboot your VM.
Then install the qemu-guest-agent package in the guest OS (using your package manager):
# yum install qemu-guest-agent -y
Use this command to create a VM snapshot:
# virsh snapshot-create-as --domain VMname snapshot --disk-only --atomic --quiesce –no-metadata
# gzip -c VM > /backup/VMname/VMname.gz
After copying the virtual machine disk file, merge it with the snapshot:
# virsh blockcommit VMname vda --active --verbose --pivot
Where vda is the output of the following command:
# virsh domblklist VMname | grep vd | awk '{print $1}'
You can use the following script to backup KVM VM online. This script starts a backup via cron, creates a snapshot, and merges it with a virtual machine disk:
#!/bin/bash
data=`date +%Y-%m-%d`
backup_dir=/backup
vm=`virsh list | grep . | awk '{print $2}'| sed 1,2d | grep -vf /root/bin/exclude | tr -s '\n' ' '`
for activevm in $vm
do
mkdir -p $backup_dir/$activevm
# Back up an VM configuration file virsh dumpxml $activevm > $backup_dir/$activevm/$activevm-$data.xml
# A list of virtual machine disks
disk_list=`virsh domblklist $activevm | grep vd | awk '{print $1}'`
# Virtual machine disks
disk_path=`virsh domblklist $activevm | grep vd | awk '{print $2}'`
# Create a disk snapshot
virsh snapshot-create-as --domain $activevm snapshot --disk-only --atomic --quiesce --no-metadata
sleep 3
for path in $disk_path
do
# Remove the file name from the path
filename=`basename $path`
# Back up the disk
gzip -c $path > $backup_dir/$activevm/$filename-$data.gz
sleep 3
done
for disk in $disk_list
do
# Get the snapshot path
snapshot=`virsh domblklist $activevm | grep $disk | awk '{print $2}'`
# Merge the snapshot with the disk
virsh blockcommit $activevm $disk --active --verbose --pivot
sleep 2
# Remove the snapshot
rm -rf $snapshot
done
done
/usr/bin/find /backup/ -type f -mtime +7 -exec rm -rf {} \;
This script creates a backup similar to the first method, but a virtual machine is not stopped (it works correctly, I have tested it on virtual servers with postgresql, mariadb, and nginx with php-fpm).
Now you copy the backup folder to a remote host or storage using Rsync.
maybe, you want to try this solution: https://github.com/abbbi/virtnbdbackup
I wonder if I can delete the snapshot after blockcommit.
Thank you, useful information, nice that you included the offline case with simple tools.
You could improve by adding the restore steps as well though.
In case of ‘backup’ it’s dangerous to only think about the backup part, since it creates a false sense of safety.
If you ask me, backup always means “how to back up AND restore” something, and you should always test restores, before you conclude.
cheers mate,
Robert
4 things:
i) The line # Back up an VM configuration file !!!should be CR here so the script actually dumps the xmls!!!
virsh dumpxml $activevm > $backup_dir/$activevm/$activevm-$data.xml
ii) Shouldn’t ‘/usr/bin/find /backup/ -type f -mtime +7 -exec rm -rf {} \;’ be ‘/usr/bin/find $backup_dir/ -type f -mtime +7 -exec rm -rf {} \;’? so it is a bit more universal, in case someone uses different location i.e. backup_dir=/mnt/backup
iii) What is the format of the /root/bin/exclude file? space / comma separated, vm per line?
iv) How can I restore the VM from that backup? Is it a matter of copying the backup file (and decompressing it ofc) and then defining the VM using virsh?