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

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

Ü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:

#!/bin/bash

###########################################
#                                         #
#    !!! AUTOMATISIERTE  SICHERUNG !!!    #
#                                         #
###########################################

#Variablendeklaration
backups_path="/mnt/storage/data/Backups"
exclude_file_prefix="blacklist_"
max_size_gb=200
dev_streamer="$1"

#Datumprefix und Logfile erstellen
logprefix="$(date +"%d_%m_%Y_%H_%M")"
if [ -d "/var/log/backup/tape/$2" ]; then
    #Ordner vorhanden
    echo "Log directory for this target (/var/log/backup/tape/$2) exists."
else
    #Ordner nicht vorhanden
    mkdir -p /var/log/backup/tape/$2
    echo "Log directory for this target (/var/log/backup/tape/$2) didn't exist -  I created it for you. :)"
fi
echo "log file from $(date)" >> /var/log/backup/tape/$2/$logprefix.log
echo "parameters were:   $1 $2 $3 $4" >> /var/log/backup/tape/$2/$logprefix.log

#Wurde ein Streamer angegeben?
if [ "$1" = "" ]; then
        #Nein
    echo "ERROR: You must specify a streamer device (e.g. nst0)!" | tee -a /var/log/backup/tape/$2/$logprefix.log
    exit 1
fi

#Wurde ein Ziel angegeben?
if [ "$2" = "" ]; then
    #Nein
    echo "ERROR: You must specify a target (e.g. host)!" | tee -a /var/log/backup/tape/$2/$logprefix.log
    echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
    exit 1
fi

#Flag setzen
if [ "$3" = "--from" ]; then
    #Ein vorheriges Backup wurde angefordert --> wurde ein Datum angegeben?
    if [ "$4" = "" ]; then
        #Nein
        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
        echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
        exit 1
    else
        sel_flag="$4"
    fi

else
    #Setze Flag
    sel_flag="latest"
fi

#Ordner fuer Backup vorhanden?
if [ -d "$backups_path/$2/$sel_flag" ]; then
        #Ja
        echo "Backup exists" | tee -a /var/log/backup/tape/$2/$logprefix.log
else
    #Nein
           echo "ERROR: There is no backup #$sel_flag for that target!" | tee -a /var/log/backup/tape/$2/$logprefix.log
           echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
        exit 1
fi

#Ueberpruefe ob das Backup auf das Tape passt
backup_size="$(du -cs $backups_path/$2/$sel_flag --exclude-from=$backups_path/$exclude_file_prefix$2 | grep insgesamt | cut -f1)"
echo -n "Backup size is $backup_size kbytes" | tee -a /var/log/backup/tape/$2/$logprefix.log

if [ "$backup_size" -gt "$(($max_size_gb*1024*1024))" ]; then
    #Nein
    echo ", more than $max_size_gb gbytes - that won't fit!" | tee -a /var/log/backup/tape/$2/$logprefix.log
       echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
       exit 1
else
    #Ja
    echo " - that will fit." | tee -a /var/log/backup/tape/$2/$logprefix.log
fi

#Streamer vorhanden?
if [ "$(ls /dev | grep $dev_streamer)" = "" ]; then
    echo "ERROR: Streamer device not found" | tee -a /var/log/backup/tape/$2/$logprefix.log
    echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
    exit 1
fi

#Ist das Geraet belegt?
echo -n "Checking whether the device is currently in use..." | tee -a /var/log/backup/tape/$2/$logprefix.log
if [ "$(mt -f /dev/$dev_streamer status | grep busy)" = "" ]; then
        #Nein
        echo "NO" | tee -a /var/log/backup/tape/$2/$logprefix.log
else
        #Ja
        echo "YES" | tee -a /var/log/backup/tape/$2/$logprefix.log
    echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
        exit 1

fi

#Ist ein Band eingelegt?
echo -n "Checking whether a tape is inserted..." | tee -a /var/log/backup/tape/$2/$logprefix.log
if [ "$(mt -f /dev/$dev_streamer status | grep DR_OPEN)" = "" ]; then
    #Ja
    echo "YES" | tee -a /var/log/backup/tape/$2/$logprefix.log
else
    #Nein
    echo "NO" | tee -a /var/log/backup/tape/$2/$logprefix.log
    echo "Aborting..." | tee -a /var/log/backup/tape/$2/$logprefix.log
    exit 1
fi

#Spiele Band zurueck
echo "Rewinding tape..." | tee -a /var/log/backup/tape/$2/$logprefix.log
mt -f /dev/$dev_streamer rewind | tee -a /var/log/backup/tape/$2/$logprefix.log

#Gebe Dateien aus
echo "The FOLLOWING files will be backupped:" | tee -a /var/log/backup/tape/$2/$logprefix.log
echo "" | tee -a /var/log/backup/tape/$2/$logprefix.log
du -h "$backups_path/$2/$sel_flag/" --exclude-from="$backups_path/$exclude_file_prefix$2" | tee -a /var/log/backup/tape/$2/$logprefix.log

#Sichere Daten
echo "About to backup files..." | tee -a /var/log/backup/tape/$2/$logprefix.log
tar 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:

./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.

#!/bin/sh
TAPE_DEV="/dev/sg8"
TAPE1="7"
TAPE2="8"

mtx -f $TAPE_DEV load $TAPE1
./backup.sh st0 hostA
mtx -f $TAPE_DEV unload $TAPE1
mtx -f $TAPE_DEV load $TAPE2
./backup.sh st0 hostA
mtx -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.

#!/bin/bash

##########################################
#                                        #
#    Webspace-Spiegelung mittels RSync   #
#    ---------------------------------   #
#                                        #
#    2011 By Christian Stankowic         #
#    info@christian-stankowic.de         #
#                                        #
##########################################

#Variablendeklaration
path_curlftpfs="/usr/bin/curlftpfs"
path_rsync="/usr/bin/rsync"
path_tee="/usr/bin/tee"

ftp_server="..."
ftp_mount="/mnt/ftp"
ftp_user="..."
ftp_pass="..."

log_path="/var/log/backup/ftp"
copy_path="/mnt/storage/data/Backups/web/latest"

#Datumprefix und Logfile erstellen
logprefix="$(date +"%d_%m_%Y_%H_%M")"
echo "log file from $(date)" >> $log_path/$logprefix.log
echo "parameters were:   $1 $2 $3 $4" >> $log_path/$logprefix.log

#FTP mounten
curlftpfs $ftp_server $ftp_mount -o user=$ftp_user:$ftp_pass

#Spiegel gemountet?
echo "Checking if ftp is mounted..." | $path_tee -a $log_path/$logprefix.log
if [ "$(mount | grep $ftp_mount)" = "" ]; then
    echo "Error: Mirror ($ftp_mount) NOT mounted" | $path_tee -a $log_path/$logprefix.log
    exit 1
else
    echo "Mirror ($ftp_mount) mounted" | $path_tee -a $log_path/$logprefix.log
fi

#Spiegelung
$path_rsync -a -r --delete -v $ftp_mount $copy_path | $path_tee -a $log_path/$logprefix.log

#FTP unmounten
umount $ftp_mount

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

#!/bin/bash

######################################
#                                    #
#    !!! SPIEGEL AUF DATATALE !!!    #
#                                    #
######################################

#Variablendeklaration
backups_path="/mnt/storage/data/Backups"

#Datumprefix und Logfile erstellen
logprefix="$(date +"%d_%m_%Y_%H_%M")"
echo "log file from $(date)" >> /var/log/backup/mirror/$logprefix.log
echo "parameters were:   $1 $2 $3 $4" >> /var/log/backup/mirror/$logprefix.log

#Spiegel gemountet?
echo "Checking if mirror is mounted..." | tee -a /var/log/backup/mirror/$logprefix.log
if [ "$(mount | grep /mnt/mirror)" = "" ]; then
    echo "Error: Mirror (/mnt/mirror) NOT mounted" | tee -a /var/log/backup/mirror/$logprefix.log
    exit 1
else
    echo "Mirror (/mnt/mirror) mounted" | tee -a /var/log/backup/mirror/$logprefix.log
fi

#Spiegelung
rsync -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.

# cd /var/log/backup/tape/hostA
# 29_01_2012_20_42.log
log file from So 29. Jan 20:42:48 CET 2012
parameters were:   st0 hostA
Backup exists
Backup size is 1226994 kbytes - that will fit.
Checking whether the device is currently in use...NO
Checking whether a tape is inserted...YES
Rewinding tape...
The FOLLOWING files will be backupped:

24K     ...
...

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,...

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:

Schreibe einen Kommentar