# Automatisation des snapshots LVM comme solution de backup {{METATOC 4-5}} 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é. Cet article présente un script bash de backup minimaliste. Ce n’est qu’un exemple qui peut être grandement amélioré. #### 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 on peut 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 La stratégie répond à 2 objectifs: * La mise en place de sauvegardes automatiques, dédiée aux volumes data, comme le répertoire `/home` et le répertoire `/srv` . * 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` #### Script de backup Le script utilise bzip2, : ``` 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" ``` #### Fichiers de configuration 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, on peut 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 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. #### 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éations d'un lien symbolique pour les sauvegardes automatiques : ``` ln -s /sbin/lvbackup /sbin/lvautobackup ``` Création de volume de stockage des backups : ``` # lvcreate -L 200G -n BACKUP LVM # mkfs.ext3 /dev/LVM/BACKUP ``` Un petit tour sur les volumes existants : ``` # 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 il ne doit pas prendre en compte les volumes attachés, ni les répertoires temporaires et virtuels. La base de données est hébergé sur /srv/mysql-data, pour garantir un état stable de celle-ci il faut 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. Définir les attributs des fichiers : ``` # chmod 755 /sbin/lvbackup # chmod 755 /sbin/lvautobackup # chmod 755 /etc/lvbackup.conf/SRV-pre-snap # chmod 755 /etc/lvbackup.conf/SRV-post-snap ``` #### Sauvegarde manuelle Pour valider l'installation sauvegarder la configuration de base : ``` # 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 : ``` # mkdir /mnt/backup # mount /dev/LVM/BACKUP /mnt/backup/ # 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 ``` On peut ajouter un tag spécifique comme aide mémoire par exemple:\\ \\ `root@localhost:~# lvbackup OPT ADD-REDMINE` #### Automatisation de la sauvegarde Pour les répertoires HOME on programme une sauvegarde journalière tandis que `/srv` aura une sauvegarde journalière et une toute les heures. Ajouter dans le fichier /etc/crontab : ``` 00 * * * * root /sbin/lvautobackup SRV HOURLY 15 1 * * * root /sbin/lvautobackup SRV 15 1 * * * root /sbin/lvautobackup HOME ``` attendre l’heure passée pour vérifier la configuration : ``` # mkdir /mnt/backup # mount /dev/LVM/BACKUP /mnt/backup/ # 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 # umount /mnt/backup/ # 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**: créer un autre volume, puis recopier le backup dans celui-ci, et remplacer l’ancien volume par le nouveau. * **soit une restauration partielle**: après extraction de l’archive, remplacer le contenu d’un répertoire par celui de l’archive