Utilisation des snapshots LVM comme solution de backup

Un des intérêts de LVM, est de pouvoir créer des snapshots de volume sans perturber le fonctionnement de la machine, sans interruption de services. A l’aide de simples scripts, l’automatisation des backups en est grandement facilité.

Les snapshots de LVM

Les snapshots permettent de créer un cliché d’un volume à instant t.  C’est une opération rapide, même pour les volumes importants et ne nécessite pas forcément beaucoup de ressource disque.
La création de snapshot s’effectue par la commande suivante :

lvcreate -n nomdusnapshot -l 10%ORIGIN -s LVVolume

où :

  • LVVolume est le device du volume, comme /dev/LVM/SRV
  • nomdusnapshot est le nom du snapshot
  • -l 10%ORIGIN est la taille du snapshot, dans cet exemple elle sera de 10% par rapport au volume d’origine. On peut lui indiquer une grandeur réelle avec -l 100M par exemple.

La taille du snapshot est la taille allouée pour enregistrer les différences entre le snapshot et le disque d’origine.
Si la quantité de modification dépasse la quantité allouée, le snapshot ne sera plus utilisable. Mais nous pouvons agrandir celui-ci par un lvextend avant qu’elle atteigne sa limite.

Le volume créé, peut-être monté comme n’importe quelle autre volume.

Mise en place d’une stratégie de sauvegarde

Je vous propose un script bash de backup minimaliste. Ce n’est qu’un exemple qui peut être grandement amélioré.

Ce script répond à 2 stratégies :

  • La mise en place de sauvegardes automatiques

Elle sera dédiée aux volumes data, comme le répertoire /home et le répertoire /srv dans le cas d’une structure de fichiers de type FHS.

  • La mise en place de points de sauvegardes

C’est une sauvegarde manuelle, faite lors d’opérations de maintenance ou d’upgrade du système. Elle s’effectue sur les répertoires /,  /usr , /opt

Pré-requis

Le script utilise bzip2, s’il n’est déjà pas présent, installez le par :

apt-get install bzip2

Contenu du script /sbin/lvbackup (attention, le nom du script est important)

#!/bin/bash
[ -z "${1}" ] && echo "Missing LVNAME" && return 0 || LVNAME=${1}

GLOBALCONFFILE="/etc/lvbackup.conf/lvbackup.conf"
LVCONFFILE="/etc/lvbackup.conf/$LVNAME.conf"

PRE_SNAP_CMD=/etc/lvbackup.conf/$LVNAME-pre-snap
POST_SNAP_CMD=/etc/lvbackup.conf/$LVNAME-post-snap

if [ ! -f "$GLOBALCONFFILE" ]; then
         echo "Missing configuration file $GLOBALCONFFILE !"
        exit 1
fi

if [ ! -f "$LVCONFFILE" ]; then
        echo "Missing configuration file $LVCONFFILE !"
        exit 1
fi

. $GLOBALCONFFILE
. $LVCONFFILE

LVVOLUME=/dev/$VGNAME/$LVNAME

case `basename $0` in
    lvautobackup)
        [ -z "$HISTOSIZE" ] && HISTOSIZE=5
        [ -z "${2}" ] && SNAPTAG=AUTOBACKUP-$LVNAME-  || SNAPTAG=AUTOBACKUP-${2}-$LVNAME-
        ;;
    *) unset HISTOSIZE
        [ -z "${2}" ] && SNAPTAG=SAVE-$LVNAME-  || SNAPTAG=${2}-$LVNAME-
        ;;
esac

SNAPNAME=$SNAPTAG$(date -u +%Y.%m.%d-%H.%M.%S)

if [ ! -e "$LVVOLUME" ]; then
    echo "Volume not found : $LVVOLUME!"
    exit 1
fi
[ -z "$TARFLAGS" ]  || TARFLAGS=""
for t in ${EXCLUDE[*]}
do
        TARFLAGS="$TARFLAGS --exclude=/mnt/$SNAPNAME/snap$t"
done

logger "$(date -u +%Y.%m.%d-%H.%M.%S) - $LVVOLUME  - Start backup "

[ -f "$PRE_SNAP_CMD" ] && $PRE_SNAP_CMD
lvcreate -n $SNAPNAME -l 10%ORIGIN -s $LVVOLUME
[ -f "$POST_SNAP_CMD" ] && $POST_SNAP_CMD

mkdir /mnt/$SNAPNAME
mkdir /mnt/$SNAPNAME/snap
mkdir /mnt/$SNAPNAME/bckup
echo "mounting $BACKUPDEV on /mnt/$SNAPNAME/bckup"

mount $BACKUPDEV /mnt/$SNAPNAME/bckup
mount /dev/$VGNAME/$SNAPNAME /mnt/$SNAPNAME/snap
logger "$(date -u +%Y.%m.%d-%H.%M.%S) - $LVVOLUME - Begin compression"

tar -cjv $TARFLAGS -f /mnt/$SNAPNAME/bckup/$SNAPNAME.bz2 /mnt/$SNAPNAME/snap

[ -z "$HISTOSIZE" ] ||  ls -rt /mnt/$SNAPNAME/bckup/$SNAPTAG*.bz2 | head -n -$HISTOSIZE | xargs rm

umount /mnt/$SNAPNAME/bckup
umount /mnt/$SNAPNAME/snap
lvremove -f  /dev/$VGNAME/$SNAPNAME

rm -rf /mnt/$SNAPNAME
logger "$(date -u +%Y.%m.%d-%H.%M.%S) - $LVVOLUME  - backup successful as $BACKUPDEV/$SNAPNAME.bz2"

un lien symbolique sera créé pour les sauvegardes automatiques :

ln -s /sbin/lvbackup /sbin/lvautobackup

Ce script a besoin de fichiers de configuration :

Le premier, général, détermine la destination des sauvegardes :

# /etc/lvbackup.conf/lvbackup.conf
BACKUPDEV=/dev/vol

Le deuxième, spécifique au volume que l’on souhaite sauvegarder.

XXX doit être le nom du volume à sauvegarder ( la casse est importante)

# /etc/lvbackup.conf/XXX.conf
# XXX Backup configuration
# Groupe de volume (VG)
VGNAME=LVM
# Taille de l'historique des backup pour les sauvegardes automatiques
HISTOSIZE=3
# Liste des répertoires à ignorer
EXCLUDE=( ....)

optionnellement, nous pouvons ajouter deux scripts d’exécution de tache. Le premier qui opère juste avant  le snapshot, et le second juste après :

XXX-pre-snap et XXX-post-snap

Ces deux scripts nous serviront à effectuer des opérations visant à obtenir un snapshot cohérent au niveau des données. Typiquement, si une base de données est hébergée sur le volume, il convient de flusher et de locker les tables pendant le snapshot. L’impacte de cette opération au niveau des clients est très faible car le snapshot est rapide.

Installation et paramétrage typique

Pour les exemples ci-dessous, je prendrais comme architecture de référence celle décrite dans le sujet : Modèle de Serveur Debian Raid5 et LVM passe partout

Création de volume de stockage des backups :

root@localhost:~# lvcreate -L 200G -n BACKUP LVM
root@localhost:~# mkfs.ext3 /dev/LVM/BACKUP

Un petit tour sur les volumes existants :

root@localhost:~# lvs
  LV     VG   Attr   LSize   Origin Snap%  Move Log Copy%  Convert
  BACKUP LVM  -wi-a- 279,39g
  HOME   LVM  -wi-ao  93,13g
  OPT    LVM  -wi-ao  46,56g
  ROOT   LVM  -wi-ao  18,62g
  SRV    LVM  -wi-ao  93,13g
  TMP    LVM  -wi-ao 952,00m
  USR    LVM  -wi-ao  46,56g
  VAR    LVM  -wi-ao  18,62g

Création des fichiers de configuration

# /etc/lvbackup.conf/lvbackup.conf
BACKUPDEV=/dev/LVM
# /etc/lvbackup.conf/SRV.conf
# SRV Backup configuration
# Groupe de volume (VG)
VGNAME=LVM
# Taille de l'historique des backup pour les sauvegardes automatiques
HISTOSIZE=10
# /etc/lvbackup.conf/HOME.conf
# HOME Backup configuration
# Groupe de volume (VG)
VGNAME=LVM
# Taille de l'historique des backup pour les sauvegardes automatiques
HISTOSIZE=10
# /etc/lvbackup.conf/USR.conf
# USR Backup configuration
# Groupe de volume (VG)
VGNAME=LVM
# /etc/lvbackup.conf/ROOT.conf
# ROOT Backup configuration
# Groupe de volume (VG)
VGNAME=LVM
EXCLUDE=( "/lib" "/tmp" "/var" "/mnt" "/opt" "/home" "/srv" "/media" "/dev" "/boot" "/proc" "/sys" "/root")
# /etc/lvbackup.conf/OPT.conf
# OPT Backup configuration
# Groupe de volume (VG)
VGNAME=LVM

Le fichier de configuration du Root est particulier car nous ne devons pas prendre en compte les volumes attachés, ni les répertoires temporaires et virtuels.

Cas particulier :

Dans le cadre de l’architecture FHS, notre base de données est hébergé sur /srv/mysql-data. Comme évoqué précédemment, pour garantir un état stable de celle-ci nous devons ajouter deux scripts :
/etc/lvbackup.conf/SRV-pre-snap:

#!/bin/bash
DATABASES=`echo "SHOW DATABASES;" | mysql  --skip-column-names  -u root  --password=admin`
for DB in $DATABASES; do
        echo "Flush database $DB"
        echo "FLUSH TABLES WITH READ LOCK;" | mysql $DB -u root  --password=admin
done

et /etc/lvbackup.conf/SRV-post-snap

#!/bin/bash
DATABASES=`echo "SHOW DATABASES;" | mysql  --skip-column-names  -u root  --password=admin`
for DB in $DATABASES; do
        echo "Unlock database $DB"
        echo "UNLOCK TABLES;" | mysql $DB -u root  --password=admin
done

Il convient pour ce genre de script, de créer un compte spécifique pour la maintenance avec les droits appropriés pour effectuer cette tache.

N’oublions pas de mettre les attributs des fichiers :

root@localhost:~# chmod 755 /sbin/lvbackup
root@localhost:~# chmod 755 /sbin/lvautobackup
root@localhost:~# chmod 755 /etc/lvbackup.conf/SRV-pre-snap
root@localhost:~# chmod 755 /etc/lvbackup.conf/SRV-post-snap

Sauvegarde manuel

Profitons-en pour sauvegarder notre configuration de base :

root@localhost:~# lvbackup OPT ; lvbackup ROOT ; lvbackup USR

un petit coup d’oeil sur le répertoire de backup pour voir si tout s’est passé normalement :

root@localhost:~# mkdir /mnt/backup
root@localhost:~# mount /dev/LVM/BACKUP /mnt/backup/
root@localhost:~# ls -al /mnt/backup/
total 144772
drwxr-xr-x 2 root root      4096  3 avril 11:34 .
drwxr-xr-x 3 root root      4096  3 avril 11:39 ..
-rw-r--r-- 1 root root       201  3 avril 11:34 SAVE-OPT-2013.04.03-09.34.17.bz2
-rw-r--r-- 1 root root   4641326  3 avril 11:34 SAVE-ROOT-2013.04.03-09.34.18.bz2
-rw-r--r-- 1 root root 143274574  3 avril 11:37 SAVE-USR-2013.04.03-09.34.43.bz2
root@localhost:~# umount /mnt/backup/
root@localhost:~# rm -r /mnt/backup

Note : on peut ajouter un tag spécifique comme aide mémoire par exemple

root@localhost:~# lvbackup OPT ADD-REDMINE

Sauvegarde automatique

Pour les répertoires HOME nous utiliserons une sauvegarde journalière tandis que /srv aura une sauvegarde journalière et une toute les heures.

Ajoutons dans le fichier /etc/crontab :

00 * * * * root /sbin/lvautobackup SRV HOURLY
15 1 * * * root /sbin/lvautobackup SRV
15 1 * * * root /sbin/lvautobackup HOME

attendons l’heure passée pour vérifier la configuration :

root@localhost:~# mkdir /mnt/backup
root@localhost:~# mount /dev/LVM/BACKUP /mnt/backup/
root@localhost:~# ls -al /mnt/backup/total 144920
drwxr-xr-x 2 root root      4096  3 avril 12:00 .
drwxrwxrwt 3 root root      4096  3 avril 12:00 ..
-rw-r--r-- 1 root root    147329  3 avril 12:00 AUTOBACKUP-HOURLY-SRV-2013.04.03-10.00.01.bz2
-rw-r--r-- 1 root root       201  3 avril 11:34 SAVE-OPT-2013.04.03-09.34.17.bz2
-rw-r--r-- 1 root root   4641326  3 avril 11:34 SAVE-ROOT-2013.04.03-09.34.18.bz2
-rw-r--r-- 1 root root 143274574  3 avril 11:37 SAVE-USR-2013.04.03-09.34.43.bz2
root@localhost:~# umount /mnt/backup/
root@localhost:~# rm -r /mnt/backup

Restauration

Il n’y a pas de script de restauration, car le besoin de restauration peut être de plusieurs nature

  • soit une restauration complète

En ce cas, nous créerons un autre volume, puis recopierons le backup dans celui-ci, et remplacerons l’ancien volume parle nouveau.

  • soit une restauration partielle

Après extraction de l’archive, nous remplacerons le contenu d’un répertoire par celui de l’archive

 Pour conclure

Voici donc un script permettant d’effectuer des sauvegardes manuelles et automatique. En revanche, il sera nécessaire d’enrichir ce script pour pouvoir stocker les backup sur une autre machine via ssh, rsync par exemple.

Cet article vous a été utile ? Partage it !

7 réflexions au sujet de « Utilisation des snapshots LVM comme solution de backup »

    1. Bonjour Pierre,
      Merci 🙂 (et merci à Franck qui a rédigé cet article, poke !)
      SimonBot a l’air intéressant, je vais essayer tiens !
      David

  1. Hello,
    Il y a un passage qui n’est pas très clair.
    « elle sera de 10% par rapport au volume d’origine ».
    donc si mon volume /dev/LVM/SRV est de 100Go, le snapshot sera de 10Go ?!
    Elle ne sera pas très utilisable cette backup…
    Pouvez-vous préciser ce passage?

  2. Donc vous êtes en train de me dire qu’en créant un snapshot de 10% d’un disque vous arrivez a faire une backup utilisable ? ça tient de la magie … chapeau

    1. Alors, je suis en train de dire que 10% de 100Go font 10Go.
      Et cette valeur de 10% est un exemple, vous pouvez mettre la valeur que vous souhaitez.
      Bon courage 🙂
      David

  3. Et vous ne pensez pas que pour avoir une backup exploitable cela devrait être 100% de la taille d’un disque dans tous les cas ?

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Si vous le souhaitez, renseignez le champ 'Nom' de cette façon : 'VotreNom@VotreMotClef' pour obtenir une ancre optimisée pour les moteurs de recherche.