Keepalived

Keepalived – czyli wysoka dostępność serwerów i usług

Keepalived to otwarte oprogramowanie używane w systemach Linux do zapewniania wysokiej dostępności i równoważenia obciążenia dla serwerów i usług. Jest to narzędzie, które umożliwia tworzenie klasterów o wysokiej dostępności poprzez monitorowanie stanu zdrowia serwerów i dynamiczne przekierowywanie ruchu między nimi w przypadku awarii lub problemów z dostępnością. Keepalived zapewnia implementację zarówno wersji 2, jak i wersji 3 protokołu służącego do przełączania awaryjnego HA – Virtual Router Redundancy Protocol (VRRP).

Keepalived został stworzony przez Alex Shemyakin, który jest głównym twórcą i programistą tego projektu. Jest to projekt open-source, co oznacza, że jest dostępny publicznie i może być używany oraz rozwijany przez społeczność programistów i użytkowników. Dzięki społeczności otwartego oprogramowania, Keepalived jest ciągle rozwijany i udoskonalany, a także dostosowywany do różnorodnych potrzeb i scenariuszy.

Podstawowe cechy Keepalived

  1. Monitorowanie stanu serwerów: Keepalived ciągle monitoruje stan zdrowia serwerów w klastrze. Może to obejmować sprawdzanie dostępności serwerów poprzez ping lub inne protokoły, a także monitorowanie usług działających na serwerach, takich jak serwery WWW czy bazy danych.
  2. Równoważenie obciążenia: Keepalived automatycznie dystrybuuje ruch od użytkowników do zdrowych serwerów w celu równoważenia obciążenia. To pozwala uniknąć nadmiernego obciążenia pojedynczego serwera, co może prowadzić do spadku wydajności lub awarii.
  3. Przekierowywanie w przypadku awarii: Jeśli któryś z serwerów zostanie uznany za niedostępny, Keepalived automatycznie przenosi ruch na zdrowy serwer, aby zapewnić ciągłość usług. Dzięki temu awaria jednego serwera nie prowadzi do przerwy w dostępie do usług.
  4. Virtual IP (VIP): Keepalived może również zarządzać wirtualnym adresem IP, który jest używany przez użytkowników do łączenia się z usługą. W przypadku awarii serwera, Keepalived przypisuje ten wirtualny adres IP do zdrowego serwera, minimalizując przerwy w dostępie.
  5. Konfigurowalność: Keepalived oferuje szeroki zakres opcji konfiguracyjnych, które pozwalają dostosować zachowanie klastra do indywidualnych potrzeb i scenariuszy.

Keepalived jest często stosowany w środowiskach, gdzie dostępność i niezawodność są kluczowe, takich jak serwery WWW, serwery poczty, serwery baz danych i inne usługi. Dzięki niemu można zapewnić, że awarie sprzętu lub oprogramowania nie wpłyną negatywnie na dostępność usług, co jest niezwykle istotne w dzisiejszym środowisku cyfrowym.

Założenia scenariuszy testowych

Wykorzystamy Keepalived do utrzymania wysokiej dostępności dwóch serwerów www (Nginx). Naszym celem jest zapewnienie dostępności strony internetowej, nawet wtedy, gdy jeden z serwerów przestanie działać. Do tego celu wykorzystamy trzy adresy IP:

  • 10.225.38.46: Ten adres będzie używany jako główny serwer primary
  • 10.225.38.57: Ten adres będzie używany jako pomocniczy serwer secondary
  • 10.225.38.38: Ten adres będzie wirtualnym adresem IP (virtual IP), który będzie przypisany do aktywnego serwera.

Zakładamy że na obydwu serwerach mamy następujący stan:

  • aktualny system (Debian/Ubuntu)
  • włączona synchronizacja czasu (chronyd lub ntpd)
  • ustawiony stały adres IP

Aby osiągnąć cel, zainstalujemy Keepalived, który będzie monitorował stan zdrowia serwerów i w razie potrzeby przejmie kontrolę nad adresem virtual IP, aby utrzymać dostępność usługi. Gdy główny serwer przestanie działać, Keepalived automatycznie przeniesie adres virtual IP na pomocniczy serwer, aby kontynuować dostarczanie usługi.

Powyższy zamysł przetestujemy za pomoc dwóch scenariuszy:

  1. Scenariusz 1 – prosta konfiguracja Keepalived bez monitorowania stanu usługi Nginx.
  2. Scenariusz 2 – konfiguracja rozbudowana o dodatkowe monitorowanie stanu usługi Nginx.

Scenariusz 1

VRRP
VRRP
VRRP
VRRP
VIP
10.225.38.38
VIP…
Serwer primary10.225.38.46Serwer secondary10.225.38.57
Text is not SVG – cannot display

1.1 Konfiguracja serwera Primary:

#ustawiamy hostname
hostnamectl set-hostname primary
#instalujemy nginx oraz keepalived
apt install keepalived nginx
#ustawiamy na domyślnej stronie nazwę hosta
echo $(hostname) > /var/www/html/index.nginx-debian.html
#tworzymy plik konfiguracyjny
mkdir /etc/haproxy/
vim /etc/keepalived/keepalived.conf

zawartość:

vrrp_instance MY_KEEPALIVED1 {  # Definicja instancji VRRP o nazwie MY_KEEPALIVED1
  state MASTER  # Tryb pracy: MASTER lub BACKUP
  interface ens3  # Określa interfejs, na którym działać będzie instancja VRRP
  virtual_router_id 1  # Unikalny numer identyfikacyjny wirtualnego routera

  priority 11  # Priorytet tego węzła (wyższa wartość oznacza wyższy priorytet)

  # Adresy virtual IP zarządzane przez Keepalived
  virtual_ipaddress {
    10.225.38.38
  }
}

Sprawdzamy status

systemctl restart nginx
systemctl restart keepalived
systemctl status nginx
systemctl status keepalived

sprawdzamy czy na naszym interfejsie pojawiło się virtualne IP

ubuntu@primary:~$ ip a | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 10.225.38.46/24 metric 100 brd 10.225.38.255 scope global ens3
    inet 10.225.38.38/32 scope global ens3

1.2 Konfiguracja serwera Secondary:

#ustawiamy hostname
hostnamectl set-hostname secondary
#instalujemy nginx oraz keepalived
apt install keepalived nginx
#ustawiamy na domyślnej stronie nazwę hosta
echo $(hostname) > /var/www/html/index.nginx-debian.html
#tworzymy plik konfiguracyjny
mkdir /etc/haproxy/
vim /etc/keepalived/keepalived.conf

zawartość

vrrp_instance MY_KEEPALIVED1 {  # Definicja instancji VRRP o nazwie MY_KEEPALIVED1
  state BACKUP  # Tryb pracy: MASTER lub BACKUP
  interface ens3  # Określa interfejs, na którym działać będzie instancja VRRP
  virtual_router_id 1  # Unikalny numer identyfikacyjny wirtualnego routera

  priority 10  # Priorytet tego węzła (wyższa wartość oznacza wyższy priorytet)

  # Adresy virtual IP zarządzane przez Keepalived
  virtual_ipaddress {
    10.225.38.38
  }
}

musimy zmienić priority na niższą wartość oraz ustawiamy state na BACKUP

uruchamiamy i sprawdzamy status

systemctl restart nginx
systemctl restart keepalived
systemctl status nginx
systemctl status keepalived

Sprawdzamy czy na naszym drugim serwerze pojawiło się virtual IP:

ubuntu@secondary:~$ ip a | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 10.225.38.57/24 metric 100 brd 10.225.38.255 scope global ens3

W sytuacji kiedy oba serwery działają poprawnie nie powinno go być.

1.3 Testy

W ramach testów zasymulujemy awarię pierwszego serwera primary i sprawdzimy czy Keepalived przeniesie virtual IP na server secondary. W pierwszej kolejności z naszego hosta sprawdzimy dostępność strony www na adresie virtual IP:

kamil@legion:~$ curl 10.225.38.38
primary

Teraz zasymulujmy awarię serwera primary:

ubuntu@primary:~# sudo systemctl stop keepalived

Sprawdzamy czy keepalived przeniósł virtual IP na serwer secondary:

ubuntu@secondary:~$ ip a | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 10.225.38.57/24 metric 100 brd 10.225.38.255 scope global ens3
    inet 10.225.38.38/32 scope global ens3

Ostatnią rzeczą którą sprawdzimy to dostępność strony www z naszego hosta

kamil@legion:~$ curl 10.225.38.38
secondary

Strona www jest cały czas dostępna pod adresem ustawionym jako virtual IP ale tym razem ruch został przekierowany na serwer secondary. Natomiast w tym prostym scenariuszu w przypadku awarii samego Nginxa, virtual IP nie zostanie przeniesiony. Scenariusz zabezpiecza tylko przed następującymi awariami:

  • Całkowita awaria serwera
  • Awaria samego daemona keepalived
  • Awaria karty sieciowej

W Scenariuszu drugim dodamy sprawdzanie stanu serwera Nginx aby zabezpieczyć się także przed tą potencjalną awarią.

Scenariusz 2

Rozbudujemy konfigurację keepalived o dodatkowe monitorowanie stanu usługi Nginx.

VRRP
VRRP
VRRP
VRRP
VIP
10.225.38.38
VIP…
Serwer primary10.225.38.46Serwer secondary10.225.38.57NginxNginx
Text is not SVG – cannot display

2.1 Konfiguracja serwera Primary:

# Plik konfiguracyjny Keepalived

# Globalne definicje
global_defs {
  router_id nginx  # Unikalna nazwa dla tego węzła Keepalived
}

# Skrypt monitorujący stan NGINX
vrrp_script check_nginx {
  script "/bin/check_nginx.sh"  # Ścieżka do skryptu monitorującego
  interval 2  # Interwał sprawdzania w sekundach
  weight 50  # Waga skryptu (wyższa waga oznacza większą ważność)
}

# Instancja Keepalived
vrrp_instance MY_KEEPALIVED1 {
  state MASTER  # Tryb pracy: MASTER lub BACKUP
  interface ens3  # Interfejs sieciowy, na którym działa Keepalived
  virtual_router_id 1  # Unikalny numer identyfikacyjny instancji VRRP

  priority 11  # Priorytet tego węzła (wyższa wartość oznacza wyższy priorytet)

  # Adresy virtual IP zarządzane przez Keepalived
  virtual_ipaddress {
    10.225.38.38
  }

  # Śledzenie stanu NGINX za pomocą skryptu
  track_script {
    check_nginx  # Śledzenie skryptu check_nginx
  }
}

tworzymy skrypt monitorujący stan daemona Nginx

vim  /bin/check_nginx.sh

zawartość:

#!/bin/sh
if [ -z "`pidof nginx`" ]; then
  exit 1
fi

nadajemy uprawnienia dla skryptu oraz restartujemy keepalived

chmod 755 /bin/check_nginx.sh
systemctl restart keepalived

2.2 Konfiguracja serwera Secondary:

# Plik konfiguracyjny Keepalived

# Globalne definicje
global_defs {
  router_id nginx  # Unikalna nazwa dla tego węzła Keepalived
}

# Skrypt monitorujący stan NGINX
vrrp_script check_nginx {
  script "/bin/check_nginx.sh"  # Ścieżka do skryptu monitorującego
  interval 2  # Interwał sprawdzania w sekundach
  weight 50  # Waga skryptu (wyższa waga oznacza większą ważność)
}

# Instancja Keepalived
vrrp_instance MY_KEEPALIVED1 {
  state BACKUP  # Tryb pracy: MASTER lub BACKUP
  interface ens3  # Interfejs sieciowy, na którym działa Keepalived
  virtual_router_id 1  # Unikalny numer identyfikacyjny instancji VRRP

  priority 10  # Priorytet tego węzła (wyższa wartość oznacza wyższy priorytet)

  # Adresy virtual IP zarządzane przez Keepalived
  virtual_ipaddress {
    10.225.38.38
  }

  # Śledzenie stanu NGINX za pomocą skryptu
  track_script {
    check_nginx  # Śledzenie skryptu check_nginx
  }
}

tworzymy skrypt monitorujący stan daemona Nginx

vim  /bin/check_nginx.sh

zawartość:

#!/bin/sh
if [ -z "`pidof nginx`" ]; then
  exit 1
fi

nadajemy uprawnienia dla skryptu oraz restartujemy keepalived

chmod 755 /bin/check_nginx.sh
systemctl restart keepalived

2.3 Test

W pierwszej kolejności z naszego hosta sprawdzamy dostępność strony www

kamil@legion:~$ curl 10.225.38.38
primary

Teraz zasymulujmy awarię daemona Nginx na serwerze primary:

ubuntu@primary:~# sudo systemctl stop nginx

Sprawdzamy czy keepalived przeniósł virtual IP na serwer secondary oraz czy strona www w dalszym ciągu działa.

root@secondary:~# ip a | grep ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 10.225.38.57/24 metric 100 brd 10.225.38.255 scope global ens3
    inet 10.225.38.38/32 scope global ens3
kamil@legion:~$ curl 10.225.38.38
secondary

UWAGI

1. Bezpieczeństwo

W celu zwiększenia bezpieczeństwa możemy włączyć autentykację pomiędzy węzłami w klastrze Keepalived.

Głównym celem opcji „authentication” jest zapewnienie, że tylko węzły z prawidłowymi poświadczeniami (hasłami) mogą komunikować się ze sobą w celu monitorowania stanu i obsługi klastra Keepalived.

W tym celu musimy dodać w pliku konfiguracyjnym wpis konfiguracyjny „authentication”:

authentication {
    auth_type PASS
    auth_pass your_password
}
  1. auth_type Określa typ autentykacji. W przykładzie powyżej użyto autentykacji opartej na haśle (PASS), ale Keepalived obsługuje również inne metody autentykacji, takie jak SHA256, MD5, itp. Wybór metody zależy od preferencji i wymagań bezpieczeństwa.
  2. auth_pass Jest to właściwe hasło lub klucz autentykacyjny, który musi być wspólny dla wszystkich węzłów w klastrze. To hasło lub klucz jest wykorzystywane do uwierzytelnienia węzłów w trakcie wymiany informacji i monitorowania stanu.

2. Firewall

Jeśli mamy włączony firewall musimy dodać reguły przepuszczające ruch VRRP. W przypadku UFW:

# Na sererze primary
ufw allow to 10.225.38.57 comment 'VRRP'
ufw allow from 10.225.38.57 comment 'VRRP'
# Na serwerze secondary
ufw allow to 10.225.38.46 comment 'VRRP'
ufw allow from 10.225.38.46 comment 'VRRP'

3. IPVS

W przypadku konfiguracji Keepalived do równoważenia obciążenia z wykorzystaniem protokołu IPVS (IP Virtual Server), konieczne może być ręczne załadowanie modułu ip_vs na serwerze. Moduł ten umożliwia jądro Linux obsługę mechanizmu równoważenia obciążenia IPVS. Na obydwu serverach ładujemy moduł:

echo "modprobe ip_vs" >> /etc/modules
modprobe ip_vs

4. tcpdump

Ruch sieciowy VRRP możemy obserowować za pomocą narzędzia tcpdump:

tcpdump -v -i ens3 host 10.225.38.57

5. Szybkie środowisko testowe

W cel przygotowania szybkiego środowiska testowego na naszym komputerze z Ubuntu możemy użyć Multipass’a. Multipass to narzędzie w systemie Ubuntu, które umożliwia szybkie i łatwe tworzenie oraz zarządzanie wirtualnymi maszynami w środowisku Linux na komputerze osobistym.

snap install multipass
multipass launch --name=primary
multipass launch --name=secondary