World IPv6 Day
Happy World IPv6 Day everyone! Time to check the dancing turtle, isn’t it?

Not connected? Sneak in ..
Happy World IPv6 Day everyone! Time to check the dancing turtle, isn’t it?

Not connected? Sneak in ..
Nach Teil 5, dem Load Balancing per NAT, geht’s heute um Load Balancing per direct routing.
Zur Erinnerung:

Die Anfragen kommen am Load Balancer an, der die Ziel MAC-Adresse in den Paketen abändert. Sehen wir uns diesen Prozess im Detail an:
eth0, jedoch mit einer IP die auf einem dummy-Interface gebunden ist, tut was ein Web-Server eben tut und schickt die Antwort an an den Client zurück. Das Paket erhält als Absender-IP die auf dummy gebundene IP.persistent=) behält der Load Balancer die Information auf welchen Web-Server er den Client geschickt hat eine Weile bei oder entfernt diesen Eintrag aus der Adress-Tabelle.Notwendig für die Funktion dieses Workflows ist, daß alle Maschinen sich im gleichen Layer 2 Segment befinden. Zwischen dem Load Balancer und den Web-Servern darf bei direct routing kein Router stehen.
Konkret mit IPv4 Adressen bestückt, sieht die Konfiguration auf dem Load Balancer folgendermaßen aus:

Die IP 198.18.0.1 muß direkt auf z.B. eth0 gebunden werden. Dies ist wichtig, damit der Router eine valide MAC-Adresse für 198.18.0.1 lernen kann und die Pakete auf den Load Balancer zustellen kann.
/etc/ha.d/conf/ldirectord.cf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | checktimeout=10
checkinterval=2
autoreload=yes
callback="/etc/ha.d/config_sync.sh"
logfile="local0"
quiescent=yes
virtual=198.18.0.1:80
real=198.18.0.11:80 gate
real=198.18.0.12:80 gate
real=198.18.0.13:80 gate
fallback=127.0.0.1:80
service=http
request="lb-test.html"
receive="shiny captain"
scheduler=wrr
protocol=tcp
checktype=negotiate |
Bisher ist die Konfiguration in /etc/ha.d/conf/ldirectord.cf von den IP-Adressen und gate anstatt masq stark identisch, allerdings muß für direct routing auch jeder einzelne Web-Server angefasst werden.
Zunächst muß das dummy-Modul geladen werden, so daß dem System das Interface dummy0 zur Verfügung steht.
root@webserver:~# modprobe dummy
root@webserver:~# echo dummy >> /etc/modules
Die Datei /etc/network/interfaces wird um die Konfiguration für dummy0 erweitert:
1 2 3 4 | auto dummy0
iface dummy0 inet static
address 198.18.0.1
netmask 255.255.255.255 |
Ein beherztes ifup dummy0, und alles ist bereit für einen ersten Test. Für diesen Test kann der ldirectord von Hand gestartet werden, also per /etc/init.d/ldirectord start, allerdings sollte später die /etc/ha.d/haresources um die entsprechende Zeile erweitert werden. Wenn alles klappt, sollte ipvsadm -Ln nach wenigen Sekunden die ersten Ausgaben liefern:
root@frasier:~# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 198.18.0.1:80 wrr persistent 1200
-> 198.18.0.11:80 Route 1 0 0
Der Load Balancer hat erkannt, daß auf 198.18.0.11 der konfigurierte Service erreichbar ist, sofern bei Weight eine “1″ steht. Bei “0″ konnte keine Verbindung aufgebaut werden, und quiescent=yes ist gesetzt. (Siehe Teil 5)
root@frasier:~# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 198.18.0.1:80 wrr persistent 1200
-> 198.18.0.11:80 Route 0 0 0
Entsprechendes mit IPv6 ist auch kein Hexenwerk.

In der Datei /etc/ha.d/conf/ldirectord.cf auf checktype und checkcommand achten, und die IPv6 Adressen ausschreiben und nicht mit :: abkürzen.
/etc/ha.d/conf/ldirectord.cf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | checktimeout=10
checkinterval=2
autoreload=yes
callback="/etc/ha.d/config_sync.sh"
logfile="local0"
quiescent=no
virtual=[2001:db8:0:1:0:0:0:a]:443
real=[2001:db8:0:1:0:0:0:1]:443 gate
real=[2001:db8:0:1:0:0:0:2]:443 gate
real=[2001:db8:0:1:0:0:0:3]:443 gate
fallback=[::1]:443
persistent=1200
scheduler=wrr
protocol=tcp
checktype=external
checkcommand="/usr/share/nagios/libexec/check_http" |
Entsprechend der Konfiguration für IPv4 muß auch die IP-Adresse 2001:db8:0:1::a auf jedem einzelnen Web-Server gebunden werden.
1 2 3 4 | auto dummy0
iface dummy0 inet6 static
address 2001:db8:0:1::a
netmask 64 |
Mit ipvsadm -Ln werden auch IPv6 Verbindungen angezeigt.
root@frasier:~# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 198.18.0.1:80 wrr persistent 1200
-> 198.18.0.11:80 Route 1 0 0
-> 198.18.0.12:80 Route 1 0 0
-> 198.18.0.13:80 Route 1 0 0
TCP [2001:db8:0:1::a]:80 wrr persistent 1200
-> [2001:db8:0:1::1]:80 Route 1 0 0
-> [2001:db8:0:1::2]:80 Route 1 0 0
-> [2001:db8:0:1::3]:80 Route 1 0 0
In Teil 2 habe in angefangen über den ldirectord zu schreiben. Nochmal zur Erinnerung: der ldirectord ist ein User-Space Script, welches mit Hilfe des IP Virtual Servers (kurz IPVS) im Kernel einen Load Balancer in Software abbildet. Angerissen habe ich bereits zwei Methoden zum Load Balancing,
Dieser Artikel beschäftigt sich mit Load Balancing per NAT.
Nochmal zum Konzept:

Die Anfragen kommen am Load Balancer an, der anschließend auf die Web-Farm NATet. Sehen wir uns diesen Prozess im Detail an:
und ändert das Paket an Hand seiner Konfiguration ab. Die Ziel-IP wird durch eine der Web-Server IPs im internen Netz ausgetauscht und mit der entsprechenden MAC-Adresse versehen. Danach schickt der Load Balancer das Paket auf dem internen Interface wieder auf’s Ethernet.
persistent=) behält der Load Balancer die Information auf welchen Web-Server er den Client geschickt hat eine Weile bei oder entfernt diesen Eintrag aus der Adress-Tabelle.Abgesehen von der Entscheidung auf welchen Ziel Web-Server die Verbindung geNATtet wird, unterscheidet sich dieser Prozess nicht vom NAT in z.B. einer Fritz!Box. Zum besseren Verständnis der Konfiguration, obiges Beispiel mit IPv4 Adressen:

Das externe Interface des Load Balancers steht in 198.18.0.0/24 und das interne Netz mit der Web-Farm wird durch 10.0.0.0/24 repräsentiert. Durch dieses Setup lassen sich effizient öffentliche IPv4-Adressen einsparen, denn für die Website www.example.org wird trotz mehrerer Web-Server nur eine einzige IPv4 Adresse benötigt.
Die Konfiguration des ldirectord geschieht in der Datei /etc/ha.d/conf/ldirectord.cf, wobei der Pfad zu dieser Datei in /etc/default/ldirectord überschrieben werden kann, z.B. wenn man den ldirectord nicht mit Heartbeat kombinieren möchte.
/etc/ha.d/conf/ldirectord.cf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | checktimeout=10
checkinterval=2
autoreload=yes
callback="/etc/ha.d/config_sync.sh"
logfile="local0"
quiescent=yes
virtual=198.18.0.1:80
real=10.0.0.21:80 masq
real=10.0.0.22:80 masq
real=10.0.0.23:80 masq
fallback=127.0.0.1:80
service=http
request="lb-test.html"
receive="shiny captain"
scheduler=wrr
protocol=tcp
checktype=negotiate |
Die Konfiguration von oben nach unten:
checktimeout und checkinterval definieren wie häufig die Ziel-Maschinen geprüft werden sollen, bzw. wie hoch das Timeout definiert werden soll, bis ein Server als tot definiert wird. Die Angaben sind in Sekunden.autoreload=yes definiert, daß die Konfiguration neu geladen wurde, sobald sie sich auf der Festplatte geändert hat. Damit einher gehtcallback, denn hier kann ein Binary oder Script angegeben werden, das ausgeführt wird, sobald die Konfiguration sich geändert hatte. config_sync.sh ist nur ein Beispiel, dieses Script ist nicht Teil der Distribution.logfile definiert eine Log-Datei bzw. eine Syslog Facilityquiescent=yes werde ich weiter unten noch genauer eingehen, denn dieser Punkt arbeitet eng mit persistent in der virtual-Sektion zusammen.Die virtual-Sektion definiert jeweils eine “virtuelle” IP (das, was man in den DNS für www einträgt) und kann mehrfach in der Konfiguration stehen, sofern mehr als nur eine IP gebalanced werden soll. Jede Zeile der Konfiguration die zu einer virtual-Sektion gehört muß mit einem Tabulator (\t) eingerückt werden; leider ist die Syntax-Prüfung etwas seltsam und man bekommt extrem nichts sagende Fehlermeldungen.
virtual=198.18.0.1:80 definiert 198.18.0.1 mit Port 80 als virtuelle Adresse. Diese IP muß auf dem Load Balancer lokal (z.B. an eth0, nicht an lo oder dummy0) gebunden werden, denn ldirectord bindet die IP nicht automatisch. Bei einem HA-Setup empfiehlt es sich natürlich diese IP als Cluster-Ressource zu definieren.real=10.0.0.21:80 masq definiert einen Backend-Server inklusive des Ports. Es ist durchaus möglich intern die Web-Server auf anderen Ports zu betreiben, nach außen allerdings weiter auf Port 80 verfügbar zu sein. masq schaltet den IPVS in den NAT-Modus.fallback=127.0.0.1:80 wird ein Notfall-Server definiert, der dann genutzt wird, wenn alle reellen Server als defekt definiert wurden. Hier kann z.B. ein “Wartungsarbeiten, komm später wieder” Text auf einem lokalen Web-Server definiert werden; oder man läßt die Zeile komplett weg, wenn man keinen Fallback-Server hat oder möchte. Anfragen gehen dann allerdings ins Leere.service definiert den zu balancenden Dienst, sofern checktype=negotiate gesetzt ist. Eine Liste der verfügbaren Dienste befindet sich in der man-page des ldirectord, interessant sind zwei besondere Fälle:
none: es soll keine Form von Checks stattfinden. Wenn ein Server ausfällt wird der Load Balancer das nicht bemerken und den Server weiterhin in der Verteilung nutzen.simpletcp: ein generischer Service der mit request eine TCP-Verbindung aufbaut und das empfangene Ergebnis mit receive matcht.Für “standard” Services wie http, https oder ssh enthält der ldirectord sehr brauchbare Checks, die die Verfügbarkeit des Services exzellent prüfen.
scheduler definiert die Load Balancing Methode, den Scheduler Algorithmus. Zur Verfügung stehen 10 verschiedene Algorithmen, unter anderem
rr – Round Robin: verteile alle Anfragen der Reihe nach auf die Serverwrr – Weighted Round Robin, gewichteter Round Robin: arbeitet wieder ungewichtete Round Robin, man kann den Servern aber verschieden hohe Prioritäten geben, um beispielsweise ungleich starke Hardware besser ausnutzen zu könnenlc – Least-Connection: Maschinen mit weniger offenen Verbindungen als andere bekommen bevorzugt neue Verbindungen zugeteiltwlc – Weighted Least-Connection: ebenfalls vergleichbar mit Least-Connection, allerdings wieder mit Gewichtung der Maschinendh – Destination Hashing: erstellt einen Hash über die Ziel-IP und weist darüber einen Backend-Server zush – Source Hashing: erstellt einen Hash über die Quell-IP und weist darüber einen Backend-Server zuipvsadm gibt im Detail Auskunft. checktype noch an auf welche Weise die Backend-Server geprüft werden sollen. Mehr dazu gleich mehr.Mit IPv6 ist die Konfiguration nahezu identisch, abgesehen von den Check-Methoden.

Außerdem wird diesmal https gebalanced.
/etc/ha.d/conf/ldirectord.cf:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | checktimeout=10
checkinterval=2
autoreload=yes
callback="/etc/ha.d/config_sync.sh"
logfile="local0"
quiescent=no
virtual=[2001:db8:0:1:0:0:0:1]:443
real=[2001:db8:0:2:0:0:0:21]:443 masq
real=[2001:db8:0:2:0:0:0:22]:443 masq
real=[2001:db8:0:2:0:0:0:23]:443 masq
fallback=[::1]:443
persistent=1200
service=http
request="lb-test.html"
receive="shiny captain"
scheduler=wrr
protocol=tcp
checktype=negotiate |
Zwei Konfigurations-Direktiven bin ich Euch noch schuldig: quiescent und checktype.
Um zu erkennen in welchem Zustand sich die Backend-Server befinden, muß der Load Balancer regelmäßig prüfen, ob die Maschinen wie gewünscht antworten und ihren zugewiesenen Dienst erfüllen können. Wird checktype=connect gesetzt, so baut der ldirectord eine einfache TCP-Verbindung auf und prüft ob ein erwarteter String zurück gemeldet wird. Bei UDP würde es hier schon etwas schwerer werden, und bei Protokollen wie https muß sogar ein SSL-Handshake stattfinden. Mit einem TCP-Connect ist es also in manchen Fällen nicht unbedingt getan, hier wird etwas mehr Logik notwendig. checktype=negotiate in Verbindung mit service=https, um beim IPv6 Beispiel zu bleiben baut eine Verbindung auf Port 443 zu den Backend-Servern auf, macht den erwarteten SSL-Handshare und wertet dann den mit receive angegebenen String aus. Wird request und receive nicht angegeben, so gilt der Server bereits bei korrektem Verbindungsaufbau als intakt, ob aber beispielsweise Datenbank-Verbindungen funktionieren oder nicht wird der Load Balancer nicht erkennen. Hier ist Kreativität gefragt eine “OK“- bzw. “ERROR“-Seite zu basteln, die alle notwendigen Verbindungen der Web-Applikation prüft und entsprechend einen Status abliefert. Sofern notwendig, kann checktimeout nach oben hin angepasst werden, wenn z.B. alle Datenbank-Verbindungen aufzubauen länger als 10 Sekunden dauert.
Wird ein Backend-System auf Grund der Checks als defekt markiert, kommt quiescent ins Spiel. Bei yes wird der betroffene Backend-Server still gelegt, es werden also keine neuen Verbindungen zugelassen, er befindet sich aber noch in der Kernel-Tabelle des IPVS. Wird quiescent=no gesetzt, so wird er restlos aus der Kernel-Tabelle entfernt. In das IPv6/SSL Beispiel habe ich noch den Parameter persistent=1200 geschmuggelt. persistent definiert wie lange .. genau, das stand ja weiter oben schon, wie lange eine Verbindung in der Kernel-Tabelle gehalten werden soll, wieviele Sekunden also ein Client auf den gleichen Backend-Server gebalanced werden soll. Bei quiescent=no wird bei Ausfall eines Servers die Verbindung trotz persistent direkt neu verteilt, bei quiescent=yes muß erst das Timeout von hier 1200 Sekunden (= 20 Minuten) abgewartet werden.
Bleibt nur noch der erwähnte Sonderfall mit den Check-Methoden im Zusammenhang mit IPv6: checktype=negotiate funktioniert mit den meisten Protokollen für IPv6 noch nicht. (Stand März 2011, ldirectord-Version v1.186-ha aus Debian Squeeze) Dies ist allerdinge kein Show-Stopper, denn checktype kennt noch einen weiteren Parameter: external.
1 2 3 4 5 6 7 8 | virtual=[2001:db8:0:1:0:0:0:1]:80
real=[2001:db8:0:2:0:0:0:21]:80 masq
real=[2001:db8:0:2:0:0:0:22]:80 masq
real=[2001:db8:0:2:0:0:0:23]:80 masq
fallback=[::1]:80
scheduler=rr
checktype=external
checkcommand="/usr/share/nagios/libexec/check_http" |
Bei checktype=external kann mit checkcommand ein beiliebiges Binary oder Script angegeben werden, welches den Backend-Server prüft. Nagios-Plugins, /bin/true oder was dem geneigten Admin sonst noch so einfällt, wichtig ist nur, daß entsprechende Error-Codes an den ldirectord geliefert werden. Und der Gedanke bei Ausfall eines real-Servers gleich einen passive service check an Nagios weiter zu geben hat doch was, oder?
Teil 6 beschreibt direct routing im Detail.
I just added IPv6 AAAA-Records to the interdose.com-Zone, so this blog and the company website are now reachable via IPv6.
In der nächsten Zeit werde ich eine Artikel-Reihe zum Thema Hochverfügbarkeit mit Linux schreiben. Die Motivation dahinter ist, daß erstaunlich wenig qualitativer Content zu dieser Thematik im Netz zu finden ist, sofern man nach halbwegs aktuellen Versionen oder Artikeln in deutscher Sprache ausschau hält.
Diese Artikelreihe befasst sich mit dem aktuellen Debian GNU/Linux Release 6.0 “squeeze” und den darin enthaltenen Paketen.
heartbeat
Alt, aber hilft mit guter Laune durch jeden IOS Bug.
Als ich neulich meinen WRT54g in Rente geschickt habe, ist mir aufgefallen, daß die Time Capsule ziemlich gut mit IPv6 umgehen kann.
Die Time Capsule beherrscht hierbei drei verschiedene IPv6-Modi:
fe80::-Adresse gebunden, und Kommunikation per IPv6 ist nur innerhalb des LANs möglichWer beim Thema Tunnel lieber selbst Hand anlegen möchte, oder zumindest kontrollieren möchte wo sein IPv6 Upstream her kommt, auch dem sei geholfen:
Wird die Konfiguration einfach auf Automatik belassen, bekommt man ein /64-Prefix frei Haus mit genau keinem Aufwand.
Die Time Capsule verfügt sogar über eine rudimentäre Firewall:
Sinnvoll finde ich persönlich in diesem Zusammenhang die Möglichkeit, teredo-Tunnel zu unterbinden, und damit das IPv6-Routing nicht unnötig zu verkomplifizieren, wenn durch die Time Capsule schon halbwegs nativer Upstream besteht.
Zur besseren Übersicht – wenn ich meine Logs richtig interpretiere wird zu viel nach der Thematik gesucht – hier meine drei Artikel zum Thema IPv6 auf Clients aktivieren nochmals als Übersicht:
Vielleicht erspare ich so dem ein oder anderen Besucher die Suche.
Linux, MacOS X – bleibt ja eigentlich nur noch Windows.
Teredo ist bei Vista bereits installiert, jedoch abgeschaltet. Bei Windows XP muß der Dienst erst installiert werden, aber das ist auch kein Problem und die zwei Minuten sind weiterhin schaffbar.
Der Weg auf Windows XP:
ipv6 install
netsh interface ipv6
set teredo type=client
Der Weg auf Vista und Windows 7 (nicht getestet):
netsh interface ipv6
set teredo type=client
Auf MacOS X ist über Teredo IPv6 in zwei Minuten schaffbar. Wie sieht’s mit Linux aus?
The Teredo IPv6 tunneling protocol encapsulates IPv6 packets into UDP/IPv4 datagrams, to allow hosts behind NAT devices to access the IPv6 Internet.
Miredo is a Teredo client (as per RFC 4380): it can provide IPv6 connectivity to a dual-stack IPv6/IPv4 host even if it is located behind a NAT. It can also operate as a Teredo relay which forwards IPv6 packets between the IPv6 Internet and remote Teredo clients.
Miredo wird auf debianoiden Systemen per apt-get installiert und ist sofort nutzbar.
apt-get install miredo
Keine Konfiguration notwendig. Das schafft man in deutlich unter zwei Minuten
% ip ad sh teredo 5: teredo:mtu 1280 qdisc pfifo_fast state UNKNOWN qlen 500 link/[65534] inet6 2001:f:53aa:erfg:3447:asdf:261c:b068/32 scope global valid_lft forever preferred_lft forever inet6 fe80::ffff:ffff:ffff/64 scope link valid_lft forever preferred_lft forever