Einen hoch-verfügbaren NFS Server aufsetzen
Setting Up A Highly Available NFS Server
Version 1.0
Author: Falko Timme <ft [at] falkotimme [dot] com>
Last edited: 03/07/2006
Diese Anleitung veranschaulicht, wie man einen hoch-verfügbaren NFS server aufsetzt, der als Speicherlösung für andere hoch-verfügbare Dienste wie zum Beispiel einem Cluster von Web Servern verwendet werden kann. Wenn Du ein Web Server Cluster bestehend aus zwei oder mehreren Systemen hast, die die gleiche(n) Webseite(n) bedienen, dann müssen diese Systeme auf den gleichen Datenpool zugreifen, so dass jedes System die gleichen Daten bedient, egal ob der Loadbalancer den Benutzer auf System 1 oder n verweist. Das kann mit einer NFS Freigabe auf einem NFS Server, auf den alle Web Server Systeme (die NFS Clients) zugreifen können, erreicht werden.
Da wir nicht möchten, dass der NFS Server zu einer weiteren Schwachstelle wird, müssen wir ihn hoch-verfügbar machen. Tatsächlich werde ich in dieser Anleitung zwei NFS Server erstellen, die ihre Daten in Echtzeit unter Verwendung von DRBD spiegeln und sich mittels heartbeat gegenseitig überwachen. Wenn ein NFS Server ausfällt, übernimmt der andere. Nach außen werden diese beiden NFS Server den Anschein erwecken, als sei es nur ein NFS Server.
In diesem Setup werde ich Debian Sarge (3.1) für die beiden NFS Server sowie für den NFS Client (der ein System des Web Server Clusters repräsentiert) verwenden.
Ich möchte an dieser Stelle darauf hinweisen, dass dies nicht der einzige Weg ist, ein solches System aufzusetzen. Es gibt viele Möglichkeiten dieses Ziel zu erreichen – dies ist der Weg, den ich gewählt habe. Ich übernehme keine Garantie, dass dies auch bei Dir funktioniert!
1 Mein Setup
In dieser Anleitung verwende ich folgende Systeme:
- NFS Server 1: server1.example.com, IP Adresse: 192.168.0.172; ich werde mich als server1 auf ihn beziehen.
- NFS Server 2: server2.example.com, IP Adresse: 192.168.0.173; ich werde mich als server2 auf ihn beziehen.
- Virtuelle IP Adresse: ich verwende 192.168.0.174 als die virtuelle IP Adresse, die das NFS Cluster nach Außen repräsentiert.
- NFS Client (z.B. ein System des Web Server Clusters): client.example.com, IP Adresse: 192.168.0.100; ich werde mich client auf den NFS Client beziehen.
- Das /data Verzeichnis wird von DRBD zwischen server1 und server2 gespiegelt. Es wird die NFS Freigabe /data/export beinhalten.
2 Basis-Installation von server1 und server2
Zuerst richten wir zwei Debian Basissysteme für server1 und server2 ein. Dies nimmst Du wie auf den ersten beiden Seiten folgender Anleitung beschrieben wird vor: https://www.howtoforge.com/perfect_setup_debian_sarge. Als Hostnamen gibst Du an gegebener Stelle server1 und server2 ein und example.com als Domain.
Was die Partitionierung betrifft, verwende ich folgendes Partitionsschema:
/dev/sda1 — 100 MB /boot (primary, ext3, Bootable flag: on)
/dev/sda5 — 5000 MB / (logical, ext3)
/dev/sda6 — 1000 MB swap (logical)
/dev/sda7 — 150 MB unmounted (logical, ext3) (wird DRBDs Meta Daten enthalten)
/dev/sda8 — 26 GB unmounted (logical, ext3) (wird das /data Verzeichnis enthalten)
Du kannst die Größe der Partitionen entsprechend der Größe Deiner Festplatte ändern. Die Bezeichnung Deiner Partition können ebenfalls variieren, das hängt von Deiner Hardware ab (z.B. hast Du vielleicht /dev/hda1 anstelle von /dev/sda1 und so weiter). Es ist jedoch wichtig, dass /dev/sda7 etwas mehr als 128 MB aufweist, da wir diese Partition für DRBDs Meta Daten verwenden, was 128 MB verwendet. Pass auf, dass /dev/sda7 sowie /dev/sda8 die gleiche Größe auf server1 und server2 aufweisen und bitte mounte sie nicht (wenn Dich der Installer fragt:
No mount point is assigned for the ext3 file system in partition #7 of SCSI1 (0,0,0) (sda).
Do you want to return to the partitioning menu?
antworte bitte No)! /dev/sda8 wird unsere Daten-Partition sein (d.h. unsere NFS Freigabe).
Stelle nach der Basis-Installation sicher, dass Du server1 und server2 statische IP Adressen (server1: 192.168.0.172, server2: 192.168.0.173) zuweist, was am Anfang von https://www.howtoforge.com/perfect_setup_debian_sarge_p3) beschrieben wird.
Danach solltest Du /etc/fstab auf beiden Systemen überprüfen. Meine sieht auf beiden Systemen wie folgt aus:
# /etc/fstab: static file system information. # # proc /proc proc defaults 0 0 /dev/sda5 / ext3 defaults,errors=remount-ro 0 1 /dev/sda1 /boot ext3 defaults 0 2 /dev/sda6 none swap sw 0 0 /dev/hdc /media/cdrom0 iso9660 ro,user,noauto 0 0 /dev/fd0 /media/floppy0 auto rw,user,noauto 0 0 |
Wenn Deine zum Beispiel wie diese aussieht:
# /etc/fstab: static file system information. # # proc /proc proc defaults 0 0 /dev/hda5 / ext3 defaults,errors=remount-ro 0 1 /dev/hda1 /boot ext3 defaults 0 2 /dev/hda6 none swap sw 0 0 /dev/hdc /media/cdrom0 iso9660 ro,user,noauto 0 0 /dev/fd0 /media/floppy0 auto rw,user,noauto 0 0 |
dann pass bitte auf, dass Du /dev/hda anstelle von /dev/sda in den folgenden Konfigurationsdateien verwendest. Pass ebenfalls auf, dass /dev/sda7 (oder /dev/hda7) und /dev/sda8 (oder /dev/hda8…) nicht in /etc/fstab aufgelistet sind!
3 Synchronisation der System-Zeit
Es ist wichtig, dass server1 und server2 die gleiche System-Zeit haben. Daher installieren wir einen NTP Client auf beiden Servern:
server1/server2:
apt-get install ntp ntpdate
Danach kannst Du überprüfen, ob beide die gleiche Zeit haben, indem Du dies ausführst
server1/server2:
date
4 Installation des NFS Servers
Als Nächstes installieren wir den NFS Server auf server1 und server2:
server1/server2:
apt-get install nfs-kernel-server
Dann entfernen wir die System Bootup Links für NFS, da NFS in unserem Setup von heartbeat gestartet und kontrolliert wird:
server1/server2:
update-rc.d -f nfs-kernel-server remove
update-rc.d -f nfs-common remove
Wir möchten das Verzeichnis /data/export (d.h. dies wird unsere NFS Freigabe sein, die unsere Web Server Cluster Systeme verwenden werden, um Web Inhalt zu bedienen) exportieren, also bearbeiten wir /etc/exports auf server1 und server2. Es sollte nur die folgende Zeile enthalten:
server1/server2:
/etc/exports:
/data/export/ 192.168.0.0/255.255.255.0(rw,no_root_squash,no_all_squash,sync) |
Das bedeutet, dass auf /data/export von allen Systemen aus dem 192.168.0.x Subnetz zugegriffen werden kann. Du kannst den Zugriff auf ein einziges System beschränken, indem Du 192.168.0.100/255.255.255.255 anstelle von 192.168.0.0/255.255.255.0 verwendest. Sieh Dir zum Beispiel
man 5 exports
an um mehr darüber zu erfahren.
Zu einem späteren Zeitpunkt werden wir /data/exports auf unserer leeren (und immer noch nicht gemounteten!) Partition /dev/sda8 erstellen.
5 Installation von DRBD
Als Nächstes installieren wir DRBD auf server1 und server2:
server1/server2:
apt-get install kernel-headers-2.6.8-2-386 drbd0.7-module-source drbd0.7-utils
cd /usr/src/
tar xvfz drbd0.7.tar.gz
cd modules/drbd/drbd
make
make install
Bearbeite dann /etc/drbd.conf auf server1 und server2. Es muss auf beiden Systemen identisch sein und wie folgt aussehen:
server1/server2:
/etc/drbd.conf:
resource r0 { protocol C; incon-degr-cmd "halt -f"; startup { degr-wfc-timeout 120; # 2 minutes. } disk { on-io-error detach; } net { } syncer { rate 10M; group 1; al-extents 257; } on server1 { # ** EDIT ** the hostname of server 1 (uname -n) device /dev/drbd0; # disk /dev/sda8; # ** EDIT ** data partition on server 1 address 192.168.0.172:7788; # ** EDIT ** IP address on server 1 meta-disk /dev/sda7[0]; # ** EDIT ** 128MB partition for DRBD on server 1 } on server2 { # ** EDIT ** the hostname of server 2 (uname -n) device /dev/drbd0; # disk /dev/sda8; # ** EDIT ** data partition on server 2 address 192.168.0.173:7788; # ** EDIT ** IP address on server 2 meta-disk /dev/sda7[0]; # ** EDIT ** 128MB partition for DRBD on server 2 } } |
Als Resource Namen kannst Du nehmen was immer Du willst. Hier ist es r0. Bitte pass auf, dass Du die korrekten Hostnamen von server1 und server2 in /etc/drbd.conf einsetzt. DRBD erwartet dass die Hostnamen so sind wie sie von folgendem Befehl angezeigt werden
uname -n
Wenn Du server1 und server2 als Hostnamen während der Basis-Installation von Debian gewählt hast, dann sollte die Ausgabe von uname -n server1 und server2 sein.
Pass außerdem auf, dass Du die IP Adressen und Festplatten entsprechend ersetzt. Wenn Du /dev/hda anstelle von /dev/sda verwendest, bitte setze /dev/hda8 anstelle von /dev/sda8 in /etc/drbd.conf (das Gleiche gilt für die meta-disk auf der DRBD seine Meta Daten speichert). /dev/sda8 (oder /dev/hda8…) wird später als unsere NFS Freigabe verwendet.
6 Konfiguration von DRBD
Nun laden wir das DRBD Kernel Modul auf server1 und server2. Das müssen wir nur dieses eine Mal ausführen, da es danach vom DRBD Init Skript geladen wird.
server1/server2:
modprobe drbd
Lass uns DRBD konfigurieren:
server1/server2:
drbdadm up all
cat /proc/drbd
Der letzte Befehl sollte etwas in der Art anzeigen (auf server1 und server2):
version: 0.7.10 (api:77/proto:74) SVN Revision: 1743 build by phil@mescal, 2005-01-31 12:22:07 0: cs:Connected st:Secondary/Secondary ld:Inconsistent ns:0 nr:0 dw:0 dr:0 al:0 bm:1548 lo:0 pe:0 ua:0 ap:0 1: cs:Unconfigured |
Wie Du siehst, geben beide NFS Server an, dass sie zweitrangig und die Daten inkonsistent sind. Das liegt daran, dass bisher noch kein Initial Sync ausgeführt wurde.
server1 soll der erste NFS Server und server2 der „hot-standby“ sein. Wenn server1 ausfällt, übernimmt server2 und wenn server1 wieder funktionsfähig ist, werden alle Daten, die sich in der Zwischenzeit geändert haben, von server2 auf server1 zurück gespiegelt, damit die Daten immer konsistent sind.
Der nächste Schritt wird nur auf server1 durchgeführt!
server1:
drbdadm — –do-what-I-say primary all
Nun starten wir das Initial Sync zwischen server1 und server2 damit die Daten auf beiden Servern konsistent werden. Auf server1 führen wir dies aus:
server1:
drbdadm — connect all
Das Initial Sync wird ein paar Stunden dauern (das hängt von der Größe von /dev/sda8 (/dev/hda8…) ab), sei also bitte geduldig.
So siehst Du den Fortschritt des Initial Sync auf server1 oder server2:
server1/server2:
cat /proc/drbd
Die Ausgabe sollte wie folgt aussehen:
version: 0.7.10 (api:77/proto:74) SVN Revision: 1743 build by phil@mescal, 2005-01-31 12:22:07 0: cs:SyncSource st:Primary/Secondary ld:Consistent ns:13441632 nr:0 dw:0 dr:13467108 al:0 bm:2369 lo:0 pe:23 ua:226 ap:0 [==========>.........] sync'ed: 53.1% (11606/24733)M finish: 1:14:16 speed: 2,644 (2,204) K/sec 1: cs:Unconfigured |
Wenn das Initial Sync abgeschlossen ist, sollte die Ausgabe wie folgt aussehen:
SVN Revision: 1743 build by phil@mescal, 2005-01-31 12:22:07 0: cs:Connected st:Primary/Secondary ld:Consistent ns:37139 nr:0 dw:0 dr:49035 al:0 bm:6 lo:0 pe:0 ua:0 ap:0 1: cs:Unconfigured |
7 Eine weitere NFS Konfiguration
NFS speichert einige wichtige Informationen (z.B. Informationen über die Datei Locks, etc.) in /var/lib/nfs. Was passiert nun wenn server1 ausfällt? server2 übernimmt, aber seine Information in /var/lib/nfs wird von der Information im server1s /var/lib/nfs Verzeichnis abweichen. Dazu nehmen wir eine Optimierung vor, so dass diese Angaben auf unserer /data Partition (/dev/sda8 oder /dev/hda8…) gespeichert werden, die von DRBD zwischen server1 und server2 gespiegelt wird. Wenn server1 also ausfällt, kann server2 die NFS Angaben von server1 verwenden.
server1/server2:
mkdir /data
server1:
mount -t ext3 /dev/drbd0 /data
mv /var/lib/nfs/ /data/
ln -s /data/nfs/ /var/lib/nfs
mkdir /data/export
umount /data
server2:
rm -fr /var/lib/nfs/
ln -s /data/nfs/ /var/lib/nfs
8 Installation und Konfiguration von heartbeat
heartbeat ist die Kontrollinstanz des ganzen Setups. Es wird auf server1 und server2 installiert und überwacht den anderen Server. Wenn server1 zum Beispiel ausfällt, bemerkt heartbeat das auf server2 und sorgt dafür, dass server2 übernimmt. Außerdem startet und stoppt heartbeat den NFS Server auf server1 und server2. Es bietet NFS außerdem als virtuellen Dienst via der IP Adresse 192.168.0.174 an, so dass die Web Server Cluster Systeme nur einen NFS server sehen.
Zuerst installieren wir heartbeat:
server1/server2:
apt-get install heartbeat
Nun müssen wir drei Konfigurationsdateien für heartbeat erstellen. Sie müssen auf server1 und server2 identisch sein!
server1/server2:
/etc/heartbeat/ha.cf:
logfacility local0 keepalive 2 #deadtime 30 # USE THIS!!! deadtime 10 bcast eth0 node server1 server2 |
Als Systemnamen müssen wir die Ausgabe von uname -n auf server1 und server2 verwenden.
server1/server2:
/etc/heartbeat/haresources:
server1 IPaddr::192.168.0.174/24/eth0 drbddisk::r0 Filesystem::/dev/drbd0::/data::ext3 nfs-kernel-server |
Das erste Wort ist die Ausgabe von uname -n auf server1, egal ob Du die Datei auf server1 oder server2 erstellst! Nach IPaddr setzen wir unsere virtuelle IP Adresse 192.168.0.174 ein und nach drbddisk verwenden wir den Resource Namen unserer DRBD Resource, was hier r0 ist (denke daran, das ist der Resource Name, den wir /etc/drbd.conf verwenden – wenn Du einen anderen verwendest, musst Du ihn auch hier verwenden).
server1/server2:
/etc/heartbeat/authkeys:
auth 3 3 md5 somerandomstring |
somerandomstring ist ein Password, den die beiden heartbeat Daemons auf server1 und server2 verwenden, um sich gegenseitig zu authentifizieren. Verwende hier Deine eigenen Zeichenfolge. Du hast die Wahl zwischen drei Authentifizierungsmechanismen. Ich verwende md5, da es der sicherste ist.
/etc/heartbeat/authkeys sollte nur von Root gelesen werden können, daher führen wir dies aus:
server1/server2:
chmod 600 /etc/heartbeat/authkeys
Schließlich starten wir DRBD und heartbeat auf server1 und server2:
server1/server2:
/etc/init.d/drbd start
/etc/init.d/heartbeat start
9 Erste Tests
Jetzt können wir unsere ersten Tests durchführen. Führe auf server1 dies aus
server1:
ifconfig
In der Ausgabe sollte die virtuelle IP Adresse 192.168.0.174 auftauchen:
eth0 Link encap:Ethernet HWaddr 00:0C:29:A1:C5:9B inet addr:192.168.0.172 Bcast:192.168.0.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:fea1:c59b/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:18992 errors:0 dropped:0 overruns:0 frame:0 TX packets:24816 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:2735887 (2.6 MiB) TX bytes:28119087 (26.8 MiB) Interrupt:177 Base address:0x1400 eth0:0 Link encap:Ethernet HWaddr 00:0C:29:A1:C5:9B inet addr:192.168.0.174 Bcast:192.168.0.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 Interrupt:177 Base address:0x1400 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:71 errors:0 dropped:0 overruns:0 frame:0 TX packets:71 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:5178 (5.0 KiB) TX bytes:5178 (5.0 KiB) |
Führe auch dies
server1:
df -h
auf server1 aus. Du müsstest dort nun /data aufgelistet sehen:
Filesystem Size Used Avail Use% Mounted on /dev/sda5 4.6G 430M 4.0G 10% / tmpfs 126M 0 126M 0% /dev/shm /dev/sda1 89M 11M 74M 13% /boot /dev/drbd0 24G 33M 23G 1% /data |
Wenn Du das Gleiche
server2:
ifconfig
df -h
auf server2 ausführst, solltest Du 192.168.0.174 und /data nicht sehen können.
Nun erstellen wir eine Testdatei in /data/export auf server1 und simulieren dann das Ausfallen von server1 (indem wir heartbeat stoppen):
server1:
touch /data/export/test1
/etc/init.d/heartbeat stop
Wenn Du nun ifconfig und df -h auf server2 ausführst, solltest Du die IP Adresse 192.168.0.174 und die /data Partition sehen, und
server2:
ls -l /data/export
sollte die Datei test1 auflisten, die Du zuvor auf server1 erstellt hast. Sie wurde also auf server2 gespiegelt!
Nun erstellen wir eine andere Testdatei auf server2 und überprüfen, ob sie auf server1 gespiegelt wird, wenn er wieder funktionstüchtig ist:
server2:
touch /data/export/test2
server1:
/etc/init.d/heartbeat start
(Wait a few seconds.)
ifconfig
df -h
ls -l /data/export
Du müsstest 192.168.0.174 und /data wieder auf server1 sehen, was bedeutet, dass er wieder übernommen hat (da wir ihn als ersten Server definiert haben). Außerdem solltest Du die Datei /data/export/test2 sehen!
10 Konfiguration des NFS Clients
Nun installieren wir NFS auf unserem Client (192.168.0.100):
apt-get install nfs-common
Als Nächstes erstellen wir das /data Verzeichnis und mounten unsere NFS Freigabe darin:
mkdir /data
mount 192.168.0.174:/data/export /data
192.168.0.174 ist die virtuelle IP Adresse, die wir zuvor konfiguriert haben. Du musst sicher gehen, dass der Forward und der Reverse DNS Record für client.example.com übereinstimmen, sonst erhältst Du eine „Permission denied“ Fehlermeldung auf dem Client und auf dem Server findest Du dies in /var/log/syslog:
#Mar 2 04:19:09 localhost rpc.mountd: Fake hostname localhost for 192.168.0.100 - forward lookup doesn't match reverse |
Wenn Du keine entsprechenden DNS Records hast (oder für Dein lokales Netzwerk keinen DNS Server hast), musst Du dies nun ändern, sonst kannst Du die NFS Freigabe nicht mounten!
Wenn es funktioniert kannst Du nun weitere Testdateien in /data auf dem Client erstellen, dann den Ausfall von server1 und server2 simulieren (aber nicht beide zur gleichen Zeit!) und überprüfen, ob die Testdateien repliziert werden. Auf dem Client solltest Du überhaupt nicht bemerken, dass server1 oder server2 ausgefallen ist – die Daten im /data Verzeichnis sollten immer verfügbar sein (es sei denn server1 und server2 fallen zur gleichen Zeit aus…).
Um das /data Verzeichnis zu unmounten, führe dies aus
umount /data
Wenn die NFS Freigabe beim Hochfahren automatisch gemounted werden soll, setze folgend Zeile in /etc/fstab:
192.168.0.174:/data/export /data nfs rw 0 0 |
Links
- NFS: http://nfs.sourceforge.net
- DRBD: http://www.drbd.org
- heartbeat / The High-Availability Linux Project: http://linux-ha.org
- The Linux Virtual Server Project: http://www.linuxvirtualserver.org