Hochverfügbarkeit ist eine der Hauptanforderungen von ernsthaften Geschäftsanwendungen und hochverfügbarer Speicher ist eine Schlüsselkomponente in solchen Umgebungen. Highly Available STorage (HAST) ist ein Framework in FreeBSD, welches die transparente Speicherung der gleichen Daten über mehrere physikalisch getrennte Maschinen ermöglicht, die über ein TCP/IP-Netzwerk verbunden sind. HAST kann als ein netzbasiertes RAID1 (Spiegel) verstanden werden und ist dem DRBD®-Speichersystem der GNU/Linux®-Plattform ähnlich. In Kombination mit anderen Hochverfügbarkeitseigenschaften von FreeBSD wie CARP, ermöglicht es HAST, hochverfügbare Speichercluster zu bauen, die in der Lage sind, Hardwareausfällen zu widerstehen.
Die Hauptmerkmale von HAST sind:
Es kann zur Maskierung von I/O-Fehlern auf lokalen Festplatten eingesetzt werden.
Dateisystem-unabhängig, was es erlaubt, jedes von FreeBSD unterstützte Dateisystem zu verwenden.
Effiziente und schnelle Resynchronisation: es werden nur die Blöcke synchronisiert, die während der Ausfallzeit eines Knotens geändert wurden.
Es kann in einer bereits bestehenden Umgebung eingesetzt werden, um zusätzliche Redundanz zu erreichen.
Zusammen mit CARP, Heartbeat, oder anderen Werkzeugen, ist es möglich, ein robustes und dauerhaftes Speichersystem zu bauen.
Nachdem Sie diesen Abschnitt gelesen haben, werden Sie folgendes wissen:
Was HAST ist, wie es funktioniert und welche Eigenschaften es besitzt.
Wie man HAST unter FreeBSD aufsetzt und verwendet.
Wie man CARP und devd(8) kombiniert, um ein robustes Speichersystem zu bauen.
Bevor Sie diesen Abschnitt lesen, sollten Sie:
die Grundlagen von UNIX® und FreeBSD verstanden haben (Kapitel 3, Grundlagen des FreeBSD Betriebssystems).
wissen, wie man Netzwerkschnittstellen und andere Kernsysteme von FreeBSD konfiguriert (Kapitel 11, Konfiguration und Tuning).
ein gutes Verständnis der FreeBSD-Netzwerkfunktionalität besitzen (Teil IV, „Netzwerke“).
Das HAST-Projekt wurde von der FreeBSD Foundation mit Unterstützung der OMCnet Internet Service GmbH und TransIP BV gesponsert.
HAST bietet eine synchrone Replikation
auf Blockebene zwischen zwei Maschinen: einem
primary
, auch bekannt als
master
Knoten, sowie dem
secondary
, oder slave
Knoten. Diese beiden Maschinen zusammen werden als Cluster
bezeichnet.
Da HAST in einer primär-sekundär-Konfiguration funktioniert, ist immer nur ein Knoten des Clusters zu jeder Zeit aktiv. Der primäre Knoten, auch active genannt, ist derjenige, der alle I/O-Anfragen verarbeitet, die an die HAST-Schnittstelle gesendet werden. Der sekundäre Knoten wird automatisch vom primären Knoten aus synchronisiert.
Die physischen Komponenten des HAST-Systems sind die lokale Platte am Primärknoten und die entfernte Platte am Sekundärknoten.
HAST arbeitet synchron auf Blockebene,
was es für Dateisysteme und Anwendungen transparent macht.
HAST stellt gewöhnliche
GEOM-Provider in
/dev/hast/
für die Verwendung durch
andere Werkzeuge oder Anwendungen zur Verfügung. Es gibt
keinen Unterschied zwischen dem Einsatz von
HAST bereitgestellten Geräten und
herkömmlichen Platten oder Partitionen.
Jede Schreib-, Lösch- oder Entleerungsoperation wird an die lokale und über TCP/IP zu der entfernt liegenden Platte gesendet. Jede Leseoperation wird von der lokalen Platte durchgeführt, es sei denn, die lokale Platte ist nicht aktuell oder es tritt ein I/O-Fehler auf. In solchen Fällen wird die Leseoperation an den Sekundärknoten geschickt.
HAST versucht, eine schnelle Fehlerbereinigung zu gewährleisten. Aus diesem Grund ist es wichtig, die Synchronisationszeit nach dem Ausfall eines Knotens zu reduzieren. Um eine schnelle Synchronisation zu ermöglichen, verwaltet HAST eine Bitmap von unsauberen Bereichen auf der Platte und synchronisiert nur diese während einer regulären Synchronisation (mit Ausnahme der initialen Synchronisation).
Es gibt viele Wege, diese Synchronisation zu behandeln. HAST implementiert mehrere Replikationsarten, um unterschiedliche Methoden der Synchronisation zu realisieren:
memsync: Dieser Modus meldet Schreiboperationen als vollständig, wenn die lokale Schreiboperation beendet ist und der entfernt liegende Knoten die Ankunft der Daten bestätigt hat, jedoch bevor die Daten wirklich gespeichert wurden. Die Daten werden auf dem entfernt liegenden Knoten direkt nach dem Senden der Bestätigung gespeichert. Dieser Modus ist dafür gedacht, Latenzen zu verringern und zusätzlich eine gute Verlässlichkeit zu bieten. In der Voreinstellung wird dieser Modus benutzt.
fullsync: Dieser Modus meldet Schreiboperationen als vollständig, wenn sowohl die lokale, als auch die entfernte Schreiboperation abgeschlossen wurde. Dies ist der sicherste und zugleich der langsamste Replikationsmodus.
async: Dieser Modus meldet Schreiboperationen als vollständig, wenn lokale Schreibvorgänge abgeschlossen wurden. Dies ist der schnellste und gefährlichste Replikationsmodus. Er sollte nur verwendet werden, wenn die Latenz zu einem entfernten Knoten bei einer Replikation zu hoch ist für andere Modi.
Das HAST-Framework besteht aus mehreren Komponenten:
Dem hastd(8)-Daemon, welcher für
Datensynchronisation verantwortlich ist. Wenn dieser
Daemon gestartet wird, wird automatisch
geom_gate.ko
geladen.
Dem hastctl(8) Management-Werkzeug.
Der Konfigurationsdatei hast.conf(5). Diese Datei muss vorhanden sein, bevor hastd gestartet wird.
Alternativ lässt sich die
GEOM_GATE
-Unterstützung in den Kernel
statisch einbauen, indem folgende Zeile zur
Kernelkonfigurationsdatei hinzugefügt wird. Anschließend muss
der Kernel, wie in Kapitel 8, Konfiguration des FreeBSD-Kernels beschrieben,
neu gebaut werden:
options GEOM_GATE
Das folgende Beispiel beschreibt, wie man zwei Knoten als
master-slave / primary-secondary mittels
HAST konfiguriert, um Daten zwischen diesen
beiden auszutauschen. Die Knoten werden als
hasta
mit der IP-Adresse
172.16.0.1
und hastb
mit
der IP-Adresse
172.16.0.2
bezeichnet. Beide Knoten
besitzen eine dedizierte Festplatte
/dev/ad6
mit der gleichen Größe für den
HAST-Betrieb. Der
HAST-Pool, manchmal auch Ressource genannt,
oder der GEOM-Provider in
/dev/hast/
wird als
test
bezeichnet.
Die Konfiguration von HAST wird in
/etc/hast.conf
vorgenommen. Diese Datei
sollte auf beiden Knoten gleich sein. Die einfachste
Konfiguration ist folgende:
resourcetest
{ onhasta
{ local/dev/ad6
remote172.16.0.2
} onhastb
{ local/dev/ad6
remote172.16.0.1
} }
Fortgeschrittene Konfigurationsmöglichkeiten finden Sie in hast.conf(5).
Es ist ebenfalls möglich, den Hostnamen in den
remote
-Anweisungen zu verwenden, falls
die Rechner aufgelöst werden können und in
/etc/hosts
, oder im lokalen
DNS definiert sind.
Sobald die Konfiguration auf beiden Rechnern vorhanden ist, kann ein HAST-Pool erstellt werden. Lassen Sie diese Kommandos auf beiden Knoten ablaufen, um die initialen Metadaten auf die lokale Platte zu schreiben und starten Sie anschließend hastd(8):
#
hastctl create
test
#
service hastd onestart
Es ist nicht möglich, GEOM-Provider mit einem bereits bestehenden Dateisystem zu verwenden, um beispielsweise einen bestehenden Speicher in einen von HAST verwalteten Pool zu konvertieren. Dieses Verfahren muss einige Metadaten auf den Provider schreiben und dafür würde nicht genug freier Platz zur Verfügung stehen.
Die Rolle eines HAST Knotens, primary
oder secondary
, wird vom einem
Administrator, oder einer Software wie
Heartbeat, mittels
hastctl(8) festgelegt. Auf dem primären Knoten
hasta
geben Sie diesen Befehl ein:
#
hastctl role primary
test
Geben Sie folgendes Kommando auf dem sekundären Knoten
hastb
ein:
#
hastctl role secondary
test
Überprüfen Sie das Ergebnis mit hastctl
auf beiden Knoten:
#
hastctl status
test
Überprüfen Sie die status
-Zeile. Wird
hier degraded
angezeigt, dann ist etwas mit
der Konfigurationsdatei nicht in Ordnung. Auf jedem Konten
sollte complete
angezeigt werden, was
bedeutet, dass die Synchronisation zwischen den beiden Knoten
gestartet wurde. Die Synchronisierung ist abgeschlossen, wenn
hastctl status
meldet, dass die
dirty
-Bereiche 0 Bytes betragen.
Der nächste Schritt ist, ein Dateisystem auf dem
GEOM-Provider anzulegen und dieses ins
System einzuhängen. Dies muss auf dem
primary
-Knoten durchgeführt werden.
Die Erstellung des Dateisystems kann ein paar Minuten dauern,
abhängig von der Größe der Festplatte. Dieses Beispiel
erstellt ein UFS-Dateisystem auf
/dev/hast/test
:
#
newfs -U /dev/hast/
test
#
mkdir /hast/
test
#
mount /dev/hast/
test
/hast/test
Sobald das HAST-Framework richtig
konfiguriert wurde, besteht der letzte Schritt nun darin,
sicherzustellen, dass HAST während des
Systemstarts automatisch gestartet wird. Fügen Sie diese
Zeile in /etc/rc.conf
hinzu:
hastd_enable="YES"
Das Ziel dieses Beispiels ist, ein robustes
Speichersystem zu bauen, welches Fehlern auf einem
beliebigen Knoten widerstehen kann. Wenn der
primary
-Knoten ausfällt, ist der
secondary
-Knoten da, um nahtlos
einzuspringen, das Dateisystem zu prüfen, einzuhängen und
mit der Arbeit fortzufahren, ohne dass auch nur ein
einzelnes Bit an Daten verloren geht.
Um diese Aufgabe zu bewerkstelligen, wird das
Common Address Redundancy
Protocol (CARP)
benutzt, welches ein automatisches Failover auf der
IP-Schicht ermöglicht.
CARP erlaubt es mehreren Rechnern im
gleichen Netzsegment, die gleiche
IP-Adresse zu verwenden. Setzen Sie
CARP auf beiden Knoten des Clusters
anhand der Dokumentation in Abschnitt 31.10, „Common Address Redundancy Protocol
(CARP)“ auf.
In diesem Beispiel hat jeder Knoten seine eigene
Management IP-Adresse und die geteilte
IP-Adresse
172.16.0.254
. Der primäre
HAST-Knoten des Clusters muss der
CARP-Masterknoten sein.
Der HAST-Pool, welcher im vorherigen
Abschnitt erstellt wurde, ist nun bereit für den Export über
das Netzwerk auf den anderen Rechner. Dies kann durch den
Export über NFS oder
Samba erreicht werden, indem die
geteilte IP-Adresse
172.16.0.254
verwendet wird. Das
einzige ungelöste Problem ist der automatische Failover,
sollte der primäre Knoten einmal ausfallen.
Falls die CARP-Schnittstelle aktiviert oder deaktiviert wird, generiert das FreeBSD-Betriebssystem ein devd(8)-Ereignis, was es ermöglicht, Zustandsänderungen auf den CARP-Schnittstellen zu überwachen. Eine Zustandsänderung auf der CARP-Schnittstelle ist ein Indiz dafür, dass einer der Knoten gerade ausgefallen oder wieder verfügbar ist. Diese Zustandsänderungen machen es möglich, ein Skript zu starten, welches automatisch den HAST-Failover durchführt.
Um Zustandsänderungen auf der
CARP-Schnittstelle abzufangen, müssen
diese Zeilen in /etc/devd.conf
auf
jedem Knoten hinzugefügt werden:
notify 30 { match "system" "IFNET"; match "subsystem" "carp0"; match "type" "LINK_UP"; action "/usr/local/sbin/carp-hast-switch master"; }; notify 30 { match "system" "IFNET"; match "subsystem" "carp0"; match "type" "LINK_DOWN"; action "/usr/local/sbin/carp-hast-switch slave"; };
Wenn auf dem System FreeBSD 10 oder höher eingesetzt
wird, ersetzen Sie carp0
durch den
Namen der konfigurierten Schnittstelle für
CARP.
Starten Sie devd(8) auf beiden Knoten neu, um die neue Konfiguration wirksam werden zu lassen:
#
service devd restart
Wenn die Schnittstelle
aktiviert oder deaktiviert wird, erzeugt das System eine
Meldung, was es dem devd(8)-Subsystem ermöglicht, ein
automatisches Failover-Skript zu starten,
/usr/local/sbin/carp-hast-switch
.
Weitere Informationen zu dieser Konfiguration finden Sie in
devd.conf(5).
Es folgt ein Beispiel für ein automatisches Failover-Skript:
#!/bin/sh
# Original script by Freddie Cash <fjwcash@gmail.com>
# Modified by Michael W. Lucas <mwlucas@BlackHelicopters.org>
# and Viktor Petersson <vpetersson@wireload.net>
# The names of the HAST resources, as listed in /etc/hast.conf
resources="test
"
# delay in mounting HAST resource after becoming master
# make your best guess
delay=3
# logging
log="local0.debug"
name="carp-hast"
# end of user configurable stuff
case "$1" in
master)
logger -p $log -t $name "Switching to primary provider for ${resources}."
sleep ${delay}
# Wait for any "hastd secondary" processes to stop
for disk in ${resources}; do
while $( pgrep -lf "hastd: ${disk} \(secondary\)" > /dev/null 2>&1 ); do
sleep 1
done
# Switch role for each disk
hastctl role primary ${disk}
if [ $? -ne 0 ]; then
logger -p $log -t $name "Unable to change role to primary for resource ${disk}."
exit 1
fi
done
# Wait for the /dev/hast/* devices to appear
for disk in ${resources}; do
for I in $( jot 60 ); do
[ -c "/dev/hast/${disk}" ] && break
sleep 0.5
done
if [ ! -c "/dev/hast/${disk}" ]; then
logger -p $log -t $name "GEOM provider /dev/hast/${disk} did not appear."
exit 1
fi
done
logger -p $log -t $name "Role for HAST resources ${resources} switched to primary."
logger -p $log -t $name "Mounting disks."
for disk in ${resources}; do
mkdir -p /hast/${disk}
fsck -p -y -t ufs /dev/hast/${disk}
mount /dev/hast/${disk} /hast/${disk}
done
;;
slave)
logger -p $log -t $name "Switching to secondary provider for ${resources}."
# Switch roles for the HAST resources
for disk in ${resources}; do
if ! mount | grep -q "^/dev/hast/${disk} on "
then
else
umount -f /hast/${disk}
fi
sleep $delay
hastctl role secondary ${disk} 2>&1
if [ $? -ne 0 ]; then
logger -p $log -t $name "Unable to switch role to secondary for resource ${disk}."
exit 1
fi
logger -p $log -t $name "Role switched to secondary for resource ${disk}."
done
;;
esac
Im Kern führt das Skript die folgenden Aktionen durch, sobald ein Knoten zum Master wird:
Es ernennt den HAST-Pool als den primären für einen gegebenen Knoten.
Es prüft das Dateisystem, dass auf dem HAST-Pool erstellt wurde.
Es hängt den Pool ins System ein.
Wenn ein Knoten zum Sekundären ernannt wird:
Hängt es den HAST-Pool aus dem Dateisystem aus.
Degradiert es den HAST-Pool zum sekundären.
Dieses Skript ist nur ein Beispiel für eine mögliche Lösung. Es behandelt nicht alle möglichen Szenarien, die auftreten können und sollte erweitert bzw. abgeändert werden, so dass z.B. benötigte Dienste gestartet oder gestoppt werden.
Für dieses Beispiel wurde ein UFS-Dateisystem verwendet. Um die Zeit für die Wiederherstellung zu verringern, kann ein UFS mit Journal oder ein ZFS-Dateisystem benutzt werden.
Weitere detaillierte Informationen mit zusätzlichen Beispielen können unter http://wiki.FreeBSD.org/HAST abgerufen werden.
HAST sollte generell ohne Probleme funktionieren. Jedoch kann es, wie bei jeder anderen Software auch, zu gewissen Zeiten sein, dass sie sich nicht so verhält wie angegeben. Die Quelle dieser Probleme kann unterschiedlich sein, jedoch sollte als Faustregel gewährleistet werden, dass die Zeit für alle Knoten im Cluster synchron läuft.
Für die Fehlersuche bei HAST sollte
die Anzahl an Debugging-Meldungen von hastd(8) erhöht
werden. Dies kann durch das Starten von
hastd
mit -d
erreicht
werden. Diese Option kann mehrfach angegeben werden, um die
Anzahl an Meldungen weiter zu erhöhen. Sie sollten ebenfalls
die Verwendung von -F
in Erwägung ziehen,
was hastd
im Vordergrund startet.
split-brain
bezeichnet eine
Situation, in der beide Knoten des Clusters nicht in der
Lage sind, miteinander zu kommunizieren und dadurch beide
als primäre Knoten fungieren. Dies ist ein
gefährlicher Zustand, weil es beiden Knoten erlaubt ist,
Änderungen an den Daten vorzunehmen, die miteinander nicht
in Einklang gebracht werden können. Diese Situation muss
vom Systemadministrator manuell bereinigt werden.
Der Administrator muss entscheiden, welcher Knoten die wichtigeren Änderungen besitzt, oder die Zusammenführung manuell durchführen. Anschließend kann HAST die volle Synchronisation mit dem Knoten durchführen, der die beschädigten Daten enthält. Um dies zu tun, geben Sie folgende Befehle auf dem Knoten ein, der neu synchronisiert werden muss:
#
hastctl role init
test
#
hastctl create
test
#
hastctl role secondary
test
Wenn Sie Fragen zu FreeBSD haben, schicken Sie eine E-Mail an
<de-bsd-questions@de.FreeBSD.org>.
Wenn Sie Fragen zu dieser Dokumentation haben, schicken Sie eine E-Mail an
<de-bsd-translators@de.FreeBSD.org>.