backup_linux_kvm_par_snap
Table of Contents
Sauvegarde KVM à chaud par Snap
Le but est de minimiser les temps d'arrêt application des VM pour faire un backup, voici les étapes.
- Le chemin vers le fichier disk, est obtenu par virsh domblklist domain.
- Je vais utiliser la commande snapshot-create-as de virsh pour faire le snap.
- Le fichier disk principal n'est plus soumis aux écritures une fois le snap en place, je vais le sauvegarder via tar.
- Le répertoire de snap doit être sur le même disque que le volume de la vm (à vérifier, j'avais eu des problème).
- Une fois le backup effectué, je fais un virsh blockcommit pour revenir en écriture sur le volume d'origine de la vm.
- Le fichier snap peut être effacé.
J'ai essayé de rendre un peu plus robuste le script, il reste peut être des coquilles. J'utilise une debian 12.12 à ce jour.
Pour lancer un backup, lancer le script avec en paramètre le fichier environnement.
Par exemple:
- backup_vm.sh opnsense.env
Fichier environnement
BACKUP_PATH="/mnt/backup_vm/kvm" SNAP="/mnt/kvm/.snapshot" DOMAIN=opnsense MAIL_FROM="__EMAIL__" MAIL_TO="__EMAIL__" MAIL_SUBJECT="KVM backup"
Script de backup
#!/bin/bash
#
HOT=1 #backup a chaud
if [ $# -ne 1 ]; then
echo "Arguments error"
exit 1
fi
if [ ! -f "$1" ]; then
echo "File '$1' does not exist"
exit 1
fi
source $1
if [ ! -d $BACKUP_PATH ]; then
echo "Directory '$BACKUP_PATH' does not exist "
exit 1
fi
if [ ! -d $SNAP ]; then
echo "Directory '$SNAP' does not exist "
exit 1
fi
virsh domuuid $DOMAIN
if [ $? -ne 0 ]; then
echo "Domain '$DOMAIN' does not exist "
exit 1
fi
if [ ! -d $BACKUP_PATH/$DOMAIN ]; then
echo "Directory '$BACKUP_PATH/$DOMAIN' does not exist "
echo "Create directory $BACKUP_PATH/$DOMAIN"
mkdir $BACKUP_PATH/$DOMAIN
fi
#check if domain is running
if [ "$( LANG=C virsh domstate $DOMAIN )" != "running" ]; then
echo "Domain $DOMAIN not start - Cold backup mode"
HOT=0 #on backup a froid
fi
EXTENSION=$(virsh domblklist "$DOMAIN" --details | awk '$2=="disk" {n=split($4,a,"."); print a[n]}')
BACKUPDATE=$(date "+%Y-%m-%d.%H%M%S")
TARGET=$(virsh domblklist "$DOMAIN" --details | awk '$2=="disk" {print $3}')
DISK=$(virsh domblklist "$DOMAIN" --details | awk '$2=="disk" {print $4}')
SNAPFILE=${SNAP}/${DOMAIN}-snapshot-${BACKUPDATE}.${EXTENSION}
BACKUP_DOMAIN=${BACKUP_PATH}/${DOMAIN}
DISKSPEC="--diskspec ${TARGET},file=${SNAPFILE},snapshot=external"
MESSAGE=""
STATUS=""
send_mail()
{
printf "From: $MAIL_FROM\nTo: $MAIL_TO\nSubject: $MAIL_SUBJECT : $STATUS\n\n$MESSAGE\n" | msmtp $MAIL_TO
}
echo "creation du repertoire de sauvegarde ${BACKUP_DOMAIN}"
#creation du repertoire de sauvegarde
mkdir -p ${BACKUP_DOMAIN}
virsh dumpxml ${DOMAIN} > ${BACKUP_DOMAIN}/${BACKUPDATE}-${DOMAIN}.xml
if [ $? -ne 0 ]; then
echo "Failed to dumpxml $DOMAIN"
MESSAGE="Failed to dumpxml $DOMAIN"
STATUS="ERROR"
send_mail
exit 1
fi
if [ "$HOT" -eq 1 ]; then
echo "creation du snap ${DOMAIN}-snapshot-${BACKUPDATE}"
#creation du snap
virsh snapshot-create-as --domain ${DOMAIN} --name ${DOMAIN}-snapshot-${BACKUPDATE} --no-metadata --atomic --disk-only ${DISKSPEC}
if [ $? -ne 0 ]; then
echo "Failed to create snapshot for $DOMAIN"
MESSAGE="Failed to create snapshot for $DOMAIN"
STATUS="ERROR"
send_mail
exit 1
fi
fi
# On affiche le disk actif en écriture pour la vm, le snap normalement
virsh domblklist ${DOMAIN}
echo "copy ${DISK} to ${BACKUP_PATH}/${DOMAIN}/${BACKUPDATE}-${DOMAIN}.${EXTENSION}"
#copy
#cp ${DISK} ${BACKUP_PATH}/${DOMAIN}/${BACKUPDATE}-${DOMAIN}.${EXTENSION}
_FILE=${BACKUP_PATH}/${DOMAIN}/${BACKUPDATE}-${DOMAIN}.${EXTENSION}
#zpaq a ${_FILE}.zpaq ${DISK} -m2
tar --zstd -cvf ${_FILE}.tar.zstd ${DISK}
if [ $? -ne 0 ]; then
echo "Failed to copy ${DISK} to ${_FILE}"
MESSAGE="Failed to copy ${DISK} to ${_FILE}"
STATUS="ERROR"
send_mail
exit 1
fi
if [ "$HOT" -eq 1 ]; then
echo "retour sur snap blockcommit ${DOMAIN}"
#On arrêt le snap pour revenir écrire sur le disk d'origine
virsh blockcommit ${DOMAIN} ${TARGET} --active --pivot
if [ $? -ne 0 ]; then
echo "Failed to blockcommit snapshot for $DOMAIN"
MESSAGE="Failed to blockcommit snapshot for $DOMAIN"
STATUS="ERROR"
send_mail
exit 1
fi
fi
# On affiche le disk actif en écriture pour la vm, le disk d'origine
virsh domblklist ${DOMAIN}
echo "delete snap file $SNAPFILE"
#on peut delete le snap
if [ "$HOT" -eq 1 ]; then
rm $SNAPFILE
fi
#test de l'archive
#zpaq x ${_FILE}.zpaq -test
tar --zstd -tvf ${_FILE}.tar.zstd
if [ $? -ne 0 ]; then
echo "Failed : archive test ${_FILE}"
MESSAGE="Failed test file : {_FILE}"
STATUS="ERROR"
send_mail
exit 1
fi
MESSAGE="${MAIL_SUBJECT} [OK] Domain: $DOMAIN"
STATUS="OK"
send_mail
echo "[OK] - Status - Backup completed"
exit
backup_linux_kvm_par_snap.txt · Last modified: by ppj
