Einleitung
Das Management User Interface libvirt steuert QEMU welches auf KVM aufsetzt. Die Basis für dieses Backup/Restore bildet die Verkettung von Diskimages.
Da hier und in der restlichen Dokumentation nichts über ein restore zu finden ist und das backup bekanntlich erst nach einem restore erfolgreich sein kann - habe ich ein kurzes HowTo geschrieben. Das ist noch nicht perfekt!
Bitte am Ende den Abschnitt ToDo beachten!
Wem das zu sehr ins Detail geht, es gibt auf GitHub auch ein installierbares Tool welches die API von libvirt nutzt.
Vorbereitung
- Der qemu-guest-agent muss im Gast System installiert werden, damit beim Backup das Filesystem im Gast kurz angehalten werden kann.
- Um die Befehle universell zu halten habe ich ein paar Variablen definiert.
- Zur Steuerung des Backup sind ein paar XML Dateien notwendig, die werden mit einem kurzen Script erzeugt. (siehe weiter unten im Artikel)
Eine offline Sicherung (virsh shutdown ...) kann man durch Kopie des Diskimages machen, z.B erste Disk von win2k22 nach ./backup kopieren:
sudo cp $(virsh domblklist win2k22|awk 'NR >2 && NR < 4 {print $2}') ./backup/
Das im weiteren beschriebene Verfahren funktioniert nur bei laufender VM.
export vm=ubuntu22.04
export path2backup=/backup # mkdir -p $path2backup
export cpname=FirstCheckPoint
export dev=$(virsh domblklist ${vm}|awk 'NR >2 && NR < 4 {print $1}')
export disk=$(virsh domblklist ${vm}|awk -F\/ 'NR >2 && NR < 4 {print $NF}')
bash createxml.sh
Full Backup
Mit zwei Befehlszeilen sichert man die Definition und erzeugt eine Kopie des Diskimages.
virsh dumpxml ${vm} >${path2backup}/${vm}.xml
virsh backup-begin ${vm} b-${vm}.xml
Ein restore ist ziemlich simpel, man holt das Diskimage aus dem backup, definiert die Maschine neu und startet wieder.
sudo cp $(awk -F\' '/target file/{print $2}' b-${vm}.xml) /var/lib/libvirt/images/${disk}
virsh define ${path2backup}/${vm}.xml
virsh start ${vm}
Differential Backup
Man setzt den Startpunkt für die "Differenz" mit einem Fullbackup und einem Checkpoint.
virsh backup-begin ${vm} b-${vm}.xml c-${vm}.xml
Im weiteren Verlauf wird dann jedes mal der Unterschied zum Checkpoint gesichert.
virsh backup-begin ${vm} i-${vm}.xml
Für ein Restore muss das Fullbackup und die letzte Differenz aus dem Backup geholt werden. Die gesicherte Definition wird modifiziert, so das eine Disk Image Kette erzeugt wird. Gestartet wird die Virtuelle Maschine vom Overlay. Nach erfolgreichem Start kann das Overlay mit dem Backing Image wieder verschmolzen werden.
sudo cp $(awk -F\' '/target file/{print $2}' b-${vm}.xml) /var/lib/libvirt/images/${disk}
sudo cp $(awk -F\' '/target file/{print $2}' i-${vm}.xml) /var/lib/libvirt/images/
virsh define ${path2backup}/${vm}.xml
virsh update-device ${vm} d-${vm}.xml
virsh start ${vm}
virsh blockcommit ${vm} ${dev} --active --verbose --pivot
Dies und das
Für den Test muss man die VM nicht zerstören, ein shutdown vor dem Restore reicht.
Der Befehl backup-begin endet sofort und der Prozess läuft im Hintergrund. Um diesen abzufragen beziehungsweise in einem Script darauf zu warten, gibt es folgende Befehle:
virsh domjobinfo ${vm} --completed
virsh event ${vm} job-completed
Will man eine VM mit einem Checkpoint entfernen, sollte man zuerst den Checkpoint entfernen. Hat man experimentiert und es existiert ein checkpoint der nicht im Image zu finden ist, kann man die Option --metadata beim delete Befehl angeben.
virsh checkpoint-list ${vm}
virsh checkpoint-delete ${vm} ${cpname}
virsh shutdown ${vm} # oder virsh destroy ${vm}
virsh undefine ${vm}
Will man bei backup-begin die Dateien immer wieder überschreiben, muss man einen zusätzlichen Parameter verwenden: --reuse-external
Man kann das Backup noch packen und mit einem Zeitstempel versehen.
target=$(awk -F\' '/target file/{print $2}' b-${vm}.xml)
gzip -c ${target} > ${target}-$(date "+%F-%s").gz
Eine Schleife über alle laufenden Maschinen
for vm in $(virsh list --name)
do
virsh managedsave $vm
done
Script
Der Inhalt der Script Datei createxml.sh
cat <<EOI > b-${vm}.xml
<domainbackup>
<disks>
<disk name='${dev}' type='file'>
<driver type='qcow2'/>
<target file='${path2backup}/${disk}.backup'/>
</disk>
#<disk name='sda' backup='no'/>
</disks>
</domainbackup>
EOI
cat <<EOI > i-${vm}.xml
<domainbackup>
<incremental>${cpname}</incremental>
<disks>
<disk name='${dev}' type='file'>
<driver type='qcow2'/>
<target file='${path2backup}/${disk}.backup.inc'/>
</disk>
#<disk name='sda' backup='no'/>
</disks>
</domainbackup>
EOI
cat <<EOI > c-${vm}.xml
<domaincheckpoint>
<name>${cpname}</name>
<description>Completion of updates after OS install</description>
<disks>
<disk name='${dev}' checkpoint='bitmap'/>
#<disk name='sda' checkpoint='no'/>
</disks>
</domaincheckpoint>
EOI
cat <<EOI > d-${vm}.xml
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2' discard='unmap'/>
<source file='/var/lib/libvirt/images/${disk}.backup.inc' index='2'/>
<backingStore type='file'>
<format type='qcow2'/>
<source file='/var/lib/libvirt/images/${disk}'/>
</backingStore>
<target dev='vda' bus='virtio'/>
<address type='pci' domain='0x0000' bus='0x04' slot='0x00' function='0x0'/>
</disk>
EOI
ToDo
Das Ganze ist noch nicht komplett und funktioniert so nur für virtio Festplatten (vda).
Code Block
text
Keine Kommentare:
Kommentar veröffentlichen