Linux-Cluster mit Open-Source-Tools

DRBD: RAID1 über das Netzwerk

11.12.2007 von Thomas Steudten
Hochverfügbarkeit innerhalb eines Servers zu realisieren, ist inzwischen kein Hexenwerk mehr. Etwas komplizierter wird es, wenn man zwei Server spiegeln will. Doch dank DRBD und heartbeat lässt sich ein Linux-Cluster kostengünstig realisieren.

Redundante Systeme und Ressourcen bilden heute in der Regel den Hauptbestandteil einer ausfallsicheren Umgebung (HA - High-Availability). Ziel ist es hierbei, den so genannten „Single Point of Failure“ (SPoF), also die Ressource im System, die aufgrund der Wahrscheinlichkeit als erstes Ausfallen wird, durch mehrfach vorhandene Ressourcen zur reduzieren. Innerhalb dieser Systemkette verursacht ein Fehler im schwächsten Glied ein Ausfall des Gesamtsystems.

Erfahrungswerte aus der Praxis zeigen, dass hier die Hardware ein Grossteil dieses Risikos trägt. Software redundant zu halten, ist kaum praktikabel und verursacht einen zu hohen Administrationsaufwand. Ein Single-System in der IT besitzt daher, um als ausfallsicher gegen einen SpoF zu gelten, wenigstens:

Eine größere Ausfallsicherheit erhält man durch den Einsatz von zwei Komplettsystemen, wie beispielsweise beim von uns getesteten Hochverfügbarkeits-Cluster. Dabei wird das Master-System auf ein sekundäres System gespiegelt und per Heartbeat überwacht. Bei Ausfall des Masters übernimmt das sekundäre System dessen Funktionen.

Wichtig ist allerdings, dass das sekundäre System mit denselben Daten agieren kann wie der Master. Hier kann man entweder ein teures Shared-Storage-System einsetzen oder die Daten vom Master zum Slave replizieren. Bei einem reinen Datenbank-Server ist das noch relativ einfach, denn die meisten Datenbanken verfügen über einen eingebauten Mechanismus zur Replikation, wie beispielsweise der Artikel MySQL verteilen und sichern zeigt.

Deutlich aufwändiger wird die ganze Sache jedoch, wenn auch Dateien repliziert werden sollen, etwa Konfigurationen oder Web-Inhalte. Hier kann man sich händisch per rsync ein Verfahren zusammenstricken oder gleich auf DRBD setzen und eine für die Anwendung transparente Datenreplikation implementieren.

DRBD(+)

RAID 1 (Mirroring) auf reiner Festplattenbasis kopiert Blöcke auf ein anderes, aber meist gleich aufgebautes Speichermedium im System selbst. Die Entfernung zwischen den Datenträgern ist nur gering, dafür sind Bandbreite und Performance recht hoch. Möchte man diese Spiegelung über Systeme vornehmen, die einige Kilometer voneinander entfernt aufgebaut sind, bietet sich eine Verbindung über das Internet an. Hier kommt beispielsweise das „Distributed Replicated Block Device“ (DRBD) als Steuerungsinstanz für diesen Kopierprozess zum Einsatz.

Bei DRBD handelt es sich um einen Blockdevice-Treiber für Linux, der speziell für den Aufbau von Hochverfügbarkeits-Clustern entwickelt wurde. DRBD ist in der Lage, Datenblöcke über das verbindungsorientierte TCP/IP Protokoll zu transferieren - man könnte auch von Netzwerk-RAID 1 sprechen.

Günstigstenfalls nutzt man einen dedizierten (Ethernet-)Link für die DRBD-Verbindung. Jedes beliebige R/W-Blockdevice für die Daten (unter LINUX /dev/[hs]daX) kann dazu verwendet werden. Eine so genannte Block-Map dient dazu, das Datenaufkommen für die Replikation zu minimieren, in dem nur geänderte Blocke transferiert werden.

Beide Endsysteme von DRBD müssen bereit sein, um eine Verbindung über TCP/IP zu etablieren. Ist es einer der Partner nicht, muss definiert werden, was passieren soll. Über Timeouts wird dieses Verhalten gesteuert, damit nicht beide Seiten blockiert sind, wenn die Gegenseite Datenpakete nicht beantwortet.

DRBD wurde von Philipp Reisner entwickelt und wird zusammen mit Lars Ellenberg beide von der österreichischen Firma „Linbit“ gewartet und steht unter der Lizenz der GPL. Der kommerzielle Nachfolger "DRBD+" erlaubt einen Abgleich über drei anstelle von zwei Blockdevices bis 16TiB und einen Multi-Primary-Betrieb. Die Quellen von DRBD stehen zur freien Verfügung.

Vergleich DRBD zu DRBD+

Was

DRBD

DRBD+

Devicegrösse [TB]

4

16

Anzahl Spiegelung

2

3

Synchronisierung

Bitmap

Checksumme

Beschleunigte Meta-Daten Operation

-

100x

Nutzung von HIGHMEM

-

ja

Anwendungen für DRBD

Mit DRBD lässt sich beispielsweise der Zugriff auf eine Datenbank an einer Firmenaußenstelle optimieren, indem eine Kopie der Daten vor Ort gehalten wird. Kopie heißt in diesem Fall kein Zugriff, so lange die originale Datenbank, das heißt das Blockdevice im Status "primary" aktiv ist. Im Fehlerfall würde die Datenbank diese gespiegelten Daten nutzen und so den Service aufrecht erhalten können.

Ein Webserver in Amerika kann seine Daten auf einen Webserver in Europa spiegeln und so den Zugriff im Fehlerfall auf den europäischen Server umlegen. Eine redundante Datenhaltung ist in den meisten Clustern eine Grundvoraussetzung.

Ohne DRBD wird dies in Form von so genannten shared Storages realisiert, also gemeinsam genutztem Speicher (SAN). Dieser Speicher muss, da nur einmal vorhanden, im Storage-System (SAN) gespiegelt werden (RAID-1, RAID-5), um redundant vorhanden zu sein.

Mit DRBD lässt sich diese doppelte oder dreifache (DRBD+) Datenhaltung im Gegensatz zum SAN mit preiswerten Standard-Festplatten realisieren.

Funktionsweise in der Praxis

DRBD arbeitet bis Version 0.7 nach dem Primary-Secondary-Prinzip (analog Master-Slave) und kopiert Blöcke immer vom primären zum sekundären System, wobei die Rollenverteilung dynamisch verändert werden kann. In der Regel kommt ein Blockdevice (/dev/sdXy), also eine Partition der Festplatte oder gar die ganze Festplatte zum Einsatz.

Funktionsweise von DRBD: Zwei Block-Devices mit Filesystemen „/test1“ und „/test2“ werden zwischen den Systemen „alpha“ und „beta“ konsistent gehalten, dafür sind zwei Ressourcen nötig. Quelle: Thomas Steudten

Funktionsweise von DRBD: Zwei Block-Devices mit Filesystemen „/test1“ und „/test2“ werden zwischen den Systemen „alpha“ und „beta“ konsistent gehalten, dafür sind zwei Ressourcen nötig. Quelle: Thomas Steudten

In den meisten LINUX Distributionen ist DRBD bereits in den Kernel integriert (als Modul „drbd“). Wird das Modul in den Kernel geladen, stehen die Device-Knoten /dev/drbdX zur Verfügung - je nach Einstellung in der Konfigurationsdatei /etc/drbd.conf.

So sieht es aus

# ls -l /dev/drbd? [Conf: minor-count]
brw-r----- 1 root disk 147, 0 Jan 29 13:27 /dev/drbd0
brw-r----- 1 root disk 147, 1 Jan 29 13:27 /dev/drbd1

# ps -ef | grep drbd | grep -v grep
root 3901 1 0 Jan29 ? 00:00:49 [drbd0_receiver]
root 5101 1 0 Jan29 ? 00:00:00 [drbd0_worker]
root 10414 1 0 Jan29 ? 00:00:20 [drbd0_asender]
root 3901 1 0 Jan29 ? 00:00:49 [drbd1_receiver]
root 5101 1 0 Jan29 ? 00:00:00 [drbd1_worker]
root 10414 1 0 Jan29 ? 00:00:20 [drbd1_asender]

# lsmod | grep drbd
drbd 161280 1

Hier ist das Modul “drbd” in den Kernel geladen, es sind zwei DRBD-Devices angelegt und die Kernel-Prozesse sind gestartet.

Damit sind die wesentlichen Voraussetzungen für die Funktion bereits gegeben. Je nachdem, welches DRBD-Device in der Konfiguratiosdatei zugeordnet wurde, sind pro Device die drei Prozesse aktiv:

Konfigurationsbeispiel

Nehmen wir vier gleich große Partitionen „/dev/sda1“ und „/dev/sda2“ auf Server alpha und „/dev/sdb3“ und „/dev/sdb1“ auf Server beta - und ernennen alpha zum Primärsystem für „sda“ und beta für „sdb1“. Dann müssten die Daten, die wir auf das Blockdevice /dev/sda1 schreiben, irgendwie auf das Blockdevice /dev/sdb3 auf beta gelangen.

DRBD klingt sich nun transparent ein und zwar so, dass wir „/dev/sda1“ und „/dev/sdb3“ als DRBD-Device „/dev/drbd1“ definieren.

Im nächsten Schritt mounten wir unser Dateisystem „/test1“ von alpha nicht mehr von „/dev/sda1“ sondern von „/dev/drbd1“. Auf alpha können wir mit „/test1“ nun ganz normal arbeiten. Kopieren wir nun die Datei testfile.txt auf „/test1“, schreibt der Kernel die vom Dateisystem belegten Blöcke lokal auf „/dev/sda1“ und der DRBD-Treiber diese Daten transparent auch auf „/dev/sdb3“ auf beta und somit sind beide /test1 Dateisysteme auf beiden System identisch. Analog gilt dies für DRBD0.

Sobald alpha als Primary für DRBD1 definiert ist, synchronisiert der DRDB-Treiber beide Block-Devices miteinander und in Folge müssen nur noch die Differenzen im Betrieb abgeglichen werden. Die Metadaten geben Auskunft darüber, welche Datenblöcke zu synchronisieren sind. Die Netzwerk-Bandbreite, die für diese Synchronisierung zur Verfügung steht, stellen Sie in der Konfigurationsdatei ein (Syncer: rate 10M).

Sicherheit und Performance

Drei Protokolle (ABC) erlauben je nach Erfordernissen der Anwendung (Sicherheit/ Performance) unterschiedliche Arten von Quittierungen des Schreibvorgangs an den Secondary:

Protokoll A

Bei dieser Variante signalisiert der Treiber das lokale Schreiben auf der Disk und das Verlassen des Pakets über das Netzwerkinterface. Ob das Paket auch auf der anderen Seite ankommen wird, bleibt offen. Dieses Protokoll eignet sich nicht für transaktionsbasierte Anwendungen.

Protokoll B

Funktioniert analog zu Protokoll A. Hier meldet der Treiber jedoch erst dann einen Erfolg, wenn die Daten lokal geschrieben wurden und die Gegenseite den Empfang quittiert hat. Fällt die Gegenseite aus, bevor die Daten physisch geschrieben worden sind, gibt es eine Inkonsistenz zwischen den beiden Systemen. Da hier auf eine Quittierung gewartet wird, sollte dieses Protokoll nicht bei Verbindungen mit hohen Latenzzeiten eingesetzt werden, da sonst die Senderseite zu stark ausgebremst wird.

Protokoll C

Dies ist das transaktionssicherste Protokoll, da es einen erfolgreichen Schreibvorgang dann zurückmeldet, wenn die Blöcke auch auf der Secondary- Seite erfolgreich auf das physische Medium geschrieben worden sind.

Lesezugriffe und Journaling-Filesysteme

Ein lesender Zugriff erfolgt immer vom lokalen Disksystem. Der Schreibvorgang muss auf allen Systemen entweder lokal oder remote erfolgen und kann je nach Protokoll auch den Schreibprozess auf dem Primärsystem verzögern. Metadaten von so genannten Journaling-Dateisystemen müssen in der richtigen Reihenfolge auf die Disk geschrieben werden, beispielsweise muss das so genannte „Commit Record“ als letztes in den Journal-Bereich geschrieben werden. Da Linux auf den Abschluss solcher zwingender Schreiboperationen wartet, bis es neue Schreibzugriffe erlaubt, kommt es zu Blockierungen. Dies muss der DRBD-Treiber koordinieren.

Seit Version 0.7 kann man ein so genanntes "active set" mit vorgegebener Größe definieren. Damit dauert der gesamte Synchronisierungsvorgang zwischen ein und drei Minuten abhängig von der Device-Größe.

Speicherbedarf

Für die interne Map alloziert DRBD pro Gigabyte Diskspeicher 32KiB Hauptspeicher und dieser Wert skaliert linear. Für seine Metadaten, die intern und extern abgelegt sein können, nutzt DRBD für 1GiB Blockdevices 2MiB und für 4TiB Devices 128MiB Metadaten.

Multi-Primary-Betrieb

Herkömmliche Dateisysteme (xfs, jfs, ext3) erlauben nur einen Zugriff pro System. Würde ein zweites System parallel darauf schreiben, käme es zu Inkonsistenzen, da das erste System davon nichts mitbekäme und seinen Datenbestand für aktuell hält.

So genannte Cluster- oder Global-Dateisysteme erlauben den gleichzeitigen Zugriff schreibend und lesend von mehreren Systemen aus. Vertreter diese Art sind beispielsweise das Oracle Cluster Filesystem 2 (OCFS2) oder das AIX Global Filesystem (GFS). OCFS2 ist seit Kernel 2.6.16 Bestandteil des Linux-Kernels.

Bei diesen Filesystemen unterstützt DRBD seit Version 8.0 auch den Multi-Primary-Betrieb, bei dem beide Systeme als primär agieren und schreiben dürfen.

Einrichtung von DRBD

Wir fokussieren uns hier auf die verbreitete Version 0.7 von DRBD - Version 8 hat eine leicht andere Syntax der Konfigurationsdatei. Die wichtigen Befehle für DRBD sind

Auf beiden Systemen ist zunächst die Datei /etc/drbd.conf anzulegen und dann mittels drbdadm up all das DRBD-System zu starten. Wir definieren eine Ressourcegruppe mit Namen „r1“, die wir in das Verzeichnis „/test1“ mounten.

Die Konfigurationsdatei lässt sich grob in drei Bereiche untergliedern:

Erste Ressource anlegen

Die drbd.conf für “/test1” sieht wie folgt aus. Dabei sind die IP-Adressen der Rechner an die tatsächlichen Gegebenheiten anzupassen. Verwenden Sie eine dedizierte Verbindung zur Replikation, benutzen Sie die IP-Adresse der Direkt-Verbindung.

global {
usage-count yes;
minor-count 2;
diaglog-refresh 5;
}

resource r1 {
protocol C; # oder A oder B

net {
cram-hmac-alg sha1;
shared-secret "ExDRBD";
# allow-two-primaries;
}
on alpha {
device /dev/drbd1;
disk /dev/sda1;
address 10.0.0.10:7888;
meta-disk internal;
}
on beta {
device /dev/drbd1;
disk /dev/sdb3;
address 10.0.0.11:7888;
meta-disk internal;
}
syncer { rate 10M; }
}

Kopieren Sie die Datei in das Verzeichnis /etc auf beiden Systemen und starten die Ressource mit drbdadm up r1.

Erster Sync der Ressource

Damit sind beide Systeme erst einmal im Modus „Secondary/Inkonsitent“, da zu diesem Zeitpunkt nicht bekannt ist, wer Primary und wer Secondary sein soll. Wurde noch kein Dateisystem angelegt oder sind keine Nutzdaten vorhanden, spielt die Reihenfolge noch keine Rolle.

Auf dem System alpha starten wir nun einen „Full-Sync“ mit alpha als Primärsystem. Vor Version 8.0 erledigen Sie das mit drbdadm -- –-do-what-I-say primary r1 und ab V8.0 lautet der Befehl drbdadm -- –-overwrite-data-of-peer primary r1.

Hierbei gibt der Parameter r1 die Ressource an. Verwenden Sie stattdessen all, werden alle konfigurierten Ressourcen synchronisiert.

Den Status von DRBD kann Sie am Inhalt der Datei drbd im Pseudofilesystem /proc auslesen. Je nach DRBD-Status ("st:") ergibt sich "Secondary/Primary" oder "Primary/Secondary" auf dem Primary: cat /proc/drbd:

# cat /proc/drbd [auf dem Secondary]
version: 0.7.22 (api:79/proto:74)
0: cs:Unconfigured
1: cs:Connected st:Secondary/Primary ld:Consistent
ns:225512 nr:4116388 dw:4341956 dr:877454 al:64 bm:991 lo:0 pe:0 ua:0 ap:0

Nun teilen wir dem System alpha mit, dass es DRBD-Primary sein soll. Damit wird beta automatisch zum Secondary:

alpha> drbdadm primary r1

Testen

Nun legen wir ein ext3-Journaling-Filesystem an und kopieren eine Datei in das neue Filesystem, um zu sehen, ob es auch auf beta erscheint.

alpha> mkext3fs /dev/drbd1
alpha> mount /dev/drbd1 /test1
alpha> hostname > testfile.txt

Die Blockdevices sind damit auf beiden Systemen synchronisiert und wir können es auf “beta” zugänglich machen:

alpha> umount /test1
alpha> drbdadm secondary r1
beta> drbdadm primary r1
beta> mount /dev/drbd1 /test1
beta> cat /test1/testfile.txt -> zeigt “alpha”

Es ist Ihnen wahrscheinlich aufgefallen, dass man auf beiden Systemen das Kommando drbdadm primary|secondary r1 absetzen muss, um zu entscheiden, wer Primary sein soll. Der ursprüngliche “Primary” muss “Secondary” werden, möchte man die Funktion tauschen. In einem Clustersystem mit “heartbeat” übernimmt dies auf beiden Systemen das mitgelieferte Skript drbddisk.

Schutz vor Anwenderfehlern

DRBD schützt den Benutzer automatisch vor einigen der gängigsten Fehlern in der Bedienung:

Man könnte nun auf beta das Dateisystem (das Blockdevice) read-only mounten, in der Regel wird aber eine Clustersoftware (heartbeat) zum Einsatz kommen und nur das Dateisystem des Primary mounten. Ab Version 8.0.x können beide Seiten das Filesystem als Primary nutzen, wenn ein Shared-Filesystem wie GFS oder OCFS2 eingesetzt wird (Option: net { allow-two-primaries })

DRBD automatisch starten

Die meisten LINUX Distributionen bringen bereits ein passendes SysV-Startskript unter /etc/init.d/drbd mit, so dass sie lediglich den Dienst aktivieren müssen.

Fazit

Hochverfügbarkeit ist heute aufgrund von niedrigen Hardware-Preisen und OpenSource-Produkten alltäglich und finanzierbar. DRBD und DRBD+ bieten in diesem Segment diese HA-Möglichkeiten, die bisher meist nur von kommerziellen, teueren Produkten angeboten wurden.

Clusterlösungen mit DRBD+ erlauben eine Drei-Wege-Spiegelung über weit verteilte Standorte mit einfachen Mitteln.

Linux kommt mit dem Clustersystem „heartbeat“ und DRBD nahe an die Funktionen von Sun-, Veritas VCS und IBM HACMP-Clustern heran. Letztere benötigen allerdings ein teures Speichersystem mit gemeinsamem Zugriff (Shared-FC, SCSI). Linux in Kombination mit DRBD bietet diesen Komfort dagegen mit üblichen lokalen und preiswerten Diskspeichern. (mha)