Tutoriel : Sauvegarde Linux et Windows

Pour aller plus loin

Sauvegarde des attributs avancés

L’option -a de rsync utilisée dans ce tutoriel permet de sauvegarder l’essentiel des attributs des fichiers d’un client Linux. Néanmoins si l’on cherche à avoir une sauvegarde aussi fidèle que possible des données originales, il est possible de préserver également certains attributs avancés. On pourra donc ajouter éventuellement les options suivantes à la commande rsync utilisée pour la sauvegarde :
-A : préserver les ACLs
-H : préserver les hardlinks
-X : préserver les attributs étendus

Ces trois options ne sont pas incluses dans -a car rsync pouvant être compilé sans le support des ACLs ou des attributs étendus, les options -A et -H ne sont pas systématiquement disponibles. Elles nécessitent par ailleurs que le système de fichiers côté client comme serveur les supporte. Quant aux hardlinks, ils sont très onéreux à gérer en termes de mémoire et de puissance processeur, c’est pourquoi ils doivent être spécifiés explicitement.

On laisse donc à l’utilisateur désireux d’en tirer partie le soin de vérifier d’une part qu’il en a réellement besoin, et d’autre part que les conditions nécessaires à leur utilisation sont réunies.

Une contrainte supplémentaire vient du fait que si ces attributs peuvent être préservés par rsync lors de la sauvegarde, ils ne sont en revanche pas supportés par SFTP. Il ne sera donc pas possible de les restaurer par la méthode décrite dans ce tutoriel. Une solution possible reste de restaurer via rsync, mais le lecteur est libre d’en élaborer de nouvelles. Aucune je le crains ne sera toutefois aussi facile à mettre en oeuvre que SFTP…

Côté Windows, on a vu que ce tutoriel a pris le parti de se limiter à des sauvegardes basiques. Dans ce cadre, l’utilisation d’options avancées comme celles-ci est un peu hors-sujet, mais elles peuvent sans aucun doute être mises à profit pour améliorer la fidélité des sauvegardes. Comme précédemment, je suis ouvert à toute solution que trouvera le lecteur aventureux !

Expiration des sauvegardes

La personne qui a eu la patience de lire ce tutorial jusqu’à ces ligne se pose certainement la question suivante : jusqu’à quand les sauvegardes vont-elles s’accumuler sur le serveur ? Le stockage sur un système de fichiers BTRFS a beau être extrêmement efficace, l’espace disque côté serveur va fatalement arriver à saturation à un moment ou à un autre.

Il nous faut donc implémenter un mécanisme qui supprimera les anciennes sauvegardes au bout d’un certain temps afin de faire de la place pour les nouvelles. Le script suivant effectue une telle purge, en supprimant les sauvegardes antérieures à trois mois (90 jours).

/opt/btrbackup/bin/btrbackup_expire.sh :

#!/bin/bash

ARCHIVE_DIR=/data/btrfs
RETENTION=90

# Converts backup names to timestamps
fname2stamp()
{
	date --date="$(echo $1 | tr '@h' ' :')" +%s
}

expire_backups()
{
	local archivedir="$1"

	# We consider the most recent backup's time as being the present. This has the double
	# advantage of keeping us safe from the system's clock getting crazy, and of not leaving
	# us without any backup when we don't make any for longer than the retention period.
	recent=$(find "$archivedir" -maxdepth 1 -type d -name '????-??-??@??h??' >/dev/null | sort -r | head -n 1 | xargs -r basename)
	[ -z "$recent" ] && return
	recent=$(fname2stamp $recent)

	# Remove backups older than RETENTION (stamps are in seconds so we convert them to days)
	echo "Backups:"
        find "$archivedir" -maxdepth 1 -type d -name '????-??-??@??h??' 2>/dev/null | sort | while read fulldir; do
		backup=$(basename "$fulldir")
		stamp=$(fname2stamp "$backup")
		delta=$(((recent - stamp) / 60 / 60 / 24))
		if [ $delta -ge $RETENTION ]; then
			echo "  $backup: deleting"
			btrfs subvolume delete "$fulldir" >/dev/null
		else
			echo "  $backup: keeping"
		fi
	done
}

# Let's remove as many backups as possible
echo "Backup are in directory $ARCHIVE_DIR"
for clientdir in "$ARCHIVE_DIR"/*/; do
        client=$(basename "$clientdir")
	echo -e "\n\n** Expiring backups for client: '$client'\n"
	expire_backups "$clientdir/archives"
done

Bien entendu – et c’est recommandé – on pourra choisir une politique de rétention plus élaborée, du type Conserver une sauvegarde par jour pendant une semaine, puis une sauvegarde hebdomadaire pendant un mois, et une sauvegarde mensuelle pendant un an. De cette manière on peut conserver un historique très long tout en économisant l’espace disque. On pourra également spécifier une politique différente pour chaque client à l’aide de fichiers de configuration.

On sort là quelque peu du cadre de ce tutoriel, aussi le développement d’une telle solution est laissé au talent du lecteur. Qu’il sache toutefois que cela n’a rien d’insurmontable et que votre serviteur a relevé le défi sans trop de peine. Un seul mais précieux conseil : ne testez pas vos scripts directement sur vos sauvegardes, faites-en une copie ou vous le regretterez !

Déduplication

Le principe est simple : si des fichiers situés sur un même système de fichiers diffèrent très peu, on met en commun les blocs identiques de manière à économiser l’espace disque. Dans le cas de sauvegardes, le gain est important puisque la plupart des données ne sont guère modifiées entre deux sauvegardes. Deux versions d’un même fichier prises à quelques heures d’intervalle différeront donc probablement très peu.

Cet aspect de la déduplication est déjà fort bien géré par BTRFS en conjonction avec l’option --inplace de rsync (voir plus haut pour une explication plus complète).

Il existe néanmoins plusieurs cas dans lesquels cette déduplication automatique ne peut avoir lieu, par exemple :

  • un fichier a été déplacé ou renommé sur le client entre deux sauvegardes
  • un même fichier est présent sur plusieurs clients, éventuellement sous des noms différents

Dans ces situations il n’y a pas de lien a priori entre deux fichiers pourtant identiques. Chacun aura donc ses propres blocs sur le système de fichiers, ce qui conduit à un certain gaspillage d’espace. Imaginez que vous décidiez benoîtement de renommer les vidéos de vos vacances (de bons gros fichiers bien lourds) pour leur donner un nom plus parlant : l’espace nécessaire à leur sauvegarde double d’un seul coup…

La solution consiste à lancer à intervalles régulier le programme bedup qui va scanner le système de fichiers contenant les sauvegardes à la recherche de fichiers présentant des blocs communs. Il modifie alors les métadonnées des fichiers pour les faire pointer vers une unique série de blocs et supprime les autres.

Malheureusement, la quantité de mémoire nécessaire à la recherche des duplicats augmente exponentiellement avec la taille des données examinées. Il faut donc trouver une façon de procéder qui réduise la quantité de données que doit considérer bedup. Pour ma part j’ai trouvé un compromis satisfaisant en dédupliquant chaque sauvegarde d’un client :

  • avec la version précédente d’elle même (pour le cas où un fichier a été renommé)
  • avec les sauvegardes des autres clients datant du même jour (pour le cas où des fichiers sont présents sur plusieurs clients)
  • en ne tenant compte que des fichiers de plus de 10 Mo (la place gagnée en dédupliquant de petits fichiers ne mérite pas les ressources mobilisées)

Pour finir, précisons que la déduplication a ses détracteurs, notamment en ce qui concerne son utilisation dans le cadre de sauvegardes. Ceux-ci considèrent en effet que son principe même (ne conserver qu’une seule copie de chaque bloc) est contraire à l’esprit de la sauvegarde dont le but est de sécuriser ses données au maximum. Gagner de la place c’est très bien, mais que se passe-t-il lorsqu’un secteur du disque devient défectueux ? Ce n’est pas juste un fichier qui se trouve corrompu, mais tous ceux qui partagent ce bloc, c’est à dire probablement la plus grande partie des versions antérieures et postérieures de ce fichier, ainsi que ses copies sous un nom différent.

Le problème peut néanmoins être mitigé en ne dédupliquant que des fichiers volumineux qui supportent bien quelques blocs vérolés (les vidéos par exemple), en basant son stockage sur une grappe RAID ou encore en copiant régulièrement les sauvegardes sur un support externe (ce qui est de toute façon une pratique à recommander). Je laisse au lecteur le soin de peser le pour et le contre avant de prendre la décision ou non d’utiliser cette technique…

Supervision

L’inconvénient des sauvegardes qui se font oublier, c’est que lorsque quelque chose va de travers on met parfois un certain temps avant de s’en apercevoir. Les fichiers de log sont très utiles pour trouver l’origine d’un problème, mais il est inconcevable d’aller les consulter tous les jours sur chaque machine pour vérifier que les sauvegardes se sont bien déroulées.

Fort heureusement, avec le système mis en place cette vérification est très simple. Seules les sauvegardes réussies (c’est à dire validées par le client) sont archivées. Il nous suffit donc de mesurer la durée écoulée depuis la dernière sauvegarde de chaque client, et d’émettre une alerte lorsque celle-ci dépasse un certain seuil. Cette supervision a lieu au niveau du serveur qui héberge les sauvegardes et se trouve donc centralisée sur une unique machine, ce qui nous simplifie grandement la tâche.

Voici un exemple de script qui placé dans la crontab du serveur enverra un email d’alerte si l’un des clients n’a pas été sauvegardé depuis une semaine.

/opt/btrbackup/bin/btrbackup_check.sh :

#!/bin/bash

ARCHIVE_DIR=/data/btrfs
ALERT_THRESHOLD=7

# Converts backup names to timestamps
fname2stamp()
{
	date --date="$(echo $1 | tr '@h' ' :')" +%s
}

# Send alert emails if clients have not been backed up for more than $ALERT_THRESHOLD days
for clientdir in "$ARCHIVE_DIR"/*/; do
        client=$(basename "$clientdir")
	echo -e "\n\n** Checking that recent backups exist for client: '$client'\n"
        recent=$(find "$clientdir/archives" -maxdepth 1 -type d -name '????-??-??@??h??' 2>/dev/null | sort -r | head -n 1 | xargs -r basename)
	[ -z "$recent" ] && continue
	recent=$(fname2stamp $recent)
	now=$(date +%s)
	days_since_last=$(( (now - recent) / 60 / 60 / 24 ))
	if [ $days_since_last -lt $ALERT_THRESHOLD ]; then
		echo "Yes ($days_since_last days)"
	else
		echo "No ($days_since_last days): sending email"
		cat - <
Subject: [btrbackup] Pas de sauvegarde de $client depuis $days_since_last jours

Mail d'alerte envoyé par /opt/btrbackup/bin/btrbackup_check.sh sur $(hostname).
EOF
	fi
done

2 thoughts on “Tutoriel : Sauvegarde Linux et Windows”

  1. Merci pour ce très mon tutoriel :-).

    j’ai juste un soucis au niveau de la configuration de ssh : je n’arrive pas utiliser l’attribut loaclport dans les MATCH du fichier sshd_config,et d’après le man et les recherche que j’ai fait sur le net cet attribut n’existe pas !

    Pouvez vous me dire comment vous avez fait ?

    Merci

    PS : je suis sous debian 7.1.0 avec ssh 6.0p1

  2. Bonjour,

    merci pour ce tutoriel, sur mon client, on me demande une passphrase qui est a blanc dans ton tuto. je l’ai changé par autre chose et rien n’y fait.

    J’ai transfere le .pub de mon serveur de sauvegarde vers mon client mais ca ne marche pas.

    je suis débutant sur Linux mais bon je trouve ce tutoriel vraiment bien.

Les commentaires sont clos.