Vrrp: Porovnání verzí

Z HKfree wiki
Skočit na navigaci Skočit na vyhledávání
 
(Není zobrazeno 18 mezilehlých verzí od stejného uživatele.)
Řádek 1: Řádek 1:
VRRP neboli Virtual Router Redundancy Protocol slouží k vytvoření jednoho nebo více routrů, které se navzájem zálohují a plně přebírají funkci pokud primární routr z jakéhokoli důvodu přestane fungovat. Záložních routrů může být 1 až x. Způsob zapojení routrů do HA není předmětem tohoto návodu, jde pouze o ukázku konfigurace a funkčnosti takovéhoto řešení vysoké dostupnosti routrů. Princip jako funguje VRRP, HSRP apod. také není předmětem tohoto návodu, jak VRRP funguje: [http://www.orbit-computer-solutions.com/understanding-virtual-router-redundancy-protocol-vvrp/]
+
VRRP neboli Virtual Router Redundancy Protocol slouží k vytvoření jednoho nebo více routrů, které se navzájem zálohují a plně přebírají funkci pokud primární routr z jakéhokoli důvodu přestane fungovat, či pro loadbalancing serverů, což také není předmětem tohoto návodu. Záložních (backup) routrů může být 1 až n. Způsob zapojení routrů do HA není předmětem tohoto návodu, jde pouze o ukázku konfigurace a funkčnosti takovéhoto řešení vysoké dostupnosti routrů. Princip jako funguje VRRP, HSRP apod. také není předmětem tohoto návodu, jak VRRP funguje: [http://www.orbit-computer-solutions.com/understanding-virtual-router-redundancy-protocol-vvrp/]
  
 
== HW ==
 
== HW ==
Pro naši modelovou situaci použijeme jako routry dva PCengines APU s přeinstalovaným základním systémem, switch a klientské zařízení na kterém budeme testovat funkčnost VRRP, v našem případě půjde o PC s Linuxem.
+
Pro naši modelovou situaci použijeme jako routry dva PCengines APU s předinstalovaným základním systémem, switch a klientské zařízení na kterém budeme testovat funkčnost VRRP, v našem případě půjde o PC s Linuxem.
 +
 
 
== VRRP na Debianu ==
 
== VRRP na Debianu ==
 
Konfigurace, použité verze aplikací a serverů platí pro, v době psaní návodu aktuální, stable release debianu a to verzi 8.5
 
Konfigurace, použité verze aplikací a serverů platí pro, v době psaní návodu aktuální, stable release debianu a to verzi 8.5
* Nejdříve si nastavíme na obou routrech statické IP adresy, v našem případě jsem zvolil pro interface eth1 adresy 192.168.100.10 a 11 za předpokladu, že IP routru v síti (tedy z pohledu routrů virtuální adresa) má být 192.168.100.1
+
* Nejdříve si nastavíme na obou routrech statické IP adresy, v našem případě jsem zvolil pro interface eth1 adresy 192.168.100.10 a 11 za předpokladu, že IP routru v síti (tedy z pohledu routrů virtuální adresa) má být 192.168.100.2
 
* Protože virtuální adresa nebude fyzicky nastavena na jednom nebo více routrech (pouze na aktivním), musíme systému říct, aby na tuto adresu odpovídal. Do /etc/sysctl.conf přidáme tento řádek:
 
* Protože virtuální adresa nebude fyzicky nastavena na jednom nebo více routrech (pouze na aktivním), musíme systému říct, aby na tuto adresu odpovídal. Do /etc/sysctl.conf přidáme tento řádek:
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
Řádek 25: Řádek 26:
 
     interface eth1 !interface na kterem bude keepalived komunikovat, tedy ten interface ve stejne siti/vlan jako zalozni routr(y)
 
     interface eth1 !interface na kterem bude keepalived komunikovat, tedy ten interface ve stejne siti/vlan jako zalozni routr(y)
 
     virtual_router_id 1 !identifikator virtualniho routru
 
     virtual_router_id 1 !identifikator virtualniho routru
     priority 100 !priorita daneho routru, fakticky je to jedina hodnota, ktera se meni, plati, ze vim vyssi cislo, tim vyssi priorita
+
     priority 150 !priorita daneho routru, fakticky je to jedina hodnota, ktera se meni, plati, ze vim vyssi cislo, tim vyssi priorita
 
     advert_int 1 !hodnota v sekundach jak casto se bude routr dotazovat ostatnich routru jestli jsou nazivu
 
     advert_int 1 !hodnota v sekundach jak casto se bude routr dotazovat ostatnich routru jestli jsou nazivu
 
     authentication {
 
     authentication {
Řádek 32: Řádek 33:
 
     }
 
     }
 
     virtual_ipaddress {
 
     virtual_ipaddress {
         192.168.100.1/24 dev eth1
+
         192.168.100.2/24 dev eth1
 
         !virtualni adresa a zarizeni, kteremu se ma priradit, pokud ma routr vic adres,
 
         !virtualni adresa a zarizeni, kteremu se ma priradit, pokud ma routr vic adres,
 
         !vic interfacu, postupujeme analogicky IP dev INTERFACE, napr.
 
         !vic interfacu, postupujeme analogicky IP dev INTERFACE, napr.
Řádek 41: Řádek 42:
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
* Pro routr 2 je konfigurák /etc/keepalived/keepalived.conf identický, pouze se změní hodnota priority na nějaké nižší číslo, třeba 100
 
* Spustím daemona keepalived:
 
* Spustím daemona keepalived:
 
<syntaxhighlight lang="bash">
 
<syntaxhighlight lang="bash">
Řádek 67: Řádek 69:
  
 
== Testování funkčnosti ==
 
== Testování funkčnosti ==
 +
V tuto chvíli máme připravené dva routry se zcela totožnou konfigurací (až na statické IP a prioritu)
 +
* Situace 1:
 +
** běží mi pouze záložní routr2,
 +
** zapnu routr1, po naběhnutí systému si VRRP protokol zjistí, že v síti existuje další routr, ale s nižší prioritou,
 +
** pošle tedy routru s nižší prioritou, že si přebírá roli mastera,
 +
** routr2 si smaže virtuální IP,
 +
** routr1 si nastaví virtuální IP a stane se tím MASTER routrem
 +
V logu proces vypadá nějak takto (všimněte si časových značek):
 +
 +
routr2:
 +
<syntaxhighlight lang="bash">
 +
Sep  6 15:35:54 host2 Keepalived_vrrp[963]: VRRP_Instance(VI_1) Received higher prio advert
 +
Sep  6 15:35:54 host2 Keepalived_vrrp[963]: VRRP_Instance(VI_1) Entering BACKUP STATE
 +
</syntaxhighlight>
 +
routr1 (těsně po startu systému):
 +
<syntaxhighlight lang="bash">
 +
Sep  6 15:35:52 host1 Keepalived[440]: Starting Keepalived v1.2.13 (05/28,2014)
 +
Sep  6 15:35:52 host1 Keepalived[472]: Starting Healthcheck child process, pid=475
 +
Sep  6 15:35:52 host1 Keepalived[472]: Starting VRRP child process, pid=476
 +
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Initializing ipvs 2.6
 +
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Registering Kernel netlink reflector
 +
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Registering Kernel netlink command channel
 +
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Registering gratuitous ARP shared channel
 +
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Opening file '/etc/keepalived/keepalived.conf'.
 +
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Configuration is using : 60752 Bytes
 +
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Using LinkWatch kernel netlink reflector...
 +
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Registering Kernel netlink reflector
 +
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Registering Kernel netlink command channel
 +
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Opening file '/etc/keepalived/keepalived.conf'.
 +
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Configuration is using : 5295 Bytes
 +
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Using LinkWatch kernel netlink reflector...
 +
Sep  6 15:35:53 host1 Keepalived_vrrp[476]: Kernel is reporting: interface eth1 DOWN
 +
Sep  6 15:35:53 host1 Keepalived_vrrp[476]: VRRP_Instance(VI_1) Now in FAULT state
 +
Sep  6 15:35:55 host1 Keepalived_vrrp[476]: VRRP_Instance(VI_1) prio is higher than received advert
 +
Sep  6 15:35:55 host1 Keepalived_vrrp[476]: VRRP_Instance(VI_1) Transition to MASTER STATE
 +
Sep  6 15:35:55 host1 Keepalived_vrrp[476]: VRRP_Instance(VI_1) Received lower prio advert, forcing new election
 +
Sep  6 15:35:56 host1 Keepalived_vrrp[476]: VRRP_Instance(VI_1) Entering MASTER STATE
 +
</syntaxhighlight>
 +
Z pohledu klienta se neděje vůbec nic, přechod je tak rychlý, že klient přesun IP z jednoho stroje na druhý ani nezaznamená. Testováno pomocí ping 192.168.100.2 -i 0.1 > nevypadne ani jeden packet.
 +
 +
* Situace 2:
 +
** běží mi oba routry, routr1 je master,
 +
** routr1 restartuji,
 +
** routr2 po chvilce přebere roli mastera
 +
 +
routr2 (těsně po restartu routru1):
 +
Sep  6 15:35:12 host2 Keepalived_vrrp[963]: VRRP_Instance(VI_1) Transition to MASTER STATE
 +
Sep  6 15:35:13 host2 Keepalived_vrrp[963]: VRRP_Instance(VI_1) Entering MASTER STATE
 +
 +
z pohledu klienta jde asi o 2s výpadek brány.
 +
 +
* Situace 3:
 +
** Na primárním routru chci dělat update, konkrétně upgrade kernelu, k takové změně musím systém restartovat
 +
** na primárním routru si v konfiguraci snížím prioritu pod prioritu záložního routru (např. na 90) a restartuji keepalived
 +
** záložní routr by si měl bezpečně a řízeně převezmout roli martera
 +
** primární routr pak mohu bezpečně restartovat
 +
 +
==VRRP a OSPF==
 +
Na záložním routru není nutné, ba ani žádoucí, aby běžel routovací daemon v době kdy tento stroj nemá aktivně plnit roli routru. Routovací daemony nebo i jakékoli jiné služby můžeme podle potřeby vypnout či zapnout podle aktuálního stavu ve kterém se routr nachází.
 +
 +
Toto lze docílit pomocí konstrukce v keepalived.conf: notify ''<script_to_run.sh>''
 +
Script definovaný u položky "notify" se spustí vždy pokud dojde ke změně stavu, ať MASTER>BACKUP nebo BACKUP>MASTER nebo MASRTER>FAULT a scriptu jako parametr předá stav do kterého přešel, pokud chci tímto řídit spouštění a zastavování routovacích daemonů, script může vypadat nějak takto:
 +
<syntaxhighlight lang="bash">
 +
#!/bin/bash
 +
 +
TYPE=$1
 +
NAME=$2
 +
STATE=$3
 +
 +
case $STATE in
 +
  "MASTER")
 +
    service zebra start
 +
    service ospfd start
 +
    service ospf6d start
 +
    exit 0
 +
  ;;
 +
  "BACKUP")
 +
    service zebra stop
 +
    service ospfd stop
 +
    service ospf6d stop
 +
    exit 0
 +
    ;;
 +
  "FAULT")
 +
    service zebra stop
 +
    service ospfd stop
 +
    service ospf6d stop
 +
    exit 0
 +
    ;;
 +
  *)
 +
    echo "unknown state"
 +
    exit 1
 +
  ;;
 +
esac
 +
</syntaxhighlight>
 +
 +
==Check Script==
 +
Další možností jak řídit kdy a za jakých okolností přejde routr mezi stavy je konstrukce "Check Script" kde můžeme definovat vlastní příkaz nebo script a na základě jeho návratového kódu se Keepalived zachová přepnutím do daného stavu.
 +
 +
Řekněme, že chceme například sledovat jestli má routr přístup do Internetu pomocí pingu na IP 8.8.8.8, k tomuto nemusím psát žádný script, stačí mi použít pouze příkaz fping 8.8.8.8, ten vrátí návratovou hodnotu 0, pokud je IP dostupná a 1 pokud dostupná není. Check script se chová tak, že pokud je návratová hodnota příkazu/scriptu 0, je vše v pořádku, pokud není 0 (tedy jiné záporné nebo kladné číslo) znamená to chybu.
 +
 +
Do keepalived.conf přidáme tyto řádky (do vrrp_instance):
 +
<syntaxhighlight lang="bash">
 +
track_script {
 +
    chk_myscript
 +
}
 +
</syntaxhighlight>
 +
 +
<syntaxhighlight lang="bash">
 +
vrrp_script chk_myscript {
 +
  script      "/usr/bin/fping 8.8.8.8"
 +
  weight 60    # weight of this check script
 +
  interval 2  # check every 2 seconds
 +
  fall 2      # require 2 failures for KO
 +
  rise 2      # require 2 successes for OK
 +
}
 +
</syntaxhighlight>
 +
 +
*Track script {''<vrrp_script name>''} definuje seznam vrrp_scriptů, které se mají spouštět
 +
*script ''<script/příkaz>'' definuje jaký externí script nebo příkaz se má spouštět (a vyhodnocovat jeho návratová hodnota)
 +
*weight ''<int>'' je váha check scriptu - pokud se check vyhodnotí jako OK tato hodnota se přičte k prioritě master routru, pokud check selže hodnota se přičte k prioritě backup routru, lze tak definovat více checků, kde teprve při selhání více z nich dojde k přepnutí
 +
*interval ''<int>'' definuje jak často [s] se bude chcek provádět
 +
*fall ''<int>'' definuje kolikrát musí check po bezprostředně po sobě následujících pokusech selhat, aby byl prohlášen za KO
 +
*rise ''<int>'' definuje kolikrát musí check po bezprostředně po sobě následujících pokusech selhat, aby byl prohlášen za OK
 +
 +
==Mail notifikace==
 +
Keepalived umí posílat maily v případě změny stavu, lze k tomu buď využít globální konfiguraci notification_email {}, která ale není podle mého dostatečně ohebná, použijeme tedy konstrukce notify_master, notify_backup, notify_fault. Úplně stejně se dá použít konstrukce notify, která na to ale není primárně určena.
 +
 +
Definice tedy může být takováto, v keepalived.conf:
 +
 +
<syntaxhighlight lang="bash">
 +
notify_master "/root/keepalivedEmailAlert.sh MASTER"
 +
notify_backup "/root/keepalivedEmailAlert.sh BACKUP"
 +
notify_fault "/root/keepalivedEmailAlert.sh FAULT"
 +
</syntaxhighlight>
 +
 +
Samotný script:
 +
<syntaxhighlight lang="bash">
 +
#!/bin/bash
 +
 +
HW="hrubinova routr1"
 +
IP=10.107.237.1
 +
LOG="/var/log/keepalivedEmailAlert.log"
 +
 +
#email definice#
 +
ODESILATEL=kocourkov@hkfree.org
 +
PRIJEMCE=kocourkov@hkfree.org
 +
MAILAPP="/usr/bin/sendemail"
 +
HOSTNAME=$HW
 +
SMTP="smtp.hkfree.org:25"
 +
MSG="$HOSTNAME Keepalived Alert"
 +
#end email definice#
 +
 +
DATUM=`/bin/date '+%Y.%m.%d_%H.%M.%S'`
 +
 +
case $1 in
 +
  "MASTER")
 +
    echo $DATUM $HW became MASTER | tee -a $LOGFILE | $MAILAPP -u "$MSG transition to MASTER" -t $PRIJEMCE -f $ODESILATEL -s $SMTP -a /var/log/syslog
 +
  ;;
 +
  "BACKUP")
 +
    echo $DATUM $HW became BACKUP | tee -a $LOGFILE | $MAILAPP -u "$MSG transition to BACKUP" -t $PRIJEMCE -f $ODESILATEL -s $SMTP -a /var/log/syslog
 +
  ;;
 +
  "FAULT")
 +
    echo $DATUM $HW in FAULT state | tee -a $LOGFILE | $MAILAPP -u "$MSG FAULT state" -t $PRIJEMCE -f $ODESILATEL -s $SMTP -a /var/log/syslog
 +
  ;;
 +
  *)
 +
    echo $DATUM $HW is in unknown state | tee -a $LOGFILE | $MAILAPP -u "$MSG" -t $PRIJEMCE -f $ODESILATEL -s $SMTP -a /var/log/syslog
 +
  ;;
 +
esac
 +
 +
exit 0
 +
 +
</syntaxhighlight>
 +
K emailu přikládám i syslog, což je primární logovací cíl pro keepalived.
 +
 +
==Praktické zkušenosti s Keepalived==
 +
 +
*Pokud chci nechat načíst novou konfiguraci, mělo by se to dělat odesláním signálu "HUP" hlavnímu procesu keepalived, nikoli kompletním restartem služby: kill -HUP $(cat /var/run/keepalived.pid)
 +
*pozor na misconfig u keepalived.conf! některé nesrovnalosti v konfiguraci mohou odstavit primární routr a backup routr poslat do FAULT stavu, zle tak jednoduše dospět do stavu, že ani jeden z routrů nebude mít nastaveny VIP.
 +
*keepalived provádí logování do syslogu (pokud není v logovacím systému definováno jinak), zprávy od daemona lze celkem bezpečně dostat takto: "cat /var/log/syslog | grep vrrp" případně je ještě možnost nechat spustit daemona tak, že logu je do lokální konzole (pouze pro debug): keepalived --log-console
 +
*Pokud je pro vrrp komunikaci použit samostatný interface a samotný provoz jde přes jiný interface, případ kdy jsou routry propojeny na přímo kabelem a ne přes switch, je nutné mít v konfiguraci ještě položky "dont_track_primary" jinak by docházelo k tomu, že při spadnutí linku na sledovaném interface by záložní routr přešel do stavu FAULT místo aby si převzal roli master. Jde o typický příklad kdy jsou routry propojeny napřímo kabelem a jednomu z nich selže např. zdroj, routr tedy vůbec nenaběhne a nenahodí link. Tato fíčura neřeší výpadek switche do kterého jsou routry zapojeny, ale vzhledem k tomu, že switch bude s největší pravděpodobností single-poit-of-failure je to vlastně jedno.

Aktuální verze z 15. 8. 2017, 06:56

VRRP neboli Virtual Router Redundancy Protocol slouží k vytvoření jednoho nebo více routrů, které se navzájem zálohují a plně přebírají funkci pokud primární routr z jakéhokoli důvodu přestane fungovat, či pro loadbalancing serverů, což také není předmětem tohoto návodu. Záložních (backup) routrů může být 1 až n. Způsob zapojení routrů do HA není předmětem tohoto návodu, jde pouze o ukázku konfigurace a funkčnosti takovéhoto řešení vysoké dostupnosti routrů. Princip jako funguje VRRP, HSRP apod. také není předmětem tohoto návodu, jak VRRP funguje: [1]

HW

Pro naši modelovou situaci použijeme jako routry dva PCengines APU s předinstalovaným základním systémem, switch a klientské zařízení na kterém budeme testovat funkčnost VRRP, v našem případě půjde o PC s Linuxem.

VRRP na Debianu

Konfigurace, použité verze aplikací a serverů platí pro, v době psaní návodu aktuální, stable release debianu a to verzi 8.5

  • Nejdříve si nastavíme na obou routrech statické IP adresy, v našem případě jsem zvolil pro interface eth1 adresy 192.168.100.10 a 11 za předpokladu, že IP routru v síti (tedy z pohledu routrů virtuální adresa) má být 192.168.100.2
  • Protože virtuální adresa nebude fyzicky nastavena na jednom nebo více routrech (pouze na aktivním), musíme systému říct, aby na tuto adresu odpovídal. Do /etc/sysctl.conf přidáme tento řádek:
net.ipv4.ip_nonlocal_bind=1
  • Pro načtení změn v /etc/sysctl.conf provedeme příkaz:
sysctl -p

man sysctl -p: Load in sysctl settings from the file specified or /etc/sysctl.conf if none given. Specifying - as filename means reading data from standard input.

  • Nainstalujeme keepalived
apt-get install keepalived
  • Editujeme /etc/keepalived/keepalived.conf pro routr 1:
vrrp_instance VI_1 {
    state MASTER !MASTER ma nejvyssi prioritu
    interface eth1 !interface na kterem bude keepalived komunikovat, tedy ten interface ve stejne siti/vlan jako zalozni routr(y)
    virtual_router_id 1 !identifikator virtualniho routru
    priority 150 !priorita daneho routru, fakticky je to jedina hodnota, ktera se meni, plati, ze vim vyssi cislo, tim vyssi priorita
    advert_int 1 !hodnota v sekundach jak casto se bude routr dotazovat ostatnich routru jestli jsou nazivu
    authentication {
        auth_type PASS !typ autentifikace, PASS je plaintext heslo
        auth_pass TajneHeslo !heslo v plaintext
    }
    virtual_ipaddress {
        192.168.100.2/24 dev eth1
        !virtualni adresa a zarizeni, kteremu se ma priradit, pokud ma routr vic adres,
        !vic interfacu, postupujeme analogicky IP dev INTERFACE, napr.
        !192.168.101.1 dev vlan10
        !192.168.102.1 dev vlan20
        !apod.
    }
}
  • Pro routr 2 je konfigurák /etc/keepalived/keepalived.conf identický, pouze se změní hodnota priority na nějaké nižší číslo, třeba 100
  • Spustím daemona keepalived:
service keepalived start
  • Daemon by měl do logu vypsat něco jako:
Sep  6 14:35:03 host2 Keepalived[959]: Starting Keepalived v1.2.13 (05/28,2014)
Sep  6 14:35:03 host2 Keepalived[960]: Starting Healthcheck child process, pid=962
Sep  6 14:35:03 host2 Keepalived_healthcheckers[962]: Initializing ipvs 2.6
Sep  6 14:35:03 host2 Keepalived[960]: Starting VRRP child process, pid=963
Sep  6 14:35:03 host2 Keepalived_vrrp[963]: Registering Kernel netlink reflector
Sep  6 14:35:03 host2 Keepalived_vrrp[963]: Registering Kernel netlink command channel
Sep  6 14:35:03 host2 Keepalived_healthcheckers[962]: Registering Kernel netlink reflector
Sep  6 14:35:03 host2 Keepalived_vrrp[963]: Registering gratuitous ARP shared channel
Sep  6 14:35:03 host2 Keepalived_healthcheckers[962]: Registering Kernel netlink command channel
Sep  6 14:35:03 host2 Keepalived_healthcheckers[962]: Opening file '/etc/keepalived/keepalived.conf'.
Sep  6 14:35:03 host2 Keepalived_healthcheckers[962]: Configuration is using : 5295 Bytes
Sep  6 14:35:03 host2 Keepalived_vrrp[963]: Opening file '/etc/keepalived/keepalived.conf'.
Sep  6 14:35:03 host2 Keepalived_vrrp[963]: Configuration is using : 60752 Bytes
Sep  6 14:35:03 host2 Keepalived_vrrp[963]: Using LinkWatch kernel netlink reflector...
Sep  6 14:35:03 host2 Keepalived_healthcheckers[962]: Using LinkWatch kernel netlink reflector...
Sep  6 14:35:04 host2 Keepalived_vrrp[963]: VRRP_Instance(VI_1) Transition to MASTER STATE
Sep  6 14:35:05 host2 Keepalived_vrrp[963]: VRRP_Instance(VI_1) Entering MASTER STATE

Testování funkčnosti

V tuto chvíli máme připravené dva routry se zcela totožnou konfigurací (až na statické IP a prioritu)

  • Situace 1:
    • běží mi pouze záložní routr2,
    • zapnu routr1, po naběhnutí systému si VRRP protokol zjistí, že v síti existuje další routr, ale s nižší prioritou,
    • pošle tedy routru s nižší prioritou, že si přebírá roli mastera,
    • routr2 si smaže virtuální IP,
    • routr1 si nastaví virtuální IP a stane se tím MASTER routrem

V logu proces vypadá nějak takto (všimněte si časových značek):

routr2:

Sep  6 15:35:54 host2 Keepalived_vrrp[963]: VRRP_Instance(VI_1) Received higher prio advert
Sep  6 15:35:54 host2 Keepalived_vrrp[963]: VRRP_Instance(VI_1) Entering BACKUP STATE

routr1 (těsně po startu systému):

Sep  6 15:35:52 host1 Keepalived[440]: Starting Keepalived v1.2.13 (05/28,2014)
Sep  6 15:35:52 host1 Keepalived[472]: Starting Healthcheck child process, pid=475
Sep  6 15:35:52 host1 Keepalived[472]: Starting VRRP child process, pid=476
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Initializing ipvs 2.6
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Registering Kernel netlink reflector
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Registering Kernel netlink command channel
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Registering gratuitous ARP shared channel
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Opening file '/etc/keepalived/keepalived.conf'.
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Configuration is using : 60752 Bytes
Sep  6 15:35:52 host1 Keepalived_vrrp[476]: Using LinkWatch kernel netlink reflector...
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Registering Kernel netlink reflector
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Registering Kernel netlink command channel
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Opening file '/etc/keepalived/keepalived.conf'.
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Configuration is using : 5295 Bytes
Sep  6 15:35:52 host1 Keepalived_healthcheckers[475]: Using LinkWatch kernel netlink reflector...
Sep  6 15:35:53 host1 Keepalived_vrrp[476]: Kernel is reporting: interface eth1 DOWN
Sep  6 15:35:53 host1 Keepalived_vrrp[476]: VRRP_Instance(VI_1) Now in FAULT state
Sep  6 15:35:55 host1 Keepalived_vrrp[476]: VRRP_Instance(VI_1) prio is higher than received advert
Sep  6 15:35:55 host1 Keepalived_vrrp[476]: VRRP_Instance(VI_1) Transition to MASTER STATE
Sep  6 15:35:55 host1 Keepalived_vrrp[476]: VRRP_Instance(VI_1) Received lower prio advert, forcing new election
Sep  6 15:35:56 host1 Keepalived_vrrp[476]: VRRP_Instance(VI_1) Entering MASTER STATE

Z pohledu klienta se neděje vůbec nic, přechod je tak rychlý, že klient přesun IP z jednoho stroje na druhý ani nezaznamená. Testováno pomocí ping 192.168.100.2 -i 0.1 > nevypadne ani jeden packet.

  • Situace 2:
    • běží mi oba routry, routr1 je master,
    • routr1 restartuji,
    • routr2 po chvilce přebere roli mastera

routr2 (těsně po restartu routru1): Sep 6 15:35:12 host2 Keepalived_vrrp[963]: VRRP_Instance(VI_1) Transition to MASTER STATE Sep 6 15:35:13 host2 Keepalived_vrrp[963]: VRRP_Instance(VI_1) Entering MASTER STATE

z pohledu klienta jde asi o 2s výpadek brány.

  • Situace 3:
    • Na primárním routru chci dělat update, konkrétně upgrade kernelu, k takové změně musím systém restartovat
    • na primárním routru si v konfiguraci snížím prioritu pod prioritu záložního routru (např. na 90) a restartuji keepalived
    • záložní routr by si měl bezpečně a řízeně převezmout roli martera
    • primární routr pak mohu bezpečně restartovat

VRRP a OSPF

Na záložním routru není nutné, ba ani žádoucí, aby běžel routovací daemon v době kdy tento stroj nemá aktivně plnit roli routru. Routovací daemony nebo i jakékoli jiné služby můžeme podle potřeby vypnout či zapnout podle aktuálního stavu ve kterém se routr nachází.

Toto lze docílit pomocí konstrukce v keepalived.conf: notify <script_to_run.sh> Script definovaný u položky "notify" se spustí vždy pokud dojde ke změně stavu, ať MASTER>BACKUP nebo BACKUP>MASTER nebo MASRTER>FAULT a scriptu jako parametr předá stav do kterého přešel, pokud chci tímto řídit spouštění a zastavování routovacích daemonů, script může vypadat nějak takto:

#!/bin/bash

TYPE=$1
NAME=$2
STATE=$3

case $STATE in
  "MASTER")
    service zebra start
    service ospfd start
    service ospf6d start
    exit 0
  ;;
  "BACKUP")
    service zebra stop
    service ospfd stop
    service ospf6d stop
    exit 0
    ;;
  "FAULT")
    service zebra stop
    service ospfd stop
    service ospf6d stop
    exit 0
    ;;
  *)
    echo "unknown state"
    exit 1
  ;;
esac

Check Script

Další možností jak řídit kdy a za jakých okolností přejde routr mezi stavy je konstrukce "Check Script" kde můžeme definovat vlastní příkaz nebo script a na základě jeho návratového kódu se Keepalived zachová přepnutím do daného stavu.

Řekněme, že chceme například sledovat jestli má routr přístup do Internetu pomocí pingu na IP 8.8.8.8, k tomuto nemusím psát žádný script, stačí mi použít pouze příkaz fping 8.8.8.8, ten vrátí návratovou hodnotu 0, pokud je IP dostupná a 1 pokud dostupná není. Check script se chová tak, že pokud je návratová hodnota příkazu/scriptu 0, je vše v pořádku, pokud není 0 (tedy jiné záporné nebo kladné číslo) znamená to chybu.

Do keepalived.conf přidáme tyto řádky (do vrrp_instance):

track_script {
    chk_myscript
}
vrrp_script chk_myscript {
  script       "/usr/bin/fping 8.8.8.8"
  weight 60    # weight of this check script
  interval 2   # check every 2 seconds
  fall 2       # require 2 failures for KO
  rise 2       # require 2 successes for OK
}
  • Track script {<vrrp_script name>} definuje seznam vrrp_scriptů, které se mají spouštět
  • script <script/příkaz> definuje jaký externí script nebo příkaz se má spouštět (a vyhodnocovat jeho návratová hodnota)
  • weight <int> je váha check scriptu - pokud se check vyhodnotí jako OK tato hodnota se přičte k prioritě master routru, pokud check selže hodnota se přičte k prioritě backup routru, lze tak definovat více checků, kde teprve při selhání více z nich dojde k přepnutí
  • interval <int> definuje jak často [s] se bude chcek provádět
  • fall <int> definuje kolikrát musí check po bezprostředně po sobě následujících pokusech selhat, aby byl prohlášen za KO
  • rise <int> definuje kolikrát musí check po bezprostředně po sobě následujících pokusech selhat, aby byl prohlášen za OK

Mail notifikace

Keepalived umí posílat maily v případě změny stavu, lze k tomu buď využít globální konfiguraci notification_email {}, která ale není podle mého dostatečně ohebná, použijeme tedy konstrukce notify_master, notify_backup, notify_fault. Úplně stejně se dá použít konstrukce notify, která na to ale není primárně určena.

Definice tedy může být takováto, v keepalived.conf:

notify_master "/root/keepalivedEmailAlert.sh MASTER"
notify_backup "/root/keepalivedEmailAlert.sh BACKUP"
notify_fault "/root/keepalivedEmailAlert.sh FAULT"

Samotný script:

#!/bin/bash

HW="hrubinova routr1"
IP=10.107.237.1
LOG="/var/log/keepalivedEmailAlert.log"

#email definice#
ODESILATEL=kocourkov@hkfree.org
PRIJEMCE=kocourkov@hkfree.org
MAILAPP="/usr/bin/sendemail"
HOSTNAME=$HW
SMTP="smtp.hkfree.org:25"
MSG="$HOSTNAME Keepalived Alert"
#end email definice#

DATUM=`/bin/date '+%Y.%m.%d_%H.%M.%S'`

case $1 in
  "MASTER")
    echo $DATUM $HW became MASTER | tee -a $LOGFILE | $MAILAPP -u "$MSG transition to MASTER" -t $PRIJEMCE -f $ODESILATEL -s $SMTP -a /var/log/syslog
  ;;
  "BACKUP")
    echo $DATUM $HW became BACKUP | tee -a $LOGFILE | $MAILAPP -u "$MSG transition to BACKUP" -t $PRIJEMCE -f $ODESILATEL -s $SMTP -a /var/log/syslog
  ;;
  "FAULT")
    echo $DATUM $HW in FAULT state | tee -a $LOGFILE | $MAILAPP -u "$MSG FAULT state" -t $PRIJEMCE -f $ODESILATEL -s $SMTP -a /var/log/syslog
  ;;
  *)
    echo $DATUM $HW is in unknown state | tee -a $LOGFILE | $MAILAPP -u "$MSG" -t $PRIJEMCE -f $ODESILATEL -s $SMTP -a /var/log/syslog
  ;;
esac

exit 0

K emailu přikládám i syslog, což je primární logovací cíl pro keepalived.

Praktické zkušenosti s Keepalived

  • Pokud chci nechat načíst novou konfiguraci, mělo by se to dělat odesláním signálu "HUP" hlavnímu procesu keepalived, nikoli kompletním restartem služby: kill -HUP $(cat /var/run/keepalived.pid)
  • pozor na misconfig u keepalived.conf! některé nesrovnalosti v konfiguraci mohou odstavit primární routr a backup routr poslat do FAULT stavu, zle tak jednoduše dospět do stavu, že ani jeden z routrů nebude mít nastaveny VIP.
  • keepalived provádí logování do syslogu (pokud není v logovacím systému definováno jinak), zprávy od daemona lze celkem bezpečně dostat takto: "cat /var/log/syslog | grep vrrp" případně je ještě možnost nechat spustit daemona tak, že logu je do lokální konzole (pouze pro debug): keepalived --log-console
  • Pokud je pro vrrp komunikaci použit samostatný interface a samotný provoz jde přes jiný interface, případ kdy jsou routry propojeny na přímo kabelem a ne přes switch, je nutné mít v konfiguraci ještě položky "dont_track_primary" jinak by docházelo k tomu, že při spadnutí linku na sledovaném interface by záložní routr přešel do stavu FAULT místo aby si převzal roli master. Jde o typický příklad kdy jsou routry propojeny napřímo kabelem a jednomu z nich selže např. zdroj, routr tedy vůbec nenaběhne a nenahodí link. Tato fíčura neřeší výpadek switche do kterého jsou routry zapojeny, ale vzhledem k tomu, že switch bude s největší pravděpodobností single-poit-of-failure je to vlastně jedno.