ZFS: Automatische Replikation via ssh

Ich habe das ZYNK-Script von Ben Rockwood dahingehend angepasst, dass es einen ZFS-Dataset vollständig (d. h. rekursiv, inklusive aller abhängigen Dateisysteme und Snapshots) auf einen Backup-Server repliziert. Das Script wird einmal am Tag via crontab aufgerufen, so dass die Daten der letzten Nacht auf dem Backup-Server zur Verfügung stehen. Es kann durchaus häufiger aufgerufen werden (jede Stunde oder auch mehrmals pro Stunde). Hier erst einmal das Skript:

#!/bin/bash
## ZYNK: The Zuper Zimple ZFS Sync (Replication) Tool
## Form: zynk local/dataset root@remote.host destination/dataset

# Please note: The reason this is so simple is because there is no error checking, reporting, or cleanup.
#               In the event that something goes wonkey, you'll manually need to fix the snapshots and
#               modify or remote the /var/run/zynk datafile which contains the most recent snapshot name.
# Furthermore, this absolutely relies on the GNU version of 'date' in order to get epoch time
# Before using, make sure you've distributed your SSH key to the remote host and can ssh without password.

if [ ! $3 ] 
then
        echo "Usage: zynk local/dataset root@remote.host destination/dataset"
        echo "WARNING: The destination is the full path for the remote dataset, not the prefix dataset stub."
        exit
fi

DATE=`date +%s`
if [ $DATE == "%s" ]
then
        echo "Must use GNU Date, please install and modify script."
        exit
fi

if [ -e /var/run/zynk ] 
then
        # Datafile is found, creating incr.
        echo "Incremental started at `date`"
        zfs snapshot -r ${1}@zynk-${DATE}
        zfs send -RI  ${1}@zynk-`cat /var/run/zynk` ${1}@zynk-${DATE} | ssh ${2} zfs recv -Fd ${3}
        zfs destroy -r ${1}@zynk-`cat /var/run/zynk`
        ssh ${2} zfs destroy -r ${3}@zynk-`cat /var/run/zynk`
        echo ${DATE} > /var/run/zynk
        echo "Incremental complete at `date`"
else 
        # Datafile not found, creating full.
        echo "Full started at `date`"
        zfs snapshot -r ${1}@zynk-${DATE}
        zfs send -R     ${1}@zynk-${DATE} | ssh ${2} zfs recv -Fd ${3}
        echo ${DATE} > /var/run/zynk
        echo "Full completed at `date`"
fi

In diesem Szenario soll tank/export vom Server (rubin) nach rpool/export auf dem Backup-Server (onyx) repliziert werden. Beide Systeme laufen mit OpenIndiana build 151a7. Das ZYNK-Skript liegt auf rubin unter /usr/bin/zynk. Der initiale Aufruf sieht wie folgt aus und dauerte hier mehrere Stunden (für 406 GB):

root@rubin:~# rm /var/run/zynk
root@rubin:~# zync tank/export onyx rpool
Full started at 20. November 2012 15:21:09 CET
Full completed at 21. November 2012 04:35:42 CET

Nach diesem ‚Full Backup‘ sind die inkrementellen Sicherungen schnell erledigt, da nur noch die Dateisystemänderungen (lies: Snapshots) gesendet werden, die seit dem letzten ZYNK-Aufruf angefallen sind:

root@rubin:~# zynk tank/export onyx rpool
Incremental started at 21. November 2012 13:39:24 CET
Incremental complete at 21. November 2012 13:48:11 CET

Um ZYNK jeden Tag um 2:00 Uhr automatisch aufzurufen, muss schließlich folgende Zeile in die root-crontab (crontab -e) eingetragen werden:

0  2 * * * /usr/bin/zynk tank/export onyx rpool

Das Skript setzt voraus, dass ein passwortloses (ssh-key-basiertes) root-Login möglich ist. Es empfiehlt sich allerdings einen dediziert zynk-Account mit entsprechenden Attributen zu benutzen. Wie schon dem Originalskript von Ben Rockwood, fehlt auch dieser Version jegliche Fehlerprüfung oder -behandlung.

Snow Leopard: ssh-Login-Problem

Nach einem Update von Mac OS X 10.5 (Leopard) nach 10.6 (Snow Leopard) war ein ssh-Login auf diesem Rechner nicht mehr möglich. Beim Versuch meldete der ssh-Client

$ ssh -vlroot 192.168.2.2
OpenSSH_5.2p1, OpenSSL 0.9.7l 28 Sep 2006
debug1: Reading configuration data /etc/ssh_config
debug1: Connecting to 192.168.2.2 [192.168.2.2] port 22.
debug1: Connection established.
debug1: identity file /Users/[...]/.ssh/identity type -1
debug1: identity file /Users/[...]/.ssh/id_rsa type -1
debug1: identity file /Users/[...]/.ssh/id_dsa type -1
debug1: Remote protocol version 2.0, remote software version OpenSSH_5.2
debug1: match: OpenSSH_5.2 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.2
debug1: SSH2_MSG_KEXINIT sent
Connection closed by 192.168.2.2

Hier sind beim Update offensichtlich die Zugriffsrechte der globalen ssh_host Files durcheinander geraten:

# ls -l /etc/ssh*
-rw-r--r-- 1 root wheel 1545 Feb 11 2010 /etc/ssh_config
-rw-rw-rw- 1 root admin 668 Sep 23 2011 /etc/ssh_host_dsa_key
-rw-rw-rw- 1 root admin 590 Sep 23 2011 /etc/ssh_host_dsa_key.pub
-rw-rw-rw- 1 root admin 963 Sep 23 2011 /etc/ssh_host_key
-rw-rw-rw- 1 root admin 627 Sep 23 2011 /etc/ssh_host_key.pub
-rw-rw-rw- 1 root admin 1671 Sep 23 2011 /etc/ssh_host_rsa_key
-rw-rw-rw- 1 root admin 382 Sep 23 2011 /etc/ssh_host_rsa_key.pub
-rw-r--r-- 1 root wheel 3723 Feb 11 2010 /etc/sshd_config

Diese müssen nach 0600 geändert werden, dann sollte es wieder laufen:

$ sudo chmod 600 /etc/ssh_host_*
$ ls -l /etc/ssh_host_*
-rw------- 1 root admin 668 Sep 23 2011 /etc/ssh_host_dsa_key
-rw------- 1 root admin 590 Sep 23 2011 /etc/ssh_host_dsa_key.pub
-rw------- 1 root admin 963 Sep 23 2011 /etc/ssh_host_key
-rw------- 1 root admin 627 Sep 23 2011 /etc/ssh_host_key.pub
-rw------- 1 root admin 1671 Sep 23 2011 /etc/ssh_host_rsa_key
-rw------- 1 root admin 382 Sep 23 2011 /etc/ssh_host_rsa_key.pub

In jedem Fall sollte man sicherstellen, dass sshd (unter SystemeinstellungenFreigabenEntfernte Anmeldung) aktiviert ist ;).