Wie man ein hochverfügbares Apache Cluster (inkl. Loadbalancer) aufsetzt

Version 1.0
Author: Falko Timme

Diese Anleitung veranschaulicht, wie man ein Apache Web Server Cluster, bestehend aus zwei Systemen aufsetzt, das hochverfügbar ist. Vor dem Apache Cluster erstellen wir einen Load Balancer, der eingehende Anfragen auf die beiden Apache Systeme aufteilt. Da wir nicht wollen, dass der Load Balancer ein weiterer "Single Point Of Failure" wird, müssen wir auch für den Load Balancer eine Hochverfügbarkeit bereitstellen. Daher wird unser Load Balancer tatsächlich aus zwei Load Balancer Systemen bestehen, die sich gegenseitig mittels heartbeat überwachen. Wenn ein Load Balancer ausfällt,  übernimmt der anders stillschweigend.

Der Vorteil gegenüber dem Load Balancer im Vergleich zu round robin DNS besteht darin, dass er auf die Last auf den Web Server Systemen aufpasst und versucht, Anfragen an das System mit der niedrigsten Last zu leiten. Weiterhin passt er auf Verbindungen/Sitzungen auf. Viele Web Anwendungen (z.B. Forum Software, Einkaufswagen, etc.) machen von Sessions Gebrauch. Wenn Du Dich in einer Session auf dem Apache System 1 befindest, würdest Du dieses Session verlieren, wenn System 2 plötzlich Deine Anfragen bedienen würde. Falls eines der Apache Systeme ausfällt, bermerkt das der Load Balancer und leitet alle eingehende Anfragen an das anders System weiter, was mit round robin DNS nicht möglich wäre.

Für dieses Setup benötigen wir vier Systeme (zwei Apache Systeme und zwei Load Balancer Systeme) und fünf IP Adressen: Eine für jedes System und eine virtuelle IP Adresse, die sich die Load Balancer Systeme teilen und die für eingehende HTTP Anfragen verwendet wird.

Ich werde folgendes Setup verwenden:

  • Apache System 1: webserver1.example.com (webserver1) - IP Adresse: 192.168.0.101; Apache Dokumenten-Root: /var/www
  • Apache System 2: webserver2.example.com (webserver2) - IP Adresse: 192.168.0.102; Apache Dokumenten-Root: /var/www
  • Load Balancer System 1: loadb1.example.com (loadb1) - IP Adresse: 192.168.0.103
  • Load Balancer System 2: loadb2.example.com (loadb2) - IP Adresse: 192.168.0.104
  • Virtuelle IP Adresse: 192.168.0.105 (für eingehende Anfragen)

Sieh Dir die Zeichnung http://www.linuxvirtualserver.org/docs/ha/ultramonkey.html an um nachvollziehen zu können, wie dieses Setup aussieht.

In dieser Anleitung werde ich für alle vier Systeme Debian Sarge verwenden. Ich gehe davon aus, dass Du auf allen vier Systemen Debian grundinstalliert hast und dass Du Apache auf webserver1 und webserver2 mit /var/www als Dokumenten-Root der Haupt-Webseite installiert hast.

Ich möchte darauf hinweisen, dass dies nicht der einzige Weg ist, ein solches System einzurichten. 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 IPVS auf den Load Balancern aktivieren

Zuerst müssen wir IPVS auf unseren Load Balancern aktivieren. IPVS (IP Virtual Server) implementiert transport-layer load balancing im Linux Kernel, sogenanntes Layer-4 switching.

loadb1/loadb2:

echo ip_vs_dh >> /etc/modules
echo ip_vs_ftp >> /etc/modules
echo ip_vs >> /etc/modules
echo ip_vs_lblc >> /etc/modules
echo ip_vs_lblcr >> /etc/modules
echo ip_vs_lc >> /etc/modules
echo ip_vs_nq >> /etc/modules
echo ip_vs_rr >> /etc/modules
echo ip_vs_sed >> /etc/modules
echo ip_vs_sh >> /etc/modules
echo ip_vs_wlc >> /etc/modules
echo ip_vs_wrr >> /etc/modules

Dann führen wir dies aus:

loadb1/loadb2:

modprobe ip_vs_dh
modprobe ip_vs_ftp
modprobe ip_vs
modprobe ip_vs_lblc
modprobe ip_vs_lblcr
modprobe ip_vs_lc
modprobe ip_vs_nq
modprobe ip_vs_rr
modprobe ip_vs_sed
modprobe ip_vs_sh
modprobe ip_vs_wlc
modprobe ip_vs_wrr

Wenn Du Fehlermeldungen erhältst,  dann wurde Dein Kernel vermutlich nicht mit IPVS Untertsützung kompiliert, also musst Du jetzt einen neuen Kernel mit IPVS Unterstützung kompilieren (oder ein Kernel Image mit IPVS Unterstützung installieren).

2 Installation von Ultra Monkey auf den Load Balancern

Mit dem Ultra Monkey Projekt kann man Load balanced und hoch-verfügbare Dienste auf einem lokalen Area Netzwerk mit Open Source Komponenten auf dem Linux Betriebssystem erstellen; das Ultra Monkey Paket stellt heartbeat (wird von den beiden Load Balancern verwendet um sich gegenseitig zu überwachen und zu überprüfen ob das anders System noch da ist) und ldirectord bereit, den eigentlichen Load Balancer.

Um Ultra Monkey zu installieren, müssen wir  /etc/apt/sources.list bearbeiten und diese beiden Zeilen (entferne nicht die anderen Paketdatenbanken) hinzufügen:

loadb1/loadb2:

vi /etc/apt/sources.list

 

deb http://www.ultramonkey.org/download/3/ sarge main
deb-src http://www.ultramonkey.org/download/3 sarge main
Danach führen wir dies aus:

loadb1/loadb2:

apt-get update

und installieren Ultra Monkey:

loadb1/loadb2:

apt-get install ultramonkey

Wenn diese Warnung auftaucht:
  ¦ libsensors3 not functional                                               ¦
¦ ¦ ¦ It appears that your kernel is not compiled with sensors support. As a ¦ ¦ result, libsensors3 will not be functional on your system. ¦ ¦ ¦ ¦ If you want to enable it, have a look at "I2C Hardware Sensors Chip ¦ ¦ support" in your kernel configuration. ¦
kannst Du sie ignorieren.

Während der Ultra Monkey Installation werden Dir ein paar Fragen gestellt. Antworte wie folgt:

Do you want to automatically load IPVS rules on boot?
No
Select a daemon method.
none

3 Paket-Weiterleitung auf den Load Balancern aktivieren

Die Load Balancer müssen in der Lage sein, Datenverkehr zu den Apache Systemen zu leiten. Dafür müssen wir die Paket-Weiterleitung auf den Load Balancern aktivieren. Füge folgende Zeilen /etc/sysctl.conf hinzu:

loadb1/loadb2:

vi /etc/sysctl.conf


# Enables packet forwarding
net.ipv4.ip_forward = 1
Führe dann dies aus:

loadb1/loadb2:

sysctl -p


4 Konfiguriere heartbeat und ldirectord

Nun müssen wir drei Konfigurationsdateien für heartbeat erstellen. Sie müssen auf loadb1 und loadb2 identisch sein!

loadb1/loadb2:

vi /etc/ha.d/ha.cf


logfacility        local0
bcast eth0 # Linux mcast eth0 225.0.0.1 694 1 0 auto_failback off node loadb1 node loadb2 respawn hacluster /usr/lib/heartbeat/ipfail apiauth ipfail gid=haclient uid=hacluster
Wichtig: Als Systemnamen müssen wir die Ausgabe von

uname -n

auf loadb1 und loadb2 verwenden.

loadb1/loadb2:

vi /etc/ha.d/haresources


loadb1
ldirectord::ldirectord.cf LVSSyncDaemonSwap::master IPaddr2::192.168.0.105/24/eth0/192.168.0.255
Das erste Wort ist die Ausgabe von

uname -n

auf loadb1, egal ob Du die Datei auf loadb1 oder loadb2 erstellst! Nach IPaddr2 fügen wir unsere virtuelle IP Adresse 192.168.0.105 ein.

loadb1/loadb2:

vi /etc/ha.d/authkeys


auth 3
3 md5 somerandomstring
somerandomstring ist ein Passwort, das die beiden heartbeat Daemons auf loadb1 und loadb2 verwenden, um sich gegeneinander zu authentifizieren. Verwende hier Deine eigene Zeichenfolge. Du hast die Wahl zwischen drei Authentifizierungsmechanismen. Ich verwende md5 da es der sicherste ist.

/etc/ha.d/authkeys sollte nur vom Root-Benutzer gelesen werden können, daher führen wir dies aus:

loadb1/loadb2:

chmod 600 /etc/ha.d/authkeys

ldirectord ist der eigentliche Load Balancer. Wir werden unsere beiden Load Balancer (loadb1.example.com und loadb2.example.com) in einem aktiven/passiven Setup konfigurieren, was bedeutet, dass wir einen aktiven Load Balancer haben, der andere ist ein Hot-standby und wird dann aktiv, wenn der aktive Load Balancer ausfällt. Damit dies funktioniert müssen wir die ldirectord Konfigurationsdatei /etc/ha.d/ldirectord.cf erstellen, die auch wieder auf loadb1 und loadb2 identisch sein muss.


loadb1/loadb2:

vi /etc/ha.d/ldirectord.cf


checktimeout=10
checkinterval=2 autoreload=no logfile="local0" quiescent=yes virtual=192.168.0.105:80 real=192.168.0.101:80 gate real=192.168.0.102:80 gate fallback=127.0.0.1:80 gate service=http request="ldirector.html" receive="Test Page" scheduler=rr protocol=tcp checktype=negotiate
In die virtual= Zeile fügen wir unsere virtuelle IP Adresse (192.168.0.105 in diesem Beispiel) ein und in den real= Zeilen listen wir die IP Adressen unserer Apache Systeme (192.168.0.101 und 192.168.0.102 in diesem Beispiel) auf. In der request= Zeile listen wir den Namen einer Datei auf  webserver1 und webserver2 auf, die ldirectord wiederholt anfragen wird um herauszufinden, ob  webserver1 und webserver2 noch da sind. Diese Datei (die wir später erstellen werden) muss die Zeichenfolge, die in der receive= Zeile aufgelistet ist, beinhalten.

Danach erstellen wir die System Startup Links für heartbeat und entfernen diese von ldirectord da ldirectord vom  heartbeat Daemon gestartet wird:

loadb1/loadb2:

update-rc.d heartbeat start 75 2 3 4 5 . stop 05 0 1 6 .
update-rc.d -f ldirectord remove

Schließlich starten wir heartbeat (und damit auch ldirectord):

loadb1/loadb2:

/etc/init.d/ldirectord stop
/etc/init.d/heartbeat start

5 Die Load Balancer testen

Lass uns überprüfen, ob beide Load Balancer wie erwartet funktionieren:

loadb1/loadb2:

ip addr sh eth0

Der aktive Load Balancer sollte die virtuelle IP Adresse (192.168.0.105) auflisten:

2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:16:3e:40:18:e5 brd ff:ff:ff:ff:ff:ff inet 192.168.0.103/24 brd 192.168.0.255 scope global eth0 inet 192.168.0.105/24 brd 192.168.0.255 scope global secondary eth0
Der Hot-standby sollte dies anzeigen:
2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:16:3e:50:e3:3a brd ff:ff:ff:ff:ff:ff inet 192.168.0.104/24 brd 192.168.0.255 scope global eth0
loadb1/loadb2:

ldirectord ldirectord.cf status

Ausgabe auf dem aktiven Load Balancer:
ldirectord for /etc/ha.d/ldirectord.cf is running with pid: 1455
Ausgabe auf dem Hot-standby:
ldirectord is stopped for /etc/ha.d/ldirectord.cf
loadb1/loadb2:

ipvsadm -L -n

Ausgabe auf dem aktiven Load Balancer:
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.0.105:80 rr -> 192.168.0.101:80 Route 0 0 0 -> 192.168.0.102:80 Route 0 0 0 -> 127.0.0.1:80 Local 1 0 0
Ausgabe auf dem Hot-standby:
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn
loadb1/loadb2:

/etc/ha.d/resource.d/LVSSyncDaemonSwap master status

Ausgabe auf dem aktiven Load Balancer:
master running
(ipvs_syncmaster pid: 1591)
Ausgabe auf dem Hot-standby:
master stopped
Wenn Deine Tests gut gelaufen sind, kannst Du nun weiter machen und die beiden Apache Systeme konfigurieren.

6 Konfiguriere die beiden Apache Systeme

Letztendlich müssen wir unsere Apache Cluster Systeme webserver1.example.com und webserver2.example.com konfigurieren, um Anfragen auf der virtuellen IP Adresse 192.168.0.105  zu akzeptieren.

webserver1/webserver2:

apt-get install iproute

Füge Folgendes /etc/sysctl.conf hinzu:

webserver1/webserver2:

vi /etc/sysctl.conf


# Enable configuration of arp_ignore option
net.ipv4.conf.all.arp_ignore = 1 # When an arp request is received on eth0, only respond if that address is # configured on eth0. In particular, do not respond if the address is # configured on lo net.ipv4.conf.eth0.arp_ignore = 1 # Ditto for eth1, add for all ARPing interfaces #net.ipv4.conf.eth1.arp_ignore = 1 # Enable configuration of arp_announce option net.ipv4.conf.all.arp_announce = 2 # When making an ARP request sent through eth0 Always use an address that # is configured on eth0 as the source address of the ARP request. If this # is not set, and packets are being sent out eth0 for an address that is on # lo, and an arp request is required, then the address on lo will be used. # As the source IP address of arp requests is entered into the ARP cache on # the destination, it has the effect of announcing this address. This is # not desirable in this case as adresses on lo on the real-servers should # be announced only by the linux-director. net.ipv4.conf.eth0.arp_announce = 2 # Ditto for eth1, add for all ARPing interfaces #net.ipv4.conf.eth1.arp_announce = 2
Führe dann dies aus:

webserver1/webserver2:

sysctl -p

Füge diesen Bereich für die virtuelle IP Adresse /etc/network/interfaces hinzu:

webserver1/webserver2:

vi /etc/network/interfaces


auto lo:0
iface lo:0 inet static address 192.168.0.105 netmask 255.255.255.255 pre-up sysctl -p > /dev/null
Führe dann dies aus:

webserver1/webserver2:

ifup lo:0

Zum Schluss müssen wir die Datei ldirector.html erstellen. Diese Datei wird wiederholt von den beiden Load Balancer Systemen angefragt, damit sie sehen können, ob die beiden Apache Systeme noch funktionsfähig sind. Ich gehe davon aus, dass der Dokumenten-Root der Haupt-Webseite von Apache auf webserver1 und webserver2  /var/www ist, daher erstellen wir die Datei /var/www/ldirector.html:

webserver1/webserver2:

vi /var/www/ldirector.html


Test Page

7 Weitere Tests

Nun kannst Du auf die Webseite zugreifen, die von den beiden Apache Systemen gehostet wird indem Du http://192.168.0.105 in Deinem Browser eingibst.

Unterbreche nun Apache entweder auf webserver1 oder webserver2. Du solltest die Webseite dann immer noch auf http://192.168.0.105 sehen können, da der Load Balancer Anfragen an das laufende Apache System leitet. Wenn Du natürlich beide Apaches unterbrichst, wird die Anfrage fehlschlagen.

Gehen wir nun davon aus, dass loadb1 unser aktiver Load Balancer und loadb2 der Hot-standby ist. Unterbrich nun  heartbeat auf loadb1:

loadb1:

/etc/init.d/heartbeat stop

Warte ein paar Sekunden und versuche dann http://192.168.0.105 wieder in Deinem Browser. Du müsstest immer noch Deine Webseite sehen können, da loadb2 nun die aktive Rolle übernommen hat.

Starte heartbeat nun erneut auf loadb1:

loadb1:

/etc/init.d/heartbeat start

loadb2 sollte immer noch die aktive Rolle haben. Wiederhole die Schritte von Kapitel 5 auf loadb1 und loadb2 und Du müsstest die umgekehrten Ergebisse wie zuvor sehen.

Wenn Du auch diese Tests bestanden hast, funktioniert Dein oadbalanced Apache Cluster wie erwartet. Viel Spaß!

8 Zusätzliche Lektüre

Diese Anleitung veranschaulicht, wie man zwei Apache Systeme loadbalanced. Es zeigt nicht, wie man die Dateien im Apache Dokumenten-Root in sync hält oder wie man einen Datenspeicher wie einen NFS Server erstellt, den beide Apache Systeme verwenden können. Sie bietet auch keinen Lösungsweg, wie man seine MySQL Datenbank(en) verwaltet. Du findest Lösungen für diese Probleme hier:

9 Links