Aufsetzen eines hochverfügbaren Load Balancers (mit Failover und Session Support) mit HAProxy/Heartbeat auf Fedora 8

Version 1.0
Author: Oliver Meyer <o [dot] meyer [at] projektfarm [dot] de>


Diese Anleitung erklärt, wie man einen Load Balancer (bestehend aus zwei Systemen) in einer aktiven/passiven Konfiguration mit HAProxy und heartbeat auf Fedora 8 aufsetzt. Der Load Balancer sitzt zwischen dem Benutzer und zwei (oder mehreren) Apache Web Servern, die den gleichen Inhalt aufweisen. Der Load Balancer verteilt die Anfragen an die Web Server und überprüft ihren Zustand. Wenn einer von ihnen ausfällt, werden alle Anfragen automatisch zum verbleibenden Web Server(n) umgeleitet. Zusätzlich überwachen die beiden Load Balancer-Systeme sich gegenseitig unter Verwendung von heartbeat. Wenn der Master ausfällt, wird der Slave zum Master, was bedeutet, dass dass der Benutzer keinerlei Störungen des Dienstes bemerken wird. HAProxy unterstützt Sessions, das heißt, Du kannst es mit jedem Web Programm verwenden, das Sessions in Anspruch nimmt (wie zum Beispiel Foren, Warenkörbe etc.).

Von der HAProxy Webseite: "HAProxy is a free, very fast and reliable solution offering high availability, load balancing, and proxying for TCP and HTTP-based applications. It is particularly suited for web sites crawling under very high loads while needing persistence or Layer7 processing. Supporting tens of thousands of connections is clearly realistic with todays hardware. Its mode of operation makes its integration into existing architectures very easy and riskless, while still offering the possibility not to expose fragile web servers to the Net."

Diese Anleitung ist ein praktischer Leitfaden ohne jegliche Garantie - theoretisches Hintergrundwissen wird nicht abgedeckt. Es gibt viele Möglichkeiten ein solches System einzurichten - dies ist der Weg, den ich gewählt habe.

1 Vorbereitung

Für diese Anleitung habe ich vier Fedora 8 Systeme (minimale Installation ohne gui etc.) mit folgender Konfiguration eingerichtet.

1.1 Load Balancer 1

Hostname: lb1.example.com
IP: 192.168.0.110
Shared IP: 192.168.0.120

1.2 Load Balancer 1

Hostname: lb2.example.com
IP: 192.168.0.111
Shared IP: 192.168.0.120

1.3 Web Server 1

Hostname: http1.example.com
IP: 192.168.0.112

1.4 Web Server 2

Hostname: http2.example.com
IP: 192.168.0.113

1.5 Überblick

+-----------------+
| 192.168.0.120 |
| Shared IP |
+--------+--------+
|
+----------------------+
| |
+--------+--------+ +--------+--------+
| 192.168.0.110 | | 192.168.0.111 |
| Load Balancer 1 | | Load Balancer 2 |
+--------+--------+ +--------+--------+

+--------+--------+ +--------+--------+
| 192.168.0.112 | | 192.168.0.113 |
| Web Server 1 | | Web Server 2 |
+-----------------+ +-----------------+

2 HTTP1 & HTTP2

2.1 Firewall Konfiguration

Damit auf die Web Server von außen zugegriffen werden kann, musst Du die entsprechenden Ports auf beiden Web Servern öffnen.

system-config-firewall-tui


Setze HTTP & HTTPS als vertrauenswürdigen Dienst, wie auf dem unteren Screenshot gezeigt und speichere die Einstellungen.


2.2 Apache Konfiguration

HAProxy arbeitet als transparenter Proxy - das heißt es wird die IP Adresse des Benutzers in einem Feld namens "X-Forwarded-For" zu den Web Servern leiten. Damit die Web Server die IP Adresse des Benutzers und nicht die IP Adressen der Load Balancer in den Log-Dateien speichern, müssen wir das Log Format in der Apache Konfigurationsdatei auf beiden Servern bearbeiten.

vi /etc/httpd/conf/httpd.conf

Suche nach den Zeilen, die mit "LogFormat" beginnen ...
[...]
LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined LogFormat "%h %l %u %t "%r" %>s %b" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent [...]
... und ersetze "%h" mit "%{X-Forwarded-For}i". Der Inhalt sollte wie folgt aussehen:
[...]
LogFormat "%{X-Forwarded-For}i %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined LogFormat "%{X-Forwarded-For}i %l %u %t "%r" %>s %b" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent [...]
Wir werden HAProxy so konfigurieren, dass es den Zustand des Web Servers überprüft indem es kontinuierlich die Datei "check.txt" der Web Server abruft. Um die Log-Dateien klein zu halgen, passen wir den ersten vhost auf jedem Web Server an (HAProxy wird die IP Adressen der Web Server nutzen, um die Datei abzurufen - also wird der erste vhost auf die Anfrage reagieren) um sicher zu gehen, dass der Zugriff auf "check.txt" nicht gelogged wird. In diesem Beispiel werden die vhosts konfiguriert in "/etc/httpd/conf.d/vhosts.conf".

Füge folgende Zeile der Konfiguration Deines ersten vhosts hinzu ...

SetEnvIf Request_URI "^/check.txt$" dontlog

... und füge die Ausnahme (env=!dontlog) der Zeile für das CustomLog hinzu. Zum Beispiel könnte die Konfiguration für den ersten vhost wie folgt aussehen:
NameVirtualHost 192.168.0.112:80
<VirtualHost 192.168.0.112:80>
ServerName health.example.com ServerAdmin admin@example.com DocumentRoot /var/www/haproxy SetEnvIf Request_URI "^/check.txt$" dontlog LogLevel warn ErrorLog /var/log/httpd/vhost_error.log CustomLog /var/log/httpd/vhost_access.log combined env=!dontlog </VirtualHost>
Nun müssen wir die Datei "check.txt" (diese Datei kann leer sein) innerhalb des Dokumenten-Roots des ersten vhosts erstellen.

touch /var/www/haproxy/check.txt

Danach ist die Konfiguration der Web Server abgeschlossen - starte die Web Server neu.

/etc/init.d/httpd restart


3 LB1 & LB2

3.1 Firewall Konfiguration

Damit HTTP & HTTPS Verbindungen an die Web Server weitergeleitet werden können und die heartbeat daemons mit einander kommunizieren können, musst Du die entsprechenden Ports auf beiden Load Balancern öffnen.

system-config-firewall-tui


Setze HTTP & HTTPS als vertrauenswürdigen Dienst und gib das heartbeat-port (694 udp) in das Feld "Andere Ports" ein, wie unten gezeigt wird. Speichere danach die Einstellungen.



3.2 Benötigte Pakete auf beiden Load Balancern

Installiere die benötigten Pakete via:

yum -y install haproxy heartbeat


3.3 HAProxy Konfiguration

cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg_orig
cat /dev/null > /etc/haproxy/haproxy.cfg
vi /etc/haproxy/haproxy.cfg

Der Inhalt sollte auf beiden Load Balancern wie folgt aussehen.

global
log 127.0.0.1 local0 log 127.0.0.1 local1 notice #log loghost local0 info maxconn 4096 #debug #quiet user haproxy group haproxy
defaults
log global mode http option httplog option dontlognull retries 3 redispatch maxconn 2000 contimeout 5000 clitimeout 50000 srvtimeout 50000
listen webfarm 192.168.0.120:80
mode http stats enable stats auth someuser:somepassword balance roundrobin cookie JSESSIONID prefix option httpclose option forwardfor option httpchk HEAD /check.txt HTTP/1.0 server webA 192.168.0.112:80 cookie A check server webB 192.168.0.113:80 cookie B check
Merke: Wenn Du mehr über die verfügbaren Optionen der HAProxy Konfiguration erfahren möchtest, sieh Dir Folgendes an: http://haproxy.1wt.eu/download/1.3/doc/haproxy-en.txt und http://haproxy.1wt.eu/download/1.2/doc/architecture.txt.

3.4 Heartbeat Konfiguration

3.4.1 Auf beiden Load Balancern

Heartbeat wird LB1 & LB2 mitteilen, dass sie auf der shared IP (192.168.0.120) hören sollen. Zunächst müssen wir HAProxy erlauben, sich an die shared IP zu binden.

vi /etc/sysctl.conf

Füge folgende Zeilen der Datei hinzu ...

# Allow HAProxy shared IP
net.ipv4.ip_nonlocal_bind = 1

... und führe dies aus:

sysctl -p

Nun müssen wir drei Konfigurationsdateien für heartbeat erstellen.

vi /etc/ha.d/authkeys

Der Ihnalt sollte wie folgt aussehen - ersetze %auth_password% mit einem Passwort Deiner Wahl. Die heartbeat daemons auf beiden Load Balancern werden dieses Passwort verwenden um sich gegenseitig zu authentifizieren (es sollte also ein sehr sicheres Passwort sein).
auth 3
3 md5 %authpassword%
Ändere die Rechte, sodass nur der Root-Benutzer Zugriff auf die Datei hat.

chmod 600 /etc/ha.d/authkeys

vi /etc/ha.d/haresources

Der Inhalt sollte wie folgt aussehen (auf beiden Load Balancern!) - das erste Wort ist die Ausgabe von

uname -n

auf Load Balancer 1.
lb1.example.com 192.168.0.120

3.4.2 Auf Load Balancer 1 (LB1)

vi /etc/ha.d/ha.cf

Der Inhalt sollte wie folgt aussehen - die letzten beiden Zeilen beinhalten die Ausgabe von "uname -n" von beiden Load Balancern!:
#
# keepalive: how many seconds between heartbeats # keepalive 2 # # deadtime: seconds-to-declare-host-dead # deadtime 10 # # What UDP port to use for udp or ppp-udp communication? # udpport 694 bcast eth0 mcast eth0 225.0.0.1 694 1 0 ucast eth0 192.168.0.111 # What interfaces to heartbeat over? udp eth0 # # Facility to use for syslog()/logger (alternative to log/debugfile) # logfacility local0 # # Tell what machines are in the cluster # node nodename ... -- must match uname -n node lb1.example.com node lb2.example.com

3.4.3 Auf Load Balancer 2 (LB2)

vi /etc/ha.d/ha.cf

Der Inhalt sollte wie folgt aussehen - die letzten beiden Zeilen beinhalten die Ausgabe von "uname -n" von beiden Load Balancern!:
#
# keepalive: how many seconds between heartbeats # keepalive 2 # # deadtime: seconds-to-declare-host-dead # deadtime 10 # # What UDP port to use for udp or ppp-udp communication? # udpport 694 bcast eth0 mcast eth0 225.0.0.1 694 1 0 ucast eth0 192.168.0.110 # What interfaces to heartbeat over? udp eth0 # # Facility to use for syslog()/logger (alternative to log/debugfile) # logfacility local0 # # Tell what machines are in the cluster # node nodename ... -- must match uname -n node lb1.example.com node lb2.example.com
Starte danach heartbeat auf beiden Load Balancern.

/etc/init.d/heartbeat start


3.4.4 Überprüfe Heartbeat auf LB1

Wenn alles gut gegangen ist, sollte die Ausgabe von ...

ip addr sh eth0

... auch die shared IP enthalten - es ist der aktive Load Balancer.

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:02:ae:eb brd ff:ff:ff:ff:ff:ff
inet 192.168.0.110/24 brd 192.168.0.255 scope global eth0
inet 192.168.0.120/24 brd 192.168.0.255 scope global secondary eth0:0
inet6 fe80::20c:29ff:fe02:aeeb/64 scope link
valid_lft forever preferred_lft forever

3.4.5 Überprüfe Heartbeat auf LB2

Wenn alles gut gegangen ist, sollte die Ausgabe von ...

ip addr sh eth0

... die shared IP nicht enthalten, solange Load Balancer 1 aufgesetzt ist - es ist der passive Load Balancer.

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:e6:66:18 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.111/24 brd 192.168.0.255 scope global eth1
inet6 fe80::20c:29ff:fee6:6618/64 scope link
valid_lft forever preferred_lft forever

Nun können wir HAProxy dem autostart hinzufügen und HAProxy auf beiden Load Balancern starten.

chkconfig --level 3 haproxy on
/etc/init.d/haproxy start

4 Test

4.1 Web Server

Schalte einen der beiden Web Server aus und nimm eine HTTP Anfrage an die shared IP 192.168.0.120 (oder jede andere Domain oder Hostnamen, die/der auf die shared IP gerichtet ist) vor - Du müsstest den Inhalt des verbleibenden Web Servers erhalten.

4.2 Load Balancer

Schalte den aktiven Load Balancer (LB1) aus - der passive Load Balancer (LB2) sollte sofort übernehmen. Die Ausgabe von ...

ip addr sh eth0

... auf dem zweiten Load Balancer (LB) sollte nun auch die shared IP enthalten.

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:e6:66:18 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.111/24 brd 192.168.0.255 scope global eth1
inet 192.168.0.120/24 brd 192.168.0.255 scope global secondary eth1:0
inet6 fe80::20c:29ff:fee6:6618/64 scope link
valid_lft forever preferred_lft forever

Wenn der erste Load Balancer (LB1) wieder an ist, wird er wieder die aktive Rolle übernehmen.

5 HAProxy Statistiken

HAProxy bietet ein Webinterface für Statistiken. Du kannst via http://192.168.0.120/haproxy?stats in einem Browser Deiner Wahl darauf zugreifen. Melde Dich mit den Daten, die Du in der HAProxy Konfigurationsdatei konfiguriert hast (in diesem Beispiel kannst Du Dich mit dem Benutzernamen "someuser" und dem Passwort "somepassword" anmelden (beide ohne Anführungszeichen)), an. Wenn Du keine Statistiken möchtest/benötigst, entferne einfach die Zeilen in den HAProxy Konfigurationsdateien auf beiden Load Balancern, die mit "stats" beginnen.

6 Links