Keepalived
Siehe auch
HA-Failover wird mit Hilfes des Virtual Router Redundancy Protocol (VRRP) implementiert. Keepalived bietet sowohl VRRP v2 und v3; der Artikel geht auf VRRP v2 ein.
VRRP verwendet das Konzept einer virtuellen IP-Adresse (VIP). Ein oder mehrere Hosts (Router, Server usw.) wählen einen Master-Host, der diese VIP kontrollieren soll. Fällt der Master aus, schaltet VRRP auf einen Standby-Host um.
Keepalived bietet neben der VRRP-Implementierung auch die Möglichkeit, Linux IP Virtual Servers (IPVS) für Load Balancing zu konfigurieren. Mit Keepalived lässt sich also auch ein redundanter Load Balancer konfigurieren.
VRRP wählt zunächst einen Master, der die virtuelle IP-Adresse erhalten soll. VRRP-Server werden mit einem Prioritätswert konfiguriert; der Server mit der höchsten Priorität bekommt die VRRP-Adresse zugewiesen. Alle anderen Server warten nun auf regelmässige Nachrichten des Masters, die anzeigen, dass dieser noch aktiv ist. Geht der Master offline, übernimmt der Server mit der nächsthöheren Priorität die VIP (der mittels Preemption auch automatisch zum Master werden kann).
Wenn ein Master-Server zum ersten Mal online geht und eine IP-Adresse übernimmt, sendet er eine Gratuitous ARP-Nachricht. Diese informiert andere Server über die mit der VIP verknüpften MAC-Adresse, so dass sie ihren Datenverkehr auf Schicht 2 korrekt adressieren können.
VRRP Advertisement
Sowohl die Ethernet- als auch die IP-Zieladresse sind Multicast-Adressen. Multicast-Verkehr wird immer an mehrere Hosts in einem Netzwerk gesendet, die diese Multicast-Adresse „abhören“. Da die meisten Netzwerke komplexe Multicast-Konfigurationen vermeiden, wird der Multicast-Verkehr für VRRP zu Broadcast-Verkehr auf dem lokalen Netzwerksegment.
VRRP ist weder TCP noch UDP, sondern verwendet das IP-Protokollnummer 112 (wichtig für die Konfiguration der Host-Firewalls).
Ein VRRP Advertisement-Paket enthält Informationen für die Wahl eines Masters als auch Angaben über den Master, die für die anderen Server wichtig sind:
Virtuelle Router-ID (VRID): Ein eindeutiger Bezeichner für eine VRRP-Instanz plus IP-Adressen (es kann mehr als eine geben) in einem Netzwerk. In Keepalived ist das die
virtual_router_id
-Direktive.Priorität: Priorität des Hosts, der das Paket sendet. Sobald ein Master gewählt wurde, ist dies die Priorität, die der Master verwendet hat.
Auth Type und Authentication String: Enthalten ein einfaches Textpasswort, mit dem sich die Mitglieder der VRRP-Gruppe gegenseitig authentifizieren.
Advertisement Interval: Gibt an, wie oft der Master Advertisements sendet (meist 1x pro Sekunde).
IP Address: Enthält eine oder mehrere IP-Adressen, für die der Master zuständig ist.
Installation und Konfiguration
Keepalived findet sich in den Standard-Repos.
dnf -y install keepalived
keepalived --version
systemctl status keepalived
Zur Kommunikation zwischen den Hosts muss das Virtual Router Redundancy Protocol (VRRP) auf den Host-Firewalls freigegeben werden. VRRP nach RFC3768 arbeitet nicht direkt mit Ports, sondern mit der IP-Adresse 224.0.0.18 und dem gleichnamigen IP-Service (Protokoll-Nummer 112). firewalld oder iptables werden dafür wie folgt konfiguriert:
firewall-cmd --add-rich-rule='rule protocol value="vrrp" accept' --permanent
firewall-cmd --reload
iptables --append INPUT --protocol vrrp --jump ACCEPT
iptables-save > /etc/sysconfig/iptables
systemctl restart iptables
Im nachfolgenden Beispiel werden zwei Nodes konfiguriert. Einer wird initial Master, der andere ist Standby (Backup). Die Floating-IP ist 192.0.2.26
. Beide authentifizieren sich untereinander per Passwort „1234“. Der Effekt: fällt der Master aus, erhält der zweite Node die Floating-IP. Zeigt der DNS für den Service auf die Floating-IP, ist der Service weiterhin erreichbar.
Damit System-Dienste primär die Floating-IP verwenden, muss dies noch konfiguriert werden:
echo 'net.ipv4.ip_nonlocal_bind = 1' >> /etc/sysctl.conf
sysctl -p
Konfiguration von Keepalived auf Node 1 (Master) - virtual_router_id
und virtual_ipaddress
müssen übereinstimmen:
global_defs {
notification_email {
root@example.com
}
notification_email_from noreply@server01.example.com
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id server01
}
vrrp_instance VI_1 {
state MASTER
interface ens160
virtual_router_id 51
priority 255
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.0.2.26/24
}
}
Konfiguration von Keepalived auf Node 2 (Backup):
global_defs {
notification_email {
root@example.com
}
notification_email_from noreply@server02.example.com
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id server02
}
vrrp_instance VI_1 {
state BACKUP
interface ens160
virtual_router_id 51
priority 254
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.0.2.26/24
}
}
Hinweise zu den Direktiven:
advert_int
ist das Advertisement-Intervall (hier 1x pro Sekunde).priority
kann zur Laufzeit geändert geändert werden.state
: Aus den verfügbaren Maschinen wird die mit der höchsten Priorität zum Master gewählt. Der Eintragstate
spielt also an und für sich keine Rolle.virtual_ipaddress
ist die Floating/virtuelle IP.
Am Ende auf beiden:
systemctl enable --now keepalived
Die Floating-IP erscheint auf dem Server mit dem höchsten priority
-Wert (der laut RFC bei 255 liegen sollte).
Firewalling:
Outbound: Source = MyHost, Dest = 224.0.0.18 (VRRP-IP), Service = Proto 112 (vrrp)
Inbound: Source = Keepalived-Neighbours, Dest = MyHost, Service = Proto 112 (vrrp)
Prozesse mit Keepalived tracken
Was, wenn ein App-Server netzwerktechnisch erreichbar ist, aber die darauf laufende Applikation nicht? Mit obigem Konzept wird dann kein neuer Master gewählt - aber auch dieses Szenario lässt sich mit Keepalived abfangen.
Beispiel: Failover auf Apache-Ebene mit Hilfe der track_process
-Direktive.
vrrp_track_process track_httpd {
process httpd
weight 10
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 244
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.0.2.26/24
}
track_process {
track_httpd
}
}
Der Server wird mit weight 10
und priority 244
die Priorität 10 + 244 = 254 advertisen. Wird der Apache gestoppt, fällt die Priorität auf 244, und ein Failover auslösen.
Dateien mit Keepalived tracken
Keepalived kann auch anhand von Dateiinhalten Prioritäten setzen (falls beispielsweise eine Applikation regelmässig ihren Gesundheitszustands-Code in einer Datei protokolliert).
vrrp_track_file track_app_file {
file /opt/my_app/my_health
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 244
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.0.2.26/24
}
track_file {
track_app_file weight 1
}
}
Wichtig: /opt/my_app/my_health
wird durch Keepalived interpretiert. Ist der Inhalt der Datei track_app_file
ungleich 0
, wird der Wert aus der Datei mit track_app_file weight
multipliziert. Enthält die Datei /opt/my_app/my_health
eine 5
, liegt die Priorität damit bei 5 * 1 + 244 = 249.
Interfaces mit Keepalived tracken
Beispiel: Load Balancer mit einer Frontend-VIP und einer Backend-Connection in das interne Netz soll nur dann ein Failover triggern, wenn das Backend down ist. Hier hilft track_interface
:
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 244
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.0.2.26/24
}
track_interface {
ens160 weight 5
}
}
Die Priorität liegt damit bei 5 + 244, solange ens160
verfügbar ist, ansonsten fällt sie zurück auf 244.
Scripts mit Keepalived tracken
Angenommen, ein komplexeres Health-Script namens /usr/local/bin/keepalived_check.sh
kommt zum Einsatz, welches 0
zurückgibt, wenn alles in Ordnung ist.
vrrp_script keepalived_check {
script "/usr/local/bin/keepalived_check.sh"
interval 1
timeout 5
rise 3
fall 3
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 244
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
virtual_ipaddress {
192.0.2.26/24
}
track_script {
keepalived_check
}
}
Hinweise zu den Direktiven:
interval
: Script läuft 1x pro Sekunde.rise
: Script muss 3x erfolgreich laufen, um als „healthy“ zu gelten.fall
: Script gilt nach 3 Timeouts oder nicht-erfolgreichen Läufen als „unhealthy“.
Notifications
Notification-Skripte helfen, bei Failover-Events Mails zu senden, abhängige Prozesse umzukonfigurieren, zu restarten etc. Alles, was es neben dem Skript (im Beispiel /usr/local/bin/keepalived_notify.sh
) dazu braucht, ist eine notify
-Anweisung in der vrrp_instance
-Definition:
...
vrrp_instance VI_1 {
...
notify "/usr/local/bin/keepalived_notify.sh"
}
Das Notification-Script bekommt vier Variablen übergeben, die folgende Bedeutung haben:
$1
: Instanz-Typ, z.B.INSTANCE
$2
: Name der Instanz, z.B.VI_1
$3
: aktuellerstate
, z.B.MASTER
$4
: aktuellepriority
, z.B.244
So sähe ein sinnvolles Notification-Script aus:
#!/usr/bin/env bash
logger "$1 $2 has transitioned to the $3 state with a priority of $4"
Ausgabe beispielsweise:
INSTANCE VI_1 has transitioned to the FAULT state with a priority of 244
Troubleshooting
tcpdump --interface any proto 112
Keepalived compilieren
# Install prerequisites
dnf -y install gcc openssl-devel
VER=2.2.7
wget https://www.keepalived.org/software/keepalived-$VER.tar.gz
tar -xf keepalived-$VER.tar.gz
cd keepalived-$VER
./configure
make
make install
keepalived --version
Built on 2024-11-18