ZFS for dummies – Les snapshot ca sauve de catastrophe

C’est quoi un snapshot (un instantané en Français) pour ZFS ?

Un instantané ZFS est une copie en lecture seule d’un système de fichiers ou d’un volume. La création des snapshot ZFS est quasiment immédiate. Initialement, elle ne consomme pas d’espace disque supplémentaire au sein du pool. Toutefois, à mesure que les données contenues dans le jeu de données actif changent, le snapshot consomme de l’espace disque en continuant à faire référence aux anciennes données et empêche donc de libérer de l’espace disque.

Concrètement cela permet de revenir quasiment immédiatement à la situation d’un système de fichier à l’heure ou au jour voulu, ou juste d’aller chercher un ou des fichiers supprimés par erreur. Cela permet aussi de faire des réplications de système de fichier, de basculer de développement à la production, d’archiver sur d’autres média une sauvegarde, etc.

Comment faire ? Dans mon cas en crontab je lance un script qui va faire des snapshot ZFS. (un par heure, et un chaque jour). Cela représente 31 snapshot  en une semaine, après quoi le script va détruire l’ancien snapshot de l’heure ou du jour pour faire le nouveau.

Exemple sur /usr/home

% zfs list  -t snapshot | grep /usr/home
zroot/usr/home@Thursday        883M      -   317G  -
zroot/usr/home@Friday          112M      -   317G  -
zroot/usr/home@Saturday       49.3M      -   317G  -
zroot/usr/home@Sunday         49.5M      -   317G  -
zroot/usr/home@Monday         71.1M      -   317G  -
zroot/usr/home@Tuesday         258M      -   318G  -
zroot/usr/home@hourly_18      1.22M      -   318G  -
zroot/usr/home@hourly_19      1.13M      -   318G  -
zroot/usr/home@hourly_20      1.05M      -   318G  -
zroot/usr/home@hourly_21      1.09M      -   318G  -
zroot/usr/home@hourly_22      1.07M      -   318G  -
zroot/usr/home@hourly_23      1.16M      -   318G  -
zroot/usr/home@hourly_00       732K      -   318G  -
zroot/usr/home@Wednesday       600K      -   318G  -
zroot/usr/home@hourly_01       644K      -   318G  -
zroot/usr/home@hourly_02       768K      -   318G  -
zroot/usr/home@hourly_03       764K      -   318G  -
zroot/usr/home@hourly_04       948K      -   318G  -
zroot/usr/home@hourly_05      1.18M      -   318G  -
zroot/usr/home@hourly_06      1.20M      -   318G  -
zroot/usr/home@hourly_07      1.44M      -   318G  -
zroot/usr/home@hourly_08      1.36M      -   318G  -
zroot/usr/home@hourly_09      1.43M      -   318G  -
zroot/usr/home@hourly_10      1.36M      -   318G  -
zroot/usr/home@hourly_11      1.30M      -   318G  -
zroot/usr/home@hourly_12      1.50M      -   318G  -
zroot/usr/home@hourly_13      34.8M      -   318G  -
zroot/usr/home@hourly_14      37.9M      -   318G  -
zroot/usr/home@hourly_15      45.2M      -   318G  -
zroot/usr/home@hourly_16      44.7M      -   318G  -
zroot/usr/home@hourly_17      23.3M      -   318G  -

# /etc/crontab ZFS snapshot (hourly & daily)
30 * * * * root /usr/local/bin/backup_snap.sh hourly >/dev/null 2>&1
25 0 * * * root /usr/local/bin/backup_snap.sh daily >/dev/null 2>&1

Le script “backup_snap.sh”:

#!/bin/sh

# défini une propriété de zone que l'on va exclure des snapshot.
# un peu comme le chflags nodump de UFS FreeBSD
#
# zfs set freebsd:nosnap=yes zroot/usr/ports
# zfs set freebsd:nosnap=yes zroot/usr/src
# zfs set freebsd:nosnap=yes zroot/tmp
# zfs set freebsd:nosnap=yes zroot/films
# zfs set freebsd:nosnap=yes zroot/var/tmp
# zfs set freebsd:nosnap=yes zroot/var/crash

# zfs list -o name,type,used,avail,mountpoint,compress,version,freebsd:nosnap

TYPE=$1

LANG="C"
export LANG

case $TYPE in
        daily)
                DATE=`date +"%A"`
        ;;
        hourly)
                DATE=`date +"hourly_%H"`
        ;;
        *)
                DATE=`date +"%A"`
        ;;
esac

# garde une trace de ce qui est installé sur la machine
pkg info >/root/pkg_info.txt

# snapshot destroy recursif
zfs destroy -r zroot@${DATE}

# snapshot recursif
zfs snapshot -r zroot@${DATE}

# efface les snapshot avec la property "freebsd:nosnap"

for d in `zfs list -H -t snapshot -o name,freebsd:nosnap  | grep -E 'yes$' | awk '{ print $1 }'` ; do
        zfs destroy $d
        done

exit 0;