Рубрики
backup \ crontab \ tar \ zip \ архивация \ архиваторы KVM

KVM backup VM (QEMU, KVM, libvirt) \ без остановки ВМ \ пример скрипта бэкапа

Backup VM без остановки:

В клиенте устанавливаем Агент QEMU!
-------------------------------------------
Информация:
virsh domblklist vm-name -  узнаем имена дисков виртуальной машины
virsh list --all - вывести список всех виртуалок
vm-name	- имя виртуальной машины
backup-snapshot	- название снэпшота, может быть любым
vda -имя диска, для которого указываем адрес снепшота
/snapshot/vm-name-backup.qcow2	- путь и имя файла для снепшота
-------------------------------------------

На сервере:
0) virsh snapshot-create-as --domain vm-name backup-snapshot -diskspec vda,file=/snapshot/vm-name-backup.qcow2 --disk-only --atomic --quiesce --no-metadata - выполняем снимок виртуалки
1) pigz -c /virt/vm-name.qcow2 > /backup-vm/vm-name.qcow2.gz - архивируем основной файл виртуалной машины
2) virsh blockcommit vm-name vda --active --verbose --pivot - выполняем слияние снапшота + диск
3) rm /snapshot/vm-name-backup.qcow2 - удаляем снапшот
4) virsh dumpxml vm-name > /backup-vm/vm-name.xml - бэкапим настройки виртуалки

Пример:
virsh
snapshot-create-as linux2 "snapshot" "snapshot comment" --disk-only --quiesce --atomic --diskspec vda,snapshot=external,file=/PVE/linux2.vda.qcow2
blockcommit linux2 vda --active --verbose --pivot

Ошибка выполнения слияния в debian 10

!!! При выполнении (virsh blockcommit vm-name vda --active --verbose --pivot)
!!! Ошибка (error: internal error: unable to execute QEMU command 'block-commit': Could not reopen file: Permission denied) 
!!! Временное решение
sudo aa-status - смотрим состояние AppArmor
sudo aa-teardown - вырубаем AppArmor 

На госте:

0) Диск должен быть virtio
1) Должен быть установлен guest-agent ( канал org.qemu.guest_agent.0 )

Скрипт бэкапа:

#!/bin/bash

# Дата год-месяц-день
data=`date +%Y-%m-%d`
# Папка для бэкапов
backup_dir=/backup-vm
# Список работающих VM
vm_list=`virsh list | grep running | awk '{print $2}'`
# Список VM, заданных вручную, через пробел
#vm_list=(vm-1 vm-2)
# Лог файл
logfile="/var/log/kvmbackup.log"

# Использовать это условие, если список VM задается вручную
#for activevm in "${vm_list[@]}";
# Использовать это условие, если список работающих VM берется автоматически
for activevm in $vm_list
    do
        mkdir -p $backup_dir/$activevm
        # Записываем информацию в лог с секундами
        echo "`date +"%Y-%m-%d_%H-%M-%S"` Start backup $activevm" >> $logfile
        # Бэкапим конфигурацию
        virsh dumpxml $activevm > $backup_dir/$activevm/$activevm-$data.xml
        echo "`date +"%Y-%m-%d_%H-%M-%S"` Create snapshots $activevm" >> $logfile
        # Список дисков VM
        disk_list=`virsh domblklist $activevm | grep vd | awk '{print $1}'`
        # Адрес дисков VM
        disk_path=`virsh domblklist $activevm | grep vd | awk '{print $2}'`
        # Делаем снепшот диcков
        virsh snapshot-create-as --domain $activevm snapshot --disk-only --atomic --quiesce --no-metadata
        sleep 2
        for path in $disk_path
            do
                echo "`date +"%Y-%m-%d_%H-%M-%S"` Create backup $activevm $path" >> $logfile
                # Вычленяем имя файла из пути
                filename=`basename $path`
                # Бэкапим диск
                pigz -c $path > $backup_dir/$activevm/$filename.gz
                sleep 2
            done
        for disk in $disk_list
            do
                # Определяем путь до снепшота
                snap_path=`virsh domblklist $activevm | grep $disk | awk '{print $2}'`
                echo "`date +"%Y-%m-%d_%H-%M-%S"` Commit snapshot $activevm $snap_path" >> $logfile
                # Объединяем снепшот
                virsh blockcommit $activevm $disk --active --verbose --pivot
                sleep 2
                echo "`date +"%Y-%m-%d_%H-%M-%S"` Delete snapshot $activevm $snap_path" >> $logfile
                # Удаляем снепшот
                rm $snap_path
            done
        echo "`date +"%Y-%m-%d_%H-%M-%S"` End backup $activevm" >> $logfile
    done

Пример рабочий сервер:

#!/bin/bash
# Дата год-месяц-день
data=`date +%Y-%m-%d`
# Папка для бэкапов
backup_dir=/mnt/datastore1/backup_VM/

# Список работающих VM
#vm_list=`virsh list | grep running | awk '{print $2}'`
# Список VM, заданных вручную, через пробел
vm_list=(mail squid voice nginx mirtashop b14esh nagios linux)
#vm_list=(nagios)

# Лог файл
logfile="/var/log/kvmbackup.log"

# Использовать это условие, если список VM задается вручную
for activevm in "${vm_list[@]}";
# Использовать это условие, если список работающих VM берется автоматически
#for activevm in $vm_list
    do
        mkdir -p $backup_dir/$activevm
        # Записываем информацию в лог с секундами
        echo "`date +"%Y-%m-%d_%H-%M-%S"` Start backup $activevm" >> $logfile
        # Бэкапим конфигурацию
        virsh dumpxml $activevm > $backup_dir/$activevm/$activevm-$data.xml
        echo "`date +"%Y-%m-%d_%H-%M-%S"` Create snapshots $activevm" >> $logfile
        # Список дисков VM
        disk_list=`virsh domblklist $activevm | grep vd | awk '{print $1}'`
        # Адрес дисков VM
        disk_path=`virsh domblklist $activevm | grep vd | awk '{print $2}'`
        # Делаем снепшот диcков
        virsh snapshot-create-as --domain $activevm snapshot --disk-only --atomic --quiesce --no-metadata
        sleep 2
        for path in $disk_path
            do
                echo "`date +"%Y-%m-%d_%H-%M-%S"` Create backup $activevm $path" >> $logfile
                # Вычленяем имя файла из пути
                filename=`basename $path`
                # Бэкапим диск
                pigz -c $path > $backup_dir/$activevm/$data.$filename.gz
                sleep 2
            done
        for disk in $disk_list
            do
                # Определяем путь до снепшота
                snap_path=`virsh domblklist $activevm | grep $disk | awk '{print $2}'`
                echo "`date +"%Y-%m-%d_%H-%M-%S"` Commit snapshot $activevm $snap_path" >> $logfile
                # Объединяем снепшот
                virsh blockcommit $activevm $disk --active --verbose --pivot
                sleep 2
                echo "`date +"%Y-%m-%d_%H-%M-%S"` Delete snapshot $activevm $snap_path" >> $logfile
                # Удаляем снепшот
                rm $snap_path
            done
        echo "`date +"%Y-%m-%d_%H-%M-%S"` End backup $activevm" >> $logfile
    done

Очистка папки с бэкапами(старое):

!!! вызов  (|xargs /bin/rm -f) можно заменить модным параметром у -delete для команды find
#!/bin/bash
#/mnt/datastore1/backup_VM
cd /mnt/datastore1/backup_VM
#b14esh
find /mnt/datastore1/backup_VM/b14esh  -name "*.qcow2.gz" -mtime +30 |xargs /bin/rm -f {};
find /mnt/datastore1/backup_VM/b14esh  -name "*.xml" -mtime +30 |xargs /bin/rm -f {};
#mail
find /mnt/datastore1/backup_VM/mail  -name "*.qcow2.gz" -mtime +30 |xargs /bin/rm -f {};
find /mnt/datastore1/backup_VM/mail  -name "*.xml" -mtime +30 |xargs /bin/rm -f {};
#mirtashop
find /mnt/datastore1/backup_VM/mirtashop  -name "*.qcow2.gz" -mtime +30 |xargs /bin/rm -f {};
find /mnt/datastore1/backup_VM/mirtashop  -name "*.xml" -mtime +30 |xargs /bin/rm -f {};
#nginx
find /mnt/datastore1/backup_VM/nginx  -name "*.qcow2.gz" -mtime +30 |xargs /bin/rm -f {};
find /mnt/datastore1/backup_VM/nginx  -name "*.xml" -mtime +30 |xargs /bin/rm -f {};
#squid
find /mnt/datastore1/backup_VM/squid  -name "*.qcow2.gz" -mtime +30 |xargs /bin/rm -f {};
find /mnt/datastore1/backup_VM/squid  -name "*.xml" -mtime +30 |xargs /bin/rm -f {};
#voice
find /mnt/datastore1/backup_VM/voice  -name "*.qcow2.gz" -mtime +30 |xargs /bin/rm -f {};
find /mnt/datastore1/backup_VM/voice  -name "*.xml" -mtime +30 |xargs /bin/rm -f {};
#nagios
find /mnt/datastore1/backup_VM/nagios  -name "*.qcow2.gz" -mtime +30 |xargs /bin/rm -f {};
find /mnt/datastore1/backup_VM/nagios  -name "*.xml" -mtime +30 |xargs /bin/rm -f {};
#linux
find /mnt/datastore1/backup_VM/linux  -name "*.qcow2.gz" -mtime +30 |xargs /bin/rm -f {};
find /mnt/datastore1/backup_VM/linux  -name "*.xml" -mtime +30 |xargs /bin/rm -f {};

Очистка папки с бэкапами:

#!/bin/bash
#b14esh
find /mnt/datastore1/backup_VM/b14esh/ -type f -name "*.qcow2.gz" -mtime +30  -delete
find /mnt/datastore1/backup_VM/b14esh/ -type f -name "*.xml" -mtime +30 -delete
#mail
find /mnt/datastore1/backup_VM/mail/  -type f -name "*.qcow2.gz" -mtime +30 -delete
find /mnt/datastore1/backup_VM/mail/  -type f -name "*.xml" -mtime +30 -delete

Пример переноса ВМ:

На хосте с которого копируем ВМ:
0) Копируем диск на новый хост (файл myserver.qcow2)
1) Выгружаем настройки ВМ
virsh dumpxml myserver > /mnt/data-1/myserver.xml - сохранить настройки ВМ

На хосте на котором разворачиваем бэкап:
0) Восстанавливаем ВМ
virsh define /home/user/myserver.xml
1) При необходимости правим (указываем месторасположение образа жесткого диска):
virsh edit myserver

Пример восстановления ВМ:

На хосте на котором разворачиваем бэкап:
0) Восстанавливаем ВМ
Перенесли диски ВМ любым доступным способом
1) Подключили конфиг
virsh define /home/user/myserver.xml  
2) При необходимости правим (указываем месторасположение образа жесткого диска):
virsh edit myserver