Auf Nummer sicher: Backupstrategie

Als ich heute mit Dennis, der jetzt seine Backup-Strategie aufstockt, über mögliche Backup-Implementationen diskutiert habe, kam mir die Idee, meine persönliche Vorgehensweise zu erläutern.

Die Hardware

Neben den Clients, die die zu sichernden Daten beherbergen, steht mir folgende Hardware für Backups zur Verfügung:

  • NAS - Eigenbau-Gerät mit energiesparendem AMD-Prozessor, 4 GB Arbeitsspeicher und sechs 1 TB-Festplatten im Software-RAID 5 (4.5 TB nutzbar)
  • Bandroboter - ein gebrauchter HP StorageWorks DAT72-Autoloader mit einem DDS5-Bandlaufwerk und 10 Schächten für Medien
  • Externe Festplatte (genau genommen ein DAS) - eine Onnto DataTale mit vier 2 TB-Festplatten im RAID5 (6 TB nutzbar)

Bandroboter, NAS und DAS

Datenüberblick

Die erste Frage dürfte jetzt sein, was überhaupt gesichert wird. Sicherungen werden auf meinem NAS pro "Sicherungsziel" angelegt - solche Sicherungsziele sind beispielsweise:

  • Der Webserver, auf dem dieser Blog läuft 😉
  • Mein Notebook
  • Die virtuellen Maschinen meines Hypervisors
  • ...

Für jedes Sicherungsziel wird auf dem NAS ein Ordner angelegt. Innerhalb dieses Ordners existiert ein Unterordner "latest" - in diesem Ordner landen dann die jeweils zu sichernden aktuellen Daten. Wenn eine Sicherung isoliert von neueren aufbewahrt werden soll, genügt es den Ordnernamen zu ändern. So habe ich schnell und unkompliziert einen "Snapshot". Auf dem NAS befindet sich im Backup-Ordner für jedes Sicherungsziel eine Blacklist-Datei (Sicherungsziel_blacklist), die eine Liste von Ordnern und Dateien, die nicht auf Band gesichert werden sollen, enthält.

Überblick des Konzepts

Skripte und Logdateien

Für die Sicherung der einzelnen Sicherungsziele habe ich mir diverse Skripte programmiert, die mir einige händische Arbeit abnehmen und den Prozess so beschleunigen.

Sicherungen eines Ziels erfolgen mithilfe des folgenden Skripts:

  1#!/bin/bash
  2
  3###########################################
  4#                                         #
  5#    !!! AUTOMATISIERTE  SICHERUNG !!!    #
  6#                                         #
  7###########################################
  8
  9#Variablendeklaration
 10backups_path="/mnt/storage/data/Backups"
 11exclude_file_prefix="blacklist_"
 12max_size_gb=200
 13dev_streamer="$1"
 14
 15#Datumprefix und Logfile erstellen
 16logprefix="$(date +"%d_%m_%Y_%H_%M")"
 17if [ -d "/var/log/backup/tape/$2" ]; then
 18    #Ordner vorhanden
 19    echo "Log directory for this target (/var/log/backup/tape/$2) exists."
 20else
 21    #Ordner nicht vorhanden
 22    mkdir -p /var/log/backup/tape/$2
 23    echo "Log directory for this target (/var/log/backup/tape/$2) didn't exist -  I created it for you. 🙂"
 24fi
 25echo "log file from $(date)" >> /var/log/backup/tape/$2/$logprefix.log
 26echo "parameters were:   $1 $2 $3 $4" >> /var/log/backup/tape/$2/$logprefix.log
 27
 28#Wurde ein Streamer angegeben?
 29if [ "$1" = "" ]; then
 30        #Nein
 31    echo "ERROR: You must specify a streamer device (e.g. nst0)!" | tee -a /var/log/backup/tape/$2/$logprefix.log
 32    exit 1
 33fi
 34
 35#Wurde ein Ziel angegeben?
 36if [ "$2" = "" ]; then
 37    #Nein
 38    echo "ERROR: You must specify a target (e.g. host)!" | tee -a /var/log/backup/tape/$2/$logprefix.log
 39    echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
 40    exit 1
 41fi
 42
 43#Flag setzen
 44if [ "$3" = "--from" ]; then
 45    #Ein vorheriges Backup wurde angefordert --> wurde ein Datum angegeben?
 46    if [ "$4" = "" ]; then
 47        #Nein
 48        echo "ERROR: You need to tell me the backup date in DD_MM as parameter after --from!" | tee -a /var/log/backup/tape/$2/$logprefix.log
 49        echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
 50        exit 1
 51    else
 52        sel_flag="$4"
 53    fi
 54
 55else
 56    #Setze Flag
 57    sel_flag="latest"
 58fi
 59
 60#Ordner fuer Backup vorhanden?
 61if [ -d "$backups_path/$2/$sel_flag" ]; then
 62        #Ja
 63        echo "Backup exists" | tee -a /var/log/backup/tape/$2/$logprefix.log
 64else
 65    #Nein
 66           echo "ERROR: There is no backup #$sel_flag for that target!" | tee -a /var/log/backup/tape/$2/$logprefix.log
 67           echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
 68        exit 1
 69fi
 70
 71#Ueberpruefe ob das Backup auf das Tape passt
 72backup_size="$(du -cs $backups_path/$2/$sel_flag --exclude-from=$backups_path/$exclude_file_prefix$2 | grep insgesamt | cut -f1)"
 73echo -n "Backup size is $backup_size kbytes" | tee -a /var/log/backup/tape/$2/$logprefix.log
 74
 75if [ "$backup_size" -gt "$(($max_size_gb*1024*1024))" ]; then
 76    #Nein
 77    echo ", more than $max_size_gb gbytes - that won't fit!" | tee -a /var/log/backup/tape/$2/$logprefix.log
 78       echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
 79       exit 1
 80else
 81    #Ja
 82    echo " - that will fit." | tee -a /var/log/backup/tape/$2/$logprefix.log
 83fi
 84
 85#Streamer vorhanden?
 86if [ "$(ls /dev | grep $dev_streamer)" = "" ]; then
 87    echo "ERROR: Streamer device not found" | tee -a /var/log/backup/tape/$2/$logprefix.log
 88    echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
 89    exit 1
 90fi
 91
 92#Ist das Geraet belegt?
 93echo -n "Checking whether the device is currently in use..." | tee -a /var/log/backup/tape/$2/$logprefix.log
 94if [ "$(mt -f /dev/$dev_streamer status | grep busy)" = "" ]; then
 95        #Nein
 96        echo "NO" | tee -a /var/log/backup/tape/$2/$logprefix.log
 97else
 98        #Ja
 99        echo "YES" | tee -a /var/log/backup/tape/$2/$logprefix.log
100    echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
101        exit 1
102
103fi
104
105#Ist ein Band eingelegt?
106echo -n "Checking whether a tape is inserted..." | tee -a /var/log/backup/tape/$2/$logprefix.log
107if [ "$(mt -f /dev/$dev_streamer status | grep DR_OPEN)" = "" ]; then
108    #Ja
109    echo "YES" | tee -a /var/log/backup/tape/$2/$logprefix.log
110else
111    #Nein
112    echo "NO" | tee -a /var/log/backup/tape/$2/$logprefix.log
113    echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
114    exit 1
115fi
116
117#Spiele Band zurueck
118echo "Rewinding tape..." | tee -a /var/log/backup/tape/$2/$logprefix.log
119mt -f /dev/$dev_streamer rewind | tee -a /var/log/backup/tape/$2/$logprefix.log
120
121#Gebe Dateien aus
122echo "The FOLLOWING files will be backupped:" | tee -a /var/log/backup/tape/$2/$logprefix.log
123echo "" | tee -a /var/log/backup/tape/$2/$logprefix.log
124du -h "$backups_path/$2/$sel_flag/" --exclude-from="$backups_path/$exclude_file_prefix$2" | tee -a /var/log/backup/tape/$2/$logprefix.log
125
126#Sichere Daten
127echo "About to backup files..." | tee -a /var/log/backup/tape/$2/$logprefix.log
128tar cvzf "/dev/$dev_streamer" "$backups_path/$2/$sel_flag/" --exclude-from="$backups_path/$exclude_file_prefix$2" | tee -a /var/log/backup/tape/$2/$logprefix.log

Eine Sicherung des Ziels "hostA" auf das Bandlaufwerk "/dev/st0" erfolgt beispielsweise wie folgt:

1# ./backup.sh st0 hostA

Für jedes Sicherungsziel habe ich noch ein dediziertes Wochen- und Monatsskript, welches mithilfe von mtx das entsprechende Band gleich in den Bandroboter einlegt und das o.g. Backup-Skript mit den notwendigen Paramtern startet.

 1#!/bin/sh
 2TAPE_DEV="/dev/sg8"
 3TAPE1="7"
 4TAPE2="8"
 5
 6mtx -f $TAPE_DEV load $TAPE1
 7./backup.sh st0 hostA
 8mtx -f $TAPE_DEV unload $TAPE1
 9mtx -f $TAPE_DEV load $TAPE2
10./backup.sh st0 hostA
11mtx -f $TAPE_DEV unload $TAPE2

Für die Sicherung meines Webservers habe ich ein Skript geschrieben, welches den FTP-Server mit curlftpfs mountet und die Dateien mithilfe von rsync kopiert:

 1#!/bin/bash
 2
 3##########################################
 4#                                        #
 5#    Webspace-Spiegelung mittels RSync   #
 6#    ---------------------------------   #
 7#                                        #
 8#    2011 By Christian Stankowic         #
 9#    info@christian-stankowic.de         #
10#                                        #
11##########################################
12
13#Variablendeklaration
14path_curlftpfs="/usr/bin/curlftpfs"
15path_rsync="/usr/bin/rsync"
16path_tee="/usr/bin/tee"
17
18ftp_server="..."
19ftp_mount="/mnt/ftp"
20ftp_user="..."
21ftp_pass="..."
22
23log_path="/var/log/backup/ftp"
24copy_path="/mnt/storage/data/Backups/web/latest"
25
26#Datumprefix und Logfile erstellen
27logprefix="$(date +"%d_%m_%Y_%H_%M")"
28echo "log file from $(date)" >> $log_path/$logprefix.log
29echo "parameters were:   $1 $2 $3 $4" >> $log_path/$logprefix.log
30
31#FTP mounten
32curlftpfs $ftp_server $ftp_mount -o user=$ftp_user:$ftp_pass
33
34#Spiegel gemountet?
35echo "Checking if ftp is mounted..." | $path_tee -a $log_path/$logprefix.log
36if [ "$(mount | grep $ftp_mount)" = "" ]; then
37    echo "Error: Mirror ($ftp_mount) NOT mounted" | $path_tee -a $log_path/$logprefix.log
38    exit 1
39else
40    echo "Mirror ($ftp_mount) mounted" | $path_tee -a $log_path/$logprefix.log
41fi
42
43#Spiegelung
44$path_rsync -a -r --delete -v $ftp_mount $copy_path | $path_tee -a $log_path/$logprefix.log
45
46#FTP unmounten
47umount $ftp_mount

Die Spiegelung der NAS-Daten auf das DAS erfolgt mit einem einfachen rsync-Skript:

 1#!/bin/bash
 2
 3######################################
 4#                                    #
 5#    !!! SPIEGEL AUF DATATALE !!!    #
 6#                                    #
 7######################################
 8
 9#Variablendeklaration
10backups_path="/mnt/storage/data/Backups"
11
12#Datumprefix und Logfile erstellen
13logprefix="$(date +"%d_%m_%Y_%H_%M")"
14echo "log file from $(date)" >> /var/log/backup/mirror/$logprefix.log
15echo "parameters were:   $1 $2 $3 $4" >> /var/log/backup/mirror/$logprefix.log
16
17#Spiegel gemountet?
18echo "Checking if mirror is mounted..." | tee -a /var/log/backup/mirror/$logprefix.log
19if [ "$(mount | grep /mnt/mirror)" = "" ]; then
20    echo "Error: Mirror (/mnt/mirror) NOT mounted" | tee -a /var/log/backup/mirror/$logprefix.log
21    exit 1
22else
23    echo "Mirror (/mnt/mirror) mounted" | tee -a /var/log/backup/mirror/$logprefix.log
24fi
25
26#Spiegelung
27rsync -a -r --exclude-from "/opt/bak/exclude_rsync" --delete -v /mnt/storage/data/ /mnt/mirror/data/ | tee -a /var/log/backup/mirror/$logprefix.log

Alle Skripte legen übrigens Logdateien unterhalb von /var/log/backup an - so kann ich nachvollziehen, ob die automatisierten Backups fehlerfrei durchlaufen sind:

 1# cd /var/log/backup/tape/hostA
 2# 29_01_2012_20_42.log
 3log file from So 29. Jan 20:42:48 CET 2012
 4parameters were:   st0 hostA
 5Backup exists
 6Backup size is 1226994 kbytes - that will fit.
 7Checking whether the device is currently in use...NO
 8Checking whether a tape is inserted...YES
 9Rewinding tape...
10The FOLLOWING files will be backupped:
11
1224K     ...
13...

Zeitliche Planung

Sicherungen sind nur dann sinnvoll, wenn man sie auch konsequent und regelmäßig durchführt.

Meine Planung sieht derzeit wie folgt aus:

  • Tägliche automatisierte Generierung von Sicherungsdaten auf bestimmten Hosts - i.d.R wichtige Server-Systeme
  • Wöchentliche händische Synchronisation der Notebook-Daten auf das NAS
  • Wöchentliche händische Sicherung des Webservers inklusive Datenbanken mithilfe von MySQLDumper und eines FTP-Skripts
  • Wöchentliche skriptgesteuerte doppelte Sicherung auf Band und Synchronisation mit DataTale

Bänder, Bänder, Bänder,...

Die Sicherung auf Band erfolgt in der Regel immer doppelt. Das hat zur Folge, dass ich von jedem Backup zwei Bänder hab - ein Band landet im Schrank, das andere bewahre ich an einem anderen Ort (außerhalb meiner Wohnung) auf.

Ich habe für jedes "Sicherungsziel" habe ich dedizierte Bänder für wöchentliche, monatliche und jährliche Backups. Auf dem Jahresband landet die Jahressicherung, während das Monatsband jeden Monat mit dem aktuellen Datenbestand überschrieben wird. Ebenso ist es mit dem Wochenband, was jede Woche überschrieben wird. Die Sicherungen sind übrigens Full-Backups - ich praktiziere keine inkrementellen Backups auf Band. Der wöchentliche Backup-Vorgang nimmt 2 bis 4 Stunden Zeit in Anspruch.

Das Ganze mag jetzt ein wenig übertrieben klingen - ich sichere allerdings auch geschäftliche Daten, die ich 10 Jahre vorhalten muss. Und wenn ich ohnehin schon profesionell Backups anfertige, können davon meine privaten Daten auch profitieren, oder? 🙂

Bänder, Bänder, Bänder,...

Videos

Einen Überblick über den DDS-Bandroboter und dessen Funktionen gibt es im ersten Clip:

Wer schon immer mal wissen wollte, wie ein Bandroboter arbeitet, kann sich das Ganze hier mal anschauen:

Mein DAS habe ich vor einiger Zeit mit neuen Festplatten versorgt - zu sehen ist das im letzten Clip: