Aufsetzen Eines Hochverfügbaren Load Balancers (Mit Failover und Session Support) Mit Pound Auf Debian Etch

Version 1.0
Author: Falko Timme


Diese Anleitung erklärt, wie man einen Load Balancer (bestehend aus zwei Systemen) in einer aktiven/passiven Konfiguration mit Pound und keepalived auf Debian Etch aufsetzt. Der Load Balancer sitzt zwischen dem Benutzer und zwei (oder mehreren) backend Apache Web Servern, die den gleichen Inhalt aufweisen. Der Load Balancer verteilt nicht nur Anfragen an die beiden backend Apache Servers, sondern überprüft auch den Zustand des backend Servers. Wenn einer von ihnen ausfällt, werden alle Anfragen automatisch zum verbleibenden backend Server umgeleitet. Zusätzlich überwachen die beiden Load Balancer-Systeme sich gegenseitig unter Verwendung von keepalived. Wenn der Master ausfällt, wird der Slave zum Master, was bedeutet, dass der Benutzer keinerlei Störungen des Dienstes bemerken wird. Pound 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 Pound Web Site: " The Pound program is a reverse proxy, load balancer and HTTPS front-end for Web server(s). Pound was developed to enable distributing the load among several Web-servers and to allow for a convenient SSL wrapper for those Web servers that do not offer it natively. Pound is distributed under the GPL - no warranty, it's free to use, copy and give away. "
Ich übernehme keine Garantie, dass dies auch bei Dir funktionieren wird!

1 Vorbemerkung

In dieser Anleitung werde ich folgende Hosts verwenden:
  • Load Balancer 1: lb1.example.com, IP address: 192.168.0.100
  • Load Balancer 2: lb2.example.com, IP address: 192.168.0.101
  • Web Server 1: http1.example.com, IP address: 192.168.0.102
  • Web Server 2: http2.example.com, IP address: 192.168.0.103
  • We also need a virtual IP address that floats between lb1 and lb2: 192.168.0.99
Hier ist ein kleines Diagramm, das unser Setup darstellt:

shared IP=192.168.0.99
192.168.0.100 192.168.0.101 192.168.0.102 192.168.0.103
-------+------------+--------------+-----------+----------
| | | |
+--+--+ +--+--+ +----+----+ +----+----+
| lb1 | | lb2 | | http1 | | http2 |
+-----+ +-----+ +---------+ +---------+
pound pound 2 web servers (Apache)
keepalived keepalived

Die freigegebene (virtuelle) IP Adresse stellt kein Problem dar, solange Du Dich in Deinem eigenen LAN befindest, in dem Du IP Adressen zuweisen kannst wie Du magst. Wenn Du dieses Setup allerdings mit öffentlichen IP Adressen verwenden möchtest, musst Du einen Hoster finden, wo Du zwei Server im gleichen Subnetz mieten kannst (die Load Balancer Systeme); dann kannst Du in diesem Subnetz eine freie IP Adresse für die virtuelle IP Adresse verwenden. Hier in Deutschland ist Hetzner ein Hoster, der Dir dies erlaubt.

http1 und http2 sind Standard Debian Etch Apache Setups mit dem Dokumenten-Root /var/www (die Konfiguration dieses Standard vhosts ist abgelegt in /etc/apache2/sites-available/default). Wenn Dein Dokumenten-Root davon abweicht, musst Du diesen Leitfaden etwas anpassen.

Um zu demonstrieren, dass Pound Sessions unterstützt, gehe ich davon aus, dass das Web Programm, das auf http1 und http2 installiert ist, die Session id JSESSIONID verwendet.

2 Die Backend Web Server Vorbereiten

Pound arbeitet als transparenter Proxy, das heißt es wird die originalen IP Adressen des Benutzers in einem Feld namens X-Forwarded-For zu den backend Web Servern leiten. Natürlich sollten die backend Web Server die originalen IP Adressen des Benutzers in ihren Log-Dateien speichern anstatt der IP Adresse des Load Balancers. Dafür musst Du die Zeile LogFormat in der Datei /etc/apache2/apache2.conf %h mit %{X-Forwarded-For}i ersetzen:

http1/http2:

vi /etc/apache2/apache2.conf


[...]
#LogFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined LogFormat "%{X-Forwarded-For}i %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined [...]
Danach starten wir Apache neu:

/etc/init.d/apache2 restart

Mit den Backend Server sind wir bereits fertig; der Rest der Konfigruation erfolgt auf auf den beiden Load Balancer Systemen (nodes).

3 Installation von Pound

Wir können Pound auf unseren beiden Load Balancers wie folgt installieren:

lb1/lb2:

apt-get install pound


4 Konfiguration Der Load Balancers

Die Pound Konfiguration ist abgelegt in der Datei /etc/pound/pound.cfg und ist leicht verständlich.

Wir sichern die originale /etc/pound/pound.cfg Datei und erstellen eine neue wie folgt:

lb1/lb2:

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

## Minimal sample pound.cfg
## ## see pound(8) for details ###################################################################### ## global options: User "www-data" Group "www-data" #RootJail "/chroot/pound" ## Logging: (goes to syslog by default) ## 0 no logging ## 1 normal ## 2 extended ## 3 Apache-style (common log format) LogLevel 1 ## check backend every X secs: Alive 2 ## use hardware-accelleration card supported by openssl(1): #SSLEngine "<hw>" ###################################################################### ## listen, redirect and ... to: ## redirect all requests on port 80 ("ListenHTTP") to the virtual IP address: ListenHTTP Address 192.168.0.99 Port 80 End Service BackEnd Address http1.example.com Port 80 End BackEnd Address http2.exaample.com Port 80 End Session Type Cookie ID "JSESSIONID" TTL 300 END End
Danach setzen wir startup auf 1 in der Datei /etc/default/pound:

vi /etc/default/pound


# Defaults for pound initscript
# sourced by /etc/init.d/pound # installed at /etc/default/pound by the maintainer scripts # prevent startup with default configuration # set the below varible to 1 in order to allow pound to start startup=1

5 Aufsetzen Von keepalived

Wir haben soeben Pound konfiguriert, dass es auf der virtuellen IP Adresse 192.168.0.99 hört, aber jemand muss lb1 und lb2 mitteilen, dass sie auf dieser IP Adresse hören sollen. Dies wird von keepalived erledigt, was wir wie folgt installieren:

lb1/lb2:

apt-get install keepalived

Um Pound zu erlauben, sich mit der freigegebenen IP Adresse zu verbinden, fügen wir folgende Zeile zu /etc/sysctl.conf hinzu:

vi /etc/sysctl.conf


[...]
net.ipv4.ip_nonlocal_bind=1
... und lassen Folgendes laufen:

sysctl -p

Als Nächstes müssen wir keepalived konfigurieren (dies erfolgt mittels der Konfigurationsdatei /etc/keepalived/keepalived.conf). Ich möchte, dass lb1 der Master Load Balancer ist, also verwenden wir folgende Konfiguration auf lb1:

lb1:

vi /etc/keepalived/keepalived.conf


vrrp_script chk_pound {           # Requires keepalived-1.1.13
script "killall -0 pound" # cheaper than pidof interval 2 # check every 2 seconds weight 2 # add 2 points of prio if OK } vrrp_instance VI_1 { interface eth0 state MASTER virtual_router_id 51 priority 101 # 101 on master, 100 on backup virtual_ipaddress { 192.168.0.99 } track_script { chk_pound } }
(Es ist wichtig, dass Du "priority 101" in der obrigen Datei verwendest - somit wird lb1 zum Master!)

Dann starten wir keepalived auf lb1:

lb1:

/etc/init.d/keepalived start

Lass dann dies laufen:

lb1:

ip addr sh eth0

... und Du müsstest feststellen, dass lb1 nun auch auf der freigegebenen IP Adresse hört:

lb1:/etc/keepalived# ip addr sh eth0
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:a5:5b:93 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.100/24 brd 192.168.0.255 scope global eth0
inet 192.168.0.99/32 scope global eth0
inet6 fe80::20c:29ff:fea5:5b93/64 scope link
valid_lft forever preferred_lft forever
lb1:/etc/keepalived#

Nun führen wir fast das gleiche auf lb2 aus. Es gibt nur einen, aber wichtigen Unterschied - wir verwenden priority 100 anstatt priority 101 in /etc/keepalived/keepalived.conf was dazu führt, dass lb2 der passive (slave oder hot-standby) Load Balancer wird:

lb2:

vi /etc/keepalived/keepalived.conf


vrrp_script chk_pound {           # Requires keepalived-1.1.13
script "killall -0 pound" # cheaper than pidof interval 2 # check every 2 seconds weight 2 # add 2 points of prio if OK } vrrp_instance VI_1 { interface eth0 state MASTER virtual_router_id 51 priority 100 # 101 on master, 100 on backup virtual_ipaddress { 192.168.0.99 } track_script { chk_pound } }
Dann starten wir keepalived:

lb2:

/etc/init.d/keepalived start

Da lb2 der passive Load Balancer ist, sollte er nicht auf der virtuellen IP Adresse hören, solange lb1 aufgesetzt ist. Wir können dies wie folgt überprüfen:

lb2:

ip addr sh eth0

Die Ausgabe sollte so aussehen:

lb2:~# ip addr sh eth0
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:e0:78:92 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.101/24 brd 192.168.0.255 scope global eth0
inet6 fe80::20c:29ff:fee0:7892/64 scope link
valid_lft forever preferred_lft forever
lb2:~#

6 Pound Starten

Nun können wir Pound starten:

lb1/lb2:

/etc/init.d/pound start


7 Testen

Unser hochverfügbarer Load Balancer ist nun aufgesetzt und läuft.

Du kannst nun HTTP Anfragen an die virtuelle IP Adresse 192.168.0.99 (oder zu einer beliebigen Domain/Hostnamen, die auf die virtuelle IP Adresse zeigt) senden und solltest die Inhalte von den Backend Web Servern erhalten.

Du kannst die Hochverfügbarkeit durch Ausschalten eines der Backend Servers testen - der Load Balancer sollte dann alle Anfragen an den verbleibenden Web Server weiterleiten. Schalte dann den Load Balancer (lb1) aus - lb2 sollte nun automatisch übernehmen. Du kannst dies überprüfen indem Du Folgendes ausführst:

lb2:

ip addr sh eth0

Nun müsstest Du die virtuelle IP Adresse in der Ausgabe auf lb2 sehen:

lb2:~# ip addr sh eth0
2: eth0: <BROADCAST,MULTICAST,UP,10000> mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:0c:29:e0:78:92 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.101/24 brd 192.168.0.255 scope global eth0
inet 192.168.0.99/32 scope global eth0
inet6 fe80::20c:29ff:fee0:7892/64 scope link
valid_lft forever preferred_lft forever
lb2:~#

Wenn lb1 wieder auftaucht, wird lb1 wieder die Master-Rolle übernehmen.

8 Links