Hochverfügbarkeit ist eine der Hauptanforderungen von ernsthaften Geschäftsanwendungen
und hochverfügbarer Speicher ist eine Schlüsselkomponente in solchen Umgebungen. Highly
Available STorage, oder HAST, wurde von Pawel Jakub Dawidek <[email protected]>
als
ein Framework entwickelt, 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.
Nachdem Sie diesen Abschnitt gelesen haben, werden Sie folgendes wissen:
Was HAST ist, wie es funktioniert und welche Eigenschaften es besitzt.
Wie man HAST auf 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 4).
wissen, wie man Netzwerkschnittstellen und andere Kernsysteme von FreeBSD konfiguriert (Kapitel 12).
ein gutes Verständnis der FreeBSD-Netzwerkfunktionalität besitzen (Teil IV in dem Das FreeBSD-Handbuch).
FreeBSD 8.1-RELEASE oder höher einsetzen.
Das HAST-Projekt wurde von der FreeBSD Foundation mit Unterstützung der OMCnet Internet Service GmbH und TransIP BV gesponsert.
Die Hauptmerkmale des HAST-Systems 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.
HAST stellt auf Block-Ebene eine synchrone Replikation eines beliebigen Speichermediums auf mehreren Maschinen zur Verfügung. Daher werden mindestens zwei Knoten (physikalische Maschinen) benötigt: der primary (auch bekannt als master) Knoten, sowie der secondary (slave) Knoten. Diese beiden Maschinen zusammen werden als Cluster bezeichnet.
Anmerkung: HAST ist momentan auf insgesamt zwei Knoten im Cluster beschränkt.
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 secondary-Knoten wird automatisch vom primary-Knoten aus synchronisiert.
Die physischen Komponenten des HAST-Systems sind:
lokale Platte (am Primärknoten)
Platte am entfernten Rechner (Sekundärknoten)
HAST arbeitet synchron auf Blockebene, was es für Dateisysteme und Anwendungen transparent macht. HAST stellt gewöhnliche GEOM-Provider im Verzeichnis /dev/hast/ für die Verwendung durch andere Werkzeuge oder Anwendungen zur Verfügung, somit gibt es keinen Unterschied zwischen dem Einsatz von durch HAST bereitgestellten Geräten und herkömmlichen Platten, Partitionen, etc.
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 sehr 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: 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. Der memsync-Replikationsmodus ist momentan noch nicht implementiert.
fullsync: meldet Schreiboperationen als vollständig, wenn die lokale Schreiboperation beendet ist und die entfernte Schreiboperation ebenfalls abgeschlossen wurde. Dies ist der sicherste und zugleich der langsamste Replikationsmodus. Er stellt den momentanen Standardmodus dar.
async: meldet Schreiboperationen als vollständig, wenn lokale Schreibvorgänge abgeschlossen wurden. Dies ist der schnellste und gefährlichste Replikationsmodus. Er sollte verwendet werden, wenn die Latenz zu einem entfernten Knoten bei einer Replikation zu hoch ist für andere Modi. Der async-Replikationsmodus ist zum gegenwärtigen Zeitpunkt nicht implementiert.
Warnung: Momentan wird nur der fullsync-Replikationsmodus unterstützt.
HAST benötigt GEOM_GATE-Unterstützung, um korrekt zu funktionieren. Der GENERIC-Kernel enthält jedoch GEOM_GATE nicht von vornherein, jedoch ist in der Standardinstallation von FreeBSD geom_gate.ko als ladbares Modul vorhanden. Stellen Sie bei Systemen, bei denen nur das Allernötigste vorhanden sein soll, sicher, dass dieses Modul zur Verfügung steht. Als Alternative lässt sich die GEOM_GATE-Unterstützung direkt in den Kernel statisch einbauen, indem Sie die folgende Zeile zu Ihrer Kernelkonfigurationsdatei hinzufügen:
options GEOM_GATE
Das HAST-Framework besteht aus Sicht des Betriebssystems aus mehreren Bestandteilen:
Dem hastd(8)-Dienst, welcher für die Datensynchronisation verantwortlich ist,
Dem hastctl(8) Management-Werkzeug,
Der Konfigurationsdatei hast.conf(5).
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össe für den HAST-Betrieb. Der HAST-Pool (manchmal auch Ressource genannt, z.B. der GEOM-Provider in /dev/hast/) wird als test bezeichnet.
Die Konfiguration von HAST wird in der Datei /etc/hast.conf vorgenommen. Diese Datei sollte auf beiden Knoten gleich sein. Die denkbar 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 } }
Schlagen Sie in der hast.conf(5)-Manualpage nach, wenn Sie an erweiterten Konfigurationsmöglichkeiten interessiert sind.
Tipp: Es ist ebenfalls möglich, den Hostnamen in den remote-Anweisungen zu verwenden. Stellen Sie in solchen Fällen sicher, dass diese Rechner auch aufgelöst werden können, also in der Datei /etc/hosts aufgeführt sind, oder alternativ im lokalen DNS.
Da nun die Konfiguration auf beiden Rechnern vorhanden ist, sind Sie in der Lage, den HAST-Pool zu erstellen. Lassen Sie die folgenden Kommandos auf beiden Knoten ablaufen, um die initialen Metadaten auf die lokale Platte zu schreiben und starten Sie anschliessend den hastd(8)-Dienst:
# hastctl create test # /etc/rc.d/hastd onestart
Anmerkung: Es ist nicht möglich, GEOM-Provider mit einem bereits bestehenden Dateisystem zu verwenden (z.B. um einen bestehenden Speicher in einen von HAST verwalteten Pool zu konvertieren), weil diese Prozedur bestimmte Metadaten auf den Provider schreiben muss und dafür nicht genug freier Platz zur Verfügung stehen wird.
HAST ist nicht dafür verantwortlich, die Rolle (primary oder secondary) für den jeweiligen Knoten festzulegen. Die Rolle des Knotens muss vom Administrator oder einer anderen Software wie Heartbeat mittels des hastctl(8)-Werkzeugs festgelegt werden. Auf dem primären Knoten (hasta) geben Sie nun den folgenden Befehl ein:
# hastctl role primary test
Geben Sie nun, ähnlich wie zuvor, das folgende Kommando auf dem sekundären Knoten (hastb) ein:
# hastctl role secondary test
Achtung: Es kann passieren, dass beide Knoten nicht in der Lage sind, miteinander zu kommunizieren und dadurch beide als primäre Knoten konfiguriert sind; die Konsequenz daraus wird als split-brain bezeichnet. Um diese Situation zu bereinigen, folgen Sie den Schritten, die in Abschnitt 19.18.5.2 beschrieben sind.
Es ist möglich das Ergebnis des hastctl(8)-Werkzeugs auf jedem Knoten zu überprüfen:
# hastctl status test
Der wichtigste Teil ist die status-Textzeile der Ausgabe, die auf jedem Knoten complete lauten sollte. Falls der Status als degraded zurückgemeldet wird, ist etwas schief gegangen. Zu diesem Zeitpunkt hat die Synchronisation zwischen den beiden Knoten bereits begonnen. Die Synchronisation ist beendet, wenn das Kommando hastctl status meldet, dass die dirty-Bereiche 0 Bytes betragen.
Der letzte Schritt ist, ein Dateisystem auf dem /dev/hast/test GEOM-Provider anzulegen und dieses ins System einzuhängen. Dies muss auf dem primary-Knoten durchgeführt werden (da /dev/hast/test nur auf dem primary-Knoten erscheint). Dies kann ein paar Minuten dauern, abhängig von der Grösse der Festplatte:
# 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. Die folgende Zeile sollte zur Datei /etc/rc.conf hinzugefügt werden:
hastd_enable="YES"
Das Ziel dieses Beispiels ist, ein robustes Speichersystem zu bauen, welches Fehlern auf einem beliebigen Knoten widerstehen kann. Die Schlüsselaufgabe in diesem Szenario besteht darin, zu verhindern, dass der primary-Knoten des Clusters ausfällt. Sollte es dennoch passieren, 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 ging.
Um diese Aufgabe zu bewerkstelligen, ist es nötig, eine weitere Eigenschaft zu nutzen, die unter FreeBSD verfügbar ist, welche ein automatisches Failover auf der IP-Schicht ermöglicht: CARP. CARP steht für Common Address Redundancy Protocol und 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 32.13 auf. Nachdem dieser Schritt abgeschlossen ist, sollte jeder Knoten seine eigene carp0-Schnittstelle mit der geteilten IP-Adresse 172.16.0.254 besitzen. Selbstverständlich muss der primäre HAST-Knoten des Clusters 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, Samba etc. erreicht werden, indem die geteilte IP-Addresse 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. In diesem Fall ist es möglich, ein Skript zu starten, welches den Failover automatisch durchführt.
Um diese Zustandsänderungen auf der CARP-Schnittstelle abzufangen, müssen die folgenden Zeilen in der Datei /etc/devd.conf auf jedem Knoten eingefü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"; };
Um diese neue Konfiguration zu aktivieren, starten Sie devd(8) auf beiden Knoten neu, um die neue Konfiguration wirksam werden zu lassen:
# /etc/rc.d/devd restart
Für den Fall, dass die carp0-Schnittstelle aktiviert oder deaktiviert wird (sich also der Status der Schnittstelle ändert), erzeugt das System eine Meldung, was es dem devd(8)-Subsystem ermöglicht, ein beliebiges Skript zu starten, in diesem Fall also /usr/local/sbin/carp-hast-switch. Dies ist das Skript, dass den automatischen Failover durchführt. Für genauere Informationen zu der obigen devd(8)-Konfiguration, lesen Sie die devd.conf(5)-Manualpage.
Ein Beispiel für ein solches Skript könnte wie folgt aussehen:
#!/bin/sh # Original script by Freddie Cash <[email protected]> # Modified by Michael W. Lucas <[email protected]> # and Viktor Petersson <[email protected]> # 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 / primary 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 die Pools an die richtige Stelle im System ein.
Wenn ein Knoten zum backup / secondary ernannt wird:
Hängt es den HAST-Pool aus dem Dateisystem aus.
Degradiert es den HAST-Pool zum sekundären.
Achtung: Bitte beachten Sie, dass dieses Skript nur ein Beispiel für eine mögliche Lösung darstellt. 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 usw.
Tipp: Für dieses Beispiel wurde ein Standard-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 auf der HAST Wiki-Seite 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 beide Knoten im Cluster synchron läuft.
Die Anzahl an Debugging-Meldungen von hastd(8) sollte erhöht werden, wenn Fehler von HAST bereinigt werden. Dies kann durch das Starten des hastd(8)-Dienstes mit der Option -d erreicht werden. Wichtig zu wissen ist, dass diese Option mehrfach angegeben werden kann, um die Anzahl an Meldungen weiter zu erhöhen. Sie können viele nützliche Informationen auf diese Art bekommen. Sie sollten ebenfalls die Verwendung der Option -F in Erwägung ziehen, die den hastd(8)-Dienst in den Vordergrund bringt.
Die Konsequenz aus der Situation, wenn beide Knoten des Clusters nicht in der Lage sind, miteinander zu kommunizieren und dadurch beide als primäre Knoten fungieren, wird als split-brain bezeichnet. 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 sollte vom Systemadministrator händisch bereinigt werden.
Um diese Situation zu beheben, muss der Administrator entscheiden, welcher Knoten die wichtigsten Änderungen von beiden besitzt (oder diese manuell miteinander vermischen) und anschliessend den HAST-Knoten die volle Synchronisation mit jenem Knoten durchführen zu lassen, welcher die beschädigten Daten besitzt. Um dies zu tun, geben Sie die folgenden Befehle auf dem Knoten ein, der neu synchronisiert werden soll:
# hastctl role init <resource> # hastctl create <resource> # hastctl role secondary <resource>
Zurück | Zum Anfang | Weiter |
Den Auslagerungsspeicher verschlüsseln | Nach oben | GEOM: Modulares Framework zur Plattentransformation |
Wenn Sie Fragen zu FreeBSD haben, schicken Sie eine E-Mail an
<[email protected]>.
Wenn Sie Fragen zu dieser Dokumentation haben, schicken Sie eine E-Mail an <[email protected]>.