Copie récursive de pools ZFS locale et / ou distante, comment ?

Submitted by-badmin- onMon, 03/26/2018 - 12:18

ZFS c'est bien et beau, ça, on le savait déjà !

Ce qui est encore plus fantastique, c'est de pouvoir copier un pool zfs entier, de manière récursive, en y incluant les snapshots et les propriétés des datasents enfants, grâce à zfs send et zfs receive, qui servent également à la géoréplication asynchrone.

La seule contrainte, tout dataset et dataset enfant à copier doit posséder un snapshot, car c'est sur les snapshots que se base zfs send pour envoyer des données consistantes.

Nous allons donc commencer par créer un snapshot de l'ensemble des datasets:

for i in $(zfs list -p | cut -f1 -d' ' | grep nomdupool); do zfs snapshot "$i@2018032601"; done

Ici, nous faisons la liste des datasets avec zfs list, et nous serbons de cut pour ne garder que la première colonne. Enfin, le grep permet de s'assurer de limiter la sortie uniquement qu'au pool que l'on souhaite snapshotter.

Pour chaque ligne de sortie de cette commande zfs, nous créerons un snapshot.

Une fois fait, nous pouvons envoyer ce snapshot vers un pool récepteur avec:

nohup zfs send -R nomdupool@2018032601 | zfs recv -Fv nouveaupool> /root/zfs_send.log 2>&1 &

L'utilisation de nohup permet de détacher la commande du TTY, évitant d'arrêter la commande si l'utilisateur venait à se déconnecter.

zfs send -R signifie qu'il faille envoyer l'ensemble du pool en mode "réplication", soit l'ensemble du pool et de ses descendants.

zfs recv -Fv signifie qu'il faille forcer un rollback du pool cible, et afficher les messages verbeux.

Nous redirigeons aussi la sortie de la commande vers un fichier log afin de vérifier le bon déroulé des opérations avec > fichier 2>&1.

Enfin, le '&' signifie qu'il faille lancer cette commande en arrière plan.

 

Pendant l'opération, il sera possible de vérifier les statistiques des disques avec

iostat -dx

Ou encore suivre l'état de la copie avec

tail -f /root/zfs_send.log

Cerise sur le gâteau, le nouveau pool ZFS est d'origine défragmenté. D'ailleurs, cette solution est la seule à ce jour permettant de défragmenter un pool zfs, à savoir envoyer les données sur un autre stockage, détruire le pool puis le recopier depuis la sauvegarde, nécessitant évidemment du downtime :(

 

Enfin, pour une copie entre deux machines, il convient d'utiliser ssh entre zfs send et receive, qui permet de transporter et crypter les données de transfert.

Cela étant, si les machines sont sur le même réseau local, il est possible d'accélérer substantiellement la copie en remplaçant ssh par un netcat.

Sur la machine cible:

nc -w 120 -l 5001| zfs receive -F nouveaupool

-l 5001 signifie qu'il faille écouter sur le port 5001, choisi arbitrairement car c'est le port par défaut de ipferf qui risque déjà d'être configuré dans le parefeu.

-w 120 signifie qu'il faille écouter pendant 120 secondes (afin de ne pas laisser un port d'écoute ouvert indéfiniment)

Sur la machine source:

zfs send -R pool@2018032701 | nc -w 20 10.69.254.99 5001

-w avec un timeout de 20 secondes, suivi de l'adresse IP et du port de destination.