Cassandra NetWorker

titelbild-cassandra-networker

EMC NetWorker ist eine häufig verwendete Backuplösung, welche von verschiedenen Unternehmen eingesetzt wird, um ihre Backup- und Recovery-Strategien umzusetzen. Die Software unterstützt durch seine eigenen Module für Datenbanken und Anwendungen (NMDA) die automatisierte Sicherung und Wiederherstellung einer Vielzahl von Softwaresystemen. Hierzu gehören Datenbankensysteme wie Oracle oder MySQL. Bei Software- und Datenbanksystemen, welche nicht unterstützt werden, muss auf individuell für die Zielsysteme angepasste Filesystem-Sicherungen zurückgegriffen werden. Ein Beispiel hierfür ist die Sicherung der Daten eines Apache Cassandra Clusters.

Apache Cassandra ist ein NoSQL-Datenbanksystem, welches sich unter anderem durch seinen Fokus auf Skalierbarkeit und Hochverfügbarkeit positioniert. Bei einem hochverfügbaren System wie diesem beeinflussen selbst Ausfälle von einzelnen Knoten innerhalb eines Clusters nicht die Bereitstellung der Daten. Trotz Hochverfügbarkeit der Daten im Cluster muss z.B. zur Absicherung gegen logische Fehler aber trotzdem eine traditionelle Sicherung der Daten vorgenommen werden.

Daten innerhalb von Apache Cassandra werden in einem bestimmten System zusammengefasst. Das äußerste Element hierbei ist ein Keyspace. Dies ist vergleichbar mit einer Database aus einem relationalen Datenbanksystem, welches als äußeres Konstrukt zum Speichern der Daten dient. Innerhalb eines Keyspaces werden Tables angelegt, welche als Tabellen zu verstehen sind. Die Daten, welche hier hinzugefügt oder verändert werden, durchlaufen beim Speichern mehrere Stadien. Besonders relevant zur Sicherung sind hierbei die unveränderlichen SSTable-Dateien. In dieser Form werden die Daten einer Tabelle letztendlich auf dem Festplattenspeicher geschrieben.

Apache Cassandra bietet von sich aus sehr grundlegende Funktionalitäten, um eine konsistente Sicherung herzustellen. Dabei werden auf einem Knoten per Kommandozeile lokal Hardlinks von spezifizierten SSTable-Dateien erstellt. Weitere Tätigkeiten, wie die Verwaltung der Sicherungen und deren Verschiebung außerhalb des Clusters, bleiben jedoch in den Händen des Administrators. In diesem Blogartikel wird beschrieben, inwiefern die von EMC NetWorker bereitgestellten Funktionen genutzt werden können, um die SSTable-Dateien zu sichern und wiederherzustellen.

Grundlage: Sichern mit Apache Cassandra

Apache Cassandra bietet zwei Möglichkeiten an, um Sicherungen der SSTable-Dateien anzulegen: ‚Snapshots' und ‚Incremental Backups'. Für eine Sicherung mit NetWorker konzentrieren wir uns auf Snapshots, da diese einen konsistenten Zustand einer Tabelle zu einem Zeitpunkt erzeugen.

Um verstehen zu können, wie das funktioniert, muss erklärt werden, wie und wo die SSTable-Dateien auf einer Node abgespeichert sind.

Hierzu wird innerhalb der cassandra.yaml, der Konfigurationsdatei von Cassandra, ein Data Directory definiert. Standardmäßig wird das Data Directory unter $CASSANDRA_HOME/data/data angelegt. Innerhalb dieses Verzeichnisses besteht eine Verzeichnisstruktur, welche sich wie folgt zusammensetzt:

keyspace-name/table-name/

Innerhalb des Ordners einer spezifischen Tabelle befinden sich die zugehörigen SSTable-Dateien, in denen die Dateninhalte der Tabellen abgelegt werden. Diese bilden das Ziel unseres Backups.

Durch einen Snapshot werden Hardlinks im Linux-Filesystem auf alle bestehenden SSTable-Dateien einer ausgewählten Tabelle erzeugt. Diese werden dann in einem separaten Unterordner abgelegt. Grundlegend wird ein Snapshot mit dem Befehl ‚nodetool snapshot' durchgeführt. Alle Snapshots einer spezifischen Table werden in dem Unterverzeichnis

keyspace-name/table-name/snapshots/

abgelegt. Hier wird für jeden Snapshot ein weiteres Unterverzeichnis mit dem definierten Namen des Snapshots erstellt. Ist kein Name angegeben, wird standardmäßig ein UNIX-Zeitstempel zum Zeitpunkt des jeweiligen Snapshots verwendet.

Zusätzlich zu den Hardlinks der SSTable-Dateien befindet sich im Verzeichnis eine Datei namens ‚schema.cql'. Mit dieser kann das Schema der Table zum Zeitpunkt des Snapshots wiederhergestellt werden.

Um die Daten des Snapshots physikalisch von den Daten im Cluster zu trennen, ist eine Sicherung der Snapshots mit einer Backup-Software wie NetWorker denkbar. Ein Problem stellt jedoch die Auswahl der zu sichernden Dateien dar. Ein Backup muss neu hinzugefügte Keyspaces und Tables berücksichtigen, jedoch nur die SSTable-Dateien eines Snapshots sichern. Dies lässt sich mittels einer Vorauswahl über Skripte ermöglichen.

Aufbau: Angepasste Backup-Durchläufe für NetWorker mit Skripten

EMC NetWorker unterstützt die Verwendung von Skripten, welche automatisiert vor, während oder nach einem Backup ausgeführt werden. Mithilfe dieser Skripte ist es möglich, auf Basis von Cassandra-Snapshots konsistente Backups der Snapshots von spezifischen Tables oder des gesamten Keyspaces im NetWorker zu erstellen.

Hierfür lassen sich drei individuelle Skripte erstellen: Ein Pre-command Skript, ein Backup Skript, und ein Post-command Skript. Diese Skripte müssen sich jeweils auf dem zu sichernden Node befinden und im NetWorker für den jeweiligen Client ausgewählt werden, damit sie bei einer Sicherung verwendet werden.

Pre-command Skript

#!/bin/bash
snapname=Snapshot
keyspacename=ami_test01
nsr_logfile=/nsr/logs/cassandra_pre.log

date >> "$nsr_logfile"
echo "Attempting to run pre-backup script for Apache Cassandra" >> "$nsr_logfile"

#Erstellung eines Snapshots
/opt/cassandra/apache-cassandra-3.11.4/bin/nodetool -u cassandra -pw cassandra snapshot -t $snapname $keyspacename
ret_createsnapshot_command=$?
echo "Generating snapshot "$snapname" for Keyspace "$keyspacename": "$ret_createsnapshot_command >> "$nsr_logfile"

#Status des Pre-Script
if [ $ret_createsnapshot_command != 0 ]
        then
                echo "Error" >> "$nsr_logfile"
                echo "Cancelling backup" >> "$nsr_logfile"
                exit 1
        else
                echo "Success" >> "$nsr_logfile"
fi
 

Mit diesem Pre-Skript wird vor der Durchführung des Backups auf dem ausgewählten Node ein Snapshot eines spezifizierten Keyspace erstellt. Dem Snapshot wird ein spezifischer Name – hier ‚Snapshot' – gegeben, damit dieser im nachfolgenden Backup-Skript ermittelt und verwendet werden kann. Dieser Name ist case-sensitive und darf nicht identisch mit anderen, bestehenden Snapshots oder Verzeichnisnamen innerhalb der Data Directory sein.

Zusätzlich wird überprüft, ob bei der Erstellung des Snapshots Fehler auftraten. Dies kommt z.B. vor, wenn ein Snapshot mit einem identischen Namen bereits existiert. Ist dies der Fall, wird der Backup-Prozess abgebrochen, damit kein fehlerhafter oder potenziell veralteter Snapshot gesichert wird.

Backup Skript

#!/bin/bash
nsr_pool=otc-data
datadir=/opt/cassandra/data/data/
nsr_logfile=/nsr/logs/cassandra_save.log
filelist=/nsr/logs/savefilelist.txt
snapname=Snapshot
NSR_CLIENT=`hostname`
CASSANDRA_ID=Testumgebung

date >> "$nsr_logfile"
echo "Attempting to backup the files of the created Snapshot "$snapname >> "$nsr_logfile"

# Erstellung der Dateiliste
/usr/bin/find $datadir -path "*"\/$snapname\/"*" -print > $filelist

# Dateiliste wird als Input für den save-Befehl verwendet
/usr/sbin/save -b $nsr_pool -I $filelist -N "CASSANDRA:"$NSR_CLIENT":"$CASSANDRA_ID
ret_save_command=$?
echo "Execute save command: "$ret_save_command >> "$nsr_logfile"

# Dateiliste wird nach Verwendung wieder entfernt
rm $filelist
ret_filelist_delete=$?
echo "Remove filelist: "$ret_filelist_delete >> "$nsr_logfile"

if [ $ret_save_command != 0 ] || [ $ret_filelist_delete != 0 ]
        then
                echo "Error" >> "$nsr_logfile"
                exit 1
        else
                echo "Success" >> "$nsr_logfile"
fi
 

Durch das Backup-Skript wird der Ablauf und Inhalt der NetWorker-Sicherung auf dem Node gesteuert. Vor der eigentlichen Sicherung wird eine Dateiliste erstellt, die sämtliche Dateien beinhaltet, welche sich in dem Verzeichnis des zuvor erstellten Snapshots befinden und gesichert werden sollen. Hierbei wird der Snapshot-Name als identifizierende Eigenschaft verwendet. Daher ist die Verwendung eines eindeutigen Namens wichtig, damit keine irrelevanten Verzeichnisse zusätzlich gesichert werden.

Nur die Dateien innerhalb dieser Liste werden anschließend bei der Sicherung berücksichtigt. Nach der Sicherung wird diese Dateiliste wieder vom Zielsystem entfernt.

Post-command Skript

#!/bin/bash
snapname=Snapshot
keyspacename=ami_test01
nsr_logfile=/nsr/logs/cassandra_post.log

date >> "$nsr_logfile"
echo "Attempting to run post-backup script for Apache Cassandra" >> "$nsr_logfile"

# Löschen der generierten Snapshots
/opt/cassandra/apache-cassandra-3.11.4/bin/nodetool -u cassandra -pw cassandra clearsnapshot -t $snapname $keyspacename
ret_clearsnapshot_command=$?
echo "Removing snapshot "$snapname" for Keyspace "$keyspacename": "$ret_clearsnapshot_command >> "$nsr_logfile"

#Status des Post-Script
if [ $ret_clearsnapshot_command != 0 ]
        then
                echo "Error" >> "$nsr_logfile"
                echo "Cancelling Backup" >> "$nsr_logfile"
                exit 1
        else
                echo "Success" >> "$nsr_logfile"
fi 

Das Post-Skript dient dazu, nach der NetWorker-Sicherung den für das Backup erstellten Snapshot wieder zu entfernen. Wird dies nicht durchgeführt, kommt es bei der nächsten Sicherung zu Problemen, wenn die Dateien des Snapshots nicht manuell entfernt werden.

Während mit diesen Skripten der konsistente Zustand eines Nodes gesichert werden kann, wird für eine konsistente Sicherung der gesamten Daten eines Clusters eine solche Sicherung für jede Instanz des Clusters benötigt. Werden mithilfe von diesen Skripten – je nach Replikationsfaktor und weiteren Konfigurationen – mehrere oder alle Nodes eines Clusters gesichert, lässt sich hierdurch ein konsistentes Backup der ausgewählten Daten zu einem Zeitpunkt innerhalb des Clusters erstellen.

Restore der Daten via Skript

Wo gesichert wird, muss auch wiederhergestellt werden. Grundsätzlich besteht bei Apache Cassandra die Möglichkeit, den ‚sstableloader' zu verwenden, um die Inhalte von externen Dateien in die SSTable-Dateien eines Clusters einzuführen. Damit dies erfolgreich durchgeführt wird, müssen sich die externen Dateien jedoch in einer bestimmten Verzeichnisstruktur ähnlich wie die der Verzeichnisstruktur des Data Directory befinden. Der ‚sstableloader' bezieht sich auf die beiden überliegenden Verzeichnisnamen, um den Keyspace und die Table, in denen die Daten eingefügt werden sollen, zu ermitteln.

#!/bin/bash
datadir=/home/ami/recoverscripttest
savesetid=$1
logfile=/tmp/cas_recover.log

date >> $logfile
#Wiederherstellung des Snapshots mittels savesetID
echo "Restoring saveset $savesetid in directory $datadir" >> $logfile
/bin/recover -S $savesetid -d $datadir -I '/opt/cassandra/data/data/'
rec_ret=$?

#Test ob Wiederherstellung ohne Fehler geschehen ist
if [ $rec_ret != 0 ]
        then
                echo "Error during saveset restore" >> $logfile
                echo "Cancelling further restore operations" >> $logfile
                exit 1
        else
                echo "Restore successful" >> $logfile
fi

#Verschieben der Dateien als Vorbereitung fuer sstableloader
for i in `find $datadir -name schema.cql -exec dirname {} \;`
        do
                mv $i/*.* $i/../../.
                ret=$?
                echo "Moving files from "$i/*.*" to "$i/../../." ended with code "$ret >> $logfile
        done

#Wiederherstellung der Daten aus sstable-Dateien mittels sstableloader
for i in `find $datadir -name schema.cql -exec dirname {} \;`
        do
                echo "Restoring sstable-files in $i with sstableloader" >> $logfile
                /opt/cassandra/apache-cassandra-3.11.4/bin/sstableloader -u cassandra -pw cassandra --nodes 192.168.130.28,192.168.130.196,192.168.130.197 $i >> $logfile
        done

echo "Restoring with sstableloader completed" >> $logfile

#Entfernen der nicht mehr noetigen Snapshot-Dateien 
echo "Removing restored directory under $datadir" >> $logfile
rm -r $datadir
rm_ret=$?
echo "Removing files ended with code $rm_ret" >> $logfile
 

Durch dieses Skript lassen sich die Daten einer Sicherung wieder in das Cassandra Cluster einfügen. Die Auswahl der wiederherzustellenden Sicherung findet über die Saveset-ID der jeweiligen NetWorker-Sicherung statt. Mithilfe des durch NetWorker bereitgestellten ‚recover'-Befehls werden die Daten in einem spezifizierten Verzeichnis wiederhergestellt. Hierbei wird auch die überliegende Verzeichnisstruktur rekonstruiert. Durch das Skript werden die SSTable-Dateien in jene Verzeichnisse verschoben, welche die Wiederherstellung durch den sstableloader in die korrekten Keyspaces und Tables ermöglicht. Anschließend werden mittels des sstableloader-Befehls die Daten wieder in das Cassandra Cluster eingeführt. Die Dateien der Sicherung werden anschließend wieder entfernt, da sie nicht mehr benötigt werden, sobald die Daten in das Cluster eingeführt wurden.

Fazit

Mit der Verwendung der Backup-Skripte lassen sich mit NetWorker konsistente Backups eines Cassandra Clusters erstellen. Damit muss für Cassandra-Datenbanken keine eigene Lösung entwickelt werden, um die Daten zu sichern und wiederherzustellen. Ein möglicher Nachteil bilden potenzielle Probleme, wenn beispielsweise Snapshots manuell erstellt werden, welche den Namen des automatisch generierten Snapshots teilen. Ein weiterer Nachteil ist, dass das hier dargestellte Restore-Skript nur eine einzelne Sicherung vollständig wieder in das Cluster einführt. Um einen Stand eines Clusters wieder einzuführen, muss je nach Konfiguration für jede gesicherte Instanz das Skript einmal ausgeführt werden. Für den Fall, dass nur individuelle Keyspaces oder Tabellen wiederhergestellt werden sollen, muss zudem manuell agiert werden, da dieses Restore-Skript alle SSTable-Dateien wiederherstellt.

By accepting you will be accessing a service provided by a third-party external to https://blog.ordix.de/