18.14. Highly Available Storage (HAST)

Beigetragen von Daniel Gerzo.
Mit Beiträgen von Freddie Cash, Pawel Jakub Dawidek, Michael W. Lucas und Viktor Petersson.
Übersetzt von Benedict Reuschling.

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:

Nachdem Sie diesen Abschnitt gelesen haben, werden Sie folgendes wissen:

Bevor Sie diesen Abschnitt lesen, sollten Sie:

Das HAST-Projekt wurde von der FreeBSD Foundation mit Unterstützung der OMCnet Internet Service GmbH und TransIP BV gesponsert.

18.14.1. HAST im Einsatz

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.

18.14.2. HAST-Konfiguration

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 9, 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:

resource test {
	on hasta {
		local /dev/ad6
		remote 172.16.0.2
	}
	on hastb {
		local /dev/ad6
		remote 172.16.0.1
	}
}

Fortgeschrittene Konfigurationsmöglichkeiten finden Sie in hast.conf(5).

Tipp:

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

Anmerkung:

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"

18.14.2.1. Failover-Konfiguration

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";
};

Anmerkung:

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.

Achtung:

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.

Tipp:

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.

18.14.3. Fehlerbehebung

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.

18.14.3.1. Auflösung des Split-brain-Zustands

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