Aujourd’hui, les grandes entreprises et administrations publiques hésitent entre continuer à utiliser des logiciels propriétaires ou basculer vers les Logiciels Libres. Pourtant, la plupart des logiciels libres sont capables de bien traiter les données issues des logiciels propriétaire, et parfois avec une meilleur compatibilité.
C’est alors la barrière de la prise en main qui fait peur, et pourtant...
Les logiciels libres
L’aspect « Logiciel Libre » permet une évolution rapide et une plus grande participation des utilisateurs. Les aides et tutoriels foisonnent sur Internet ou sont directement inclus dans le logiciel lui-même.
Enfin, les concepteurs sont plus proches des utilisateurs, ce qui rend les logiciels libres plus agréable à utiliser et conviviaux.
Grâce à la disponibilité des logiciels libres, vous trouverez facilement des services de support techniques et la licence n’est plus un frein à l’utilisation de ces logiciels par votre personnel.
Notre support technique concerne essentiellement les logiciels libres, que ce soit sous forme de services ponctuels ou de tutoriels.
- Février 2011 -
Le down d'un service peut avoir d'étranges conséquences sur le milieu professionnel. En effet, cela peut passer totalement inaperçu ou bien cela va générer une crise sans précédent, au cours de laquelle vous n'aurez jamais assez bien fait en aval que ce que vous auriez dû prévoir en amont.L'appréhension de ce genre d'incident permet l'évaluation du besoin et des
SLA (Service Level Agreements) et, en fonction, le déploiement d'architecture dites
HA (High Availability). Dans ce type d'architecture, typiquement, l'objectif est de pouvoir assurer un service quelque soit les incidents possibles et imaginables.Techniquement, cela se traduit par la mise en place de
n machines, capables, toutes de délivrer le service, et de savoir ordonner qui prend la main et quand. Ce dernier point implique la présence d'un maître d'orchestre, et donc d'un
Single Point Of Failure.Dans ce cas, qui monitore et assure la disponibilité du service de dispatchage des rôles ?
KeepAlived ?
Keepalived est un daemon tournant en Userland qui a pour ambition d'adresser ces 2 problématiques : d'une part gérer la vérification de l'état des intervenants d'un cluster de serveurs et d'autre part assurer, en fonction de ces états, la distribution des rôles aux membres de ce regroupement.En clair, il s'agit de monitorer les états des différents serveurs impliqués dans la délivrance du service et d'en gérer la disponibilité via l'attribution dynamique de l'IP par laquelle les clients sollicite ce service.La clé repose sur l'exploitation des fonctionnalités du projet
LVS (Linux Virtual Server) et sur le concept d'IP virtuelle. Le tout fonctionne sur une infrastructure de type cluster de serveur / load balancer, généralement contenu dans une DMZ.Afin de mieux comprendre son fonctionnement, je vous propose de rentrer directement dans la configuration de la bête, car comme dit le vieux proverbe : "il faut avoir les manches retroussées pour comprendre complètement la mécanique !"Par la suite, je vais donc lâchement supposer que votre infrastructure est en place, et qu'il ne reste plus que le point Keepalived à traiter. Si vous avez besoin d'un petit coup de pouce niveau LVS, jetez un coup d'oeil sur le
LVS HowTo de Joseph Mack.
Installation depuis les sources
L'installation la plus nette est toujours celle utilisant
git, c'est d'ailleurs elle que j'ai choisi, mais rien ne vous empêche d'utiliser les dépôts !
$ git clone http://master.formilux.org/git/people/alex/keepalived.git /usr/local/src/
$ ll /usr/local/src/
total 12
drwxr-xr-x 3 bux bux 4096 2011-02-16 12:08 .
drwxr-xr-x 20 bux bux 4096 2011-02-16 12:08 ..
drwxr-xr-x 9 bux bux 4096 2011-02-16 12:08 keepalived
$ cd keepalived
$ ./configure
[...]
Keepalived configuration
------------------------
Keepalived version : 1.1.20
Compiler : gcc
Compiler flags : -g -O2
Extra Lib : -lpopt -lssl -lcrypto
Use IPVS Framework : No
IPVS sync daemon support : No
Use VRRP Framework : Yes
Use Debug flags : No
$ make && make install
[...]
install -d /usr/local/sbin
install -m 700 ../bin/keepalived /usr/local/sbin/
install -d /usr/local/etc/rc.d/init.d
install -m 755 etc/init.d/keepalived.init /usr/local/etc/rc.d/init.d/keepalived
install -d /usr/local/etc/sysconfig
install -m 755 etc/init.d/keepalived.sysconfig /usr/local/etc/sysconfig/keepalived
install -d /usr/local/etc/keepalived/samples
install -m 644 etc/keepalived/keepalived.conf /usr/local/etc/keepalived/
install -m 644 ../doc/samples/* /usr/local/etc/keepalived/samples/
install -d /usr/local/share/man/man5
install -d /usr/local/share/man/man8
install -m 644 ../doc/man/man5/keepalived.conf.5 /usr/local/share/man/man5
install -m 644 ../doc/man/man8/keepalived.8 /usr/local/share/man/man8
make[1]: quittant le répertoire « /usr/local/src/keepalived/keepalived »
make -C genhash install
make[1]: entrant dans le répertoire « /usr/local/src/keepalived/genhash »
install -d /usr/local/bin
install -m 755 ../bin/genhash /usr/local/bin/
install -d /usr/local/share/man/man1
install -m 644 ../doc/man/man1/genhash.1 /usr/local/share/man/man1
make[1]: quittant le répertoire « /usr/local/src/keepalived/genhash »
Installation cleared !
Configuration
Comme on peut le déduire des traces laissées par le make de keepalived, les fichiers de configuration se situent sous /usr/local/etc/keepalived/, en sachant qu'un fichier est déjà fourni de base et qu'on peut également s'appuyer sur les samples (exemples, extraits) fournis :
$ ll /usr/local/etc/keepalived/
total 16
drwxr-xr-x 3 root root 4096 2011-02-16 12:13 .
drwxr-xr-x 5 root root 4096 2011-02-16 12:13 ..
-rw-r--r-- 1 root root 3562 2011-02-16 12:13 keepalived.conf
drwxr-xr-x 2 root root 4096 2011-02-16 12:13 samples
$ ll samples/
total 104
drwxr-xr-x 2 root root 4096 2011-02-16 12:13 .
drwxr-xr-x 3 root root 4096 2011-02-16 12:13 ..
-rw-r--r-- 1 root root 1745 2011-02-16 12:13 client.pem
-rw-r--r-- 1 root root 245 2011-02-16 12:13 dh1024.pem
-rw-r--r-- 1 root root 433 2011-02-16 12:13 keepalived.conf.fwmark
-rw-r--r-- 1 root root 684 2011-02-16 12:13 keepalived.conf.HTTP_GET.port
-rw-r--r-- 1 root root 746 2011-02-16 12:13 keepalived.conf.inhibit
-rw-r--r-- 1 root root 550 2011-02-16 12:13 keepalived.conf.misc_check
-rw-r--r-- 1 root root 538 2011-02-16 12:13 keepalived.conf.misc_check_arg
-rw-r--r-- 1 root root 2467 2011-02-16 12:13 keepalived.conf.quorum
-rw-r--r-- 1 root root 919 2011-02-16 12:13 keepalived.conf.sample
-rw-r--r-- 1 root root 2760 2011-02-16 12:13 keepalived.conf.SMTP_CHECK
-rw-r--r-- 1 root root 1587 2011-02-16 12:13 keepalived.conf.SSL_GET
-rw-r--r-- 1 root root 842 2011-02-16 12:13 keepalived.conf.status_code
-rw-r--r-- 1 root root 735 2011-02-16 12:13 keepalived.conf.track_interface
-rw-r--r-- 1 root root 887 2011-02-16 12:13 keepalived.conf.virtualhost
-rw-r--r-- 1 root root 1087 2011-02-16 12:13 keepalived.conf.virtual_server_group
-rw-r--r-- 1 root root 1425 2011-02-16 12:13 keepalived.conf.vrrp
-rw-r--r-- 1 root root 3019 2011-02-16 12:13 keepalived.conf.vrrp.localcheck
-rw-r--r-- 1 root root 1083 2011-02-16 12:13 keepalived.conf.vrrp.lvs_syncd
-rw-r--r-- 1 root root 888 2011-02-16 12:13 keepalived.conf.vrrp.routes
-rw-r--r-- 1 root root 1146 2011-02-16 12:13 keepalived.conf.vrrp.scripts
-rw-r--r-- 1 root root 591 2011-02-16 12:13 keepalived.conf.vrrp.static_ipaddress
-rw-r--r-- 1 root root 1742 2011-02-16 12:13 keepalived.conf.vrrp.sync
-rw-r--r-- 1 root root 802 2011-02-16 12:13 root.pem
-rw-r--r-- 1 root root 323 2011-02-16 12:13 sample.misccheck.smbcheck.sh
Le fichier de configuration en question est généré tel quel :
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.16
192.168.200.17
192.168.200.18
}
}
virtual_server 192.168.200.100 443 {
delay_loop 6
lb_algo rr
lb_kind NAT
nat_mask 255.255.255.0
persistence_timeout 50
protocol TCP
real_server 192.168.201.100 443 {
weight 1
SSL_GET {
url {
path /
digest ff20ad2481f97b1754ef3e12ecd3a9cc
}
url {
path /mrtg/
digest 9b3a0c85a887a256d6939da88aabd8cd
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
virtual_server 10.10.10.2 1358 {
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
sorry_server 192.168.200.200 1358
real_server 192.168.200.2 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl3/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.200.3 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
virtual_server 10.10.10.3 1358 {
delay_loop 3
lb_algo rr
lb_kind NAT
nat_mask 255.255.255.0
persistence_timeout 50
protocol TCP
real_server 192.168.200.4 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl3/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.200.5 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl3/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
Grâce à lui, on a déjà un aperçu de la manière dont KeepAlived organise les informations : tout passe par la définition de bloc.
Epluchage de conf
On peut voir que la configuration est scindée en trois :
- une partie globale (le bloc global_def), qui n'est ni plus ni moins que la définition des adresses mail, de routes statiques et d'identifiant.
- une partie définissant les instances et groupes de synchronisation VRRP,
- une partie propre aux paramétrages des LVS, qui peut contenir un ou plusieurs blocs de définition de serveurs virtuels, eux-même encapsulant des serveurs réels caractérisés par des paramétrage en terme de poids, d'IP, et de process de vérification.
Intéressons-nous aux 2 dernières parties.
VRRP
vrrp_sync_group
Les VRRP synchronization groups sont des groupes qui rassemblent les instances VVRP.
#string, name of group of IPs that failover together
vrrp_sync_group VG_1 {
group {
VI_1 # name of vrrp_instance (below)
VI_2 # One for each moveable IP.
...
}
# notify scripts and alerts are optional
# filenames of scripts to run on transitions can be unquoted (if just filename) or quoted (if has parameters) to MASTER transition
notify_master /path/to_master.sh
# to BACKUP transition
notify_backup /path/to_backup.sh
# FAULT transition
notify_fault "/path/fault.sh VG_1"
# for ANY state transition.
# "notify" script is called AFTER the
# notify_* script(s) and is executed
# with 3 arguments provided by keepalived (ie don't include parameters in the notify line).
# arguments
# $1 = "GROUP"|"INSTANCE"
# $2 = name of group or instance
# $3 = target state of transition
# ("MASTER"|"BACKUP"|"FAULT")
notify /path/notify.sh
# Send email notifcation during state transition,
# using addresses in global_defs above.
smtp_alert
}
vrrp_instance
La partie
vrrp_instance est définie dans la configuration créée telle que :
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.200.16
192.168.200.17
192.168.200.18
}
}
Alors, c'est quoi au juste cette vrrp_instance ?Commençons par le commencement.
VRRP, pour
Virtual Router Redondancy Protocol, est un protocole d'abstraction de serveur, qui permet via la création d'un groupe de serveurs réels et la gestion d'adresses IP réelles et virtuelles, d'attribuer dynamiquement le rôle de réponse aux requêtes client à un des serveurs en état de le faire. En un mot, il assure le
monitoring des instances capables de délivrer le service et donc sa
disponibilité.La configuration par défaut définit donc notre machine comme l'instance VRRP maître et y associe :
- un identifiant (virtual_router_id 51),
- une interface liée à VRRP (interface eth0),
- une priorité très haute (priority 100), en sachant que plus cette priorité est haute et plus la machine a de chance d'être élue,
- des paramètres d'authentification
- des adresses IP virtuelles à rajouter / supprimer lors des bascules.
Juste au cas où,
auth_pass doit être strictement identique sur toutes les machines impliquées.De cette façon, il faudra définir, pour chaque membre étant ou pouvant être impliqué potentiellement dans la bascule les caractéristiques de sa
vrrp_instance.
A noter que le template généré est loin d'être exhaustif. En effet, pas mal d'options permettent de mieux travailler la bascule.
LVS
De la même manière qu'il est possible de faire des groupes d'instance vrrpd, il est possible de grouper les instances virtual_server, mais la Communauté ne semble envisager son utilisation que dans le cas où vous êtes en présence de très grands LVS , ce ne sera donc pas abordé ici.
virtual_server
Notre bloc concernant un
virtual_server a cette tête-là dans la conf générée. Les commentaires sont là pour éviter une répétition laborieuse et peu utile de chacune des instructions pour détail :)
virtual_server 192.168.200.100 443 {
# delay timer for service polling
delay_loop 3
# LVS scheduler
lb_algo rr
# LVS forwarding method
lb_kind NAT
nat_mask 255.255.255.0
# LVS persistence timeout, sec
persistence_timeout 50
protocol TCP
# RS to add when all realservers are down
sorry_server 192.168.200.200 443
# one entry for each realserver
real_server 192.168.201.100 443 {
# relative weight to use, default: 1
weight 1
# pick one healthchecker
# HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK
SSL_GET {
url {
path /
digest ff20ad2481f97b1754ef3e12ecd3a9cc
}
url {
path /mrtg/
digest 9b3a0c85a887a256d6939da88aabd8cd
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
} # End HTTP_GET section
} # End real_server definition
} # End virtual_server definition
Beaucoup plus intuitif que les sections VRRP, cette configuration est très simple à manier et se passe assez facilement d'explication. Même remarque, les options ne sont pas exhaustives et une véritable mine de paramètres vous attendent au détour d'un man.Il ne reste plus qu'à paufiner la conf et à lancer un petit keepalived -D (detailed logs).
La preuve par l'exemple
Jouons un peu avec les serveurs DNS.Nous avons un serveur maître, et un esclave. Ces deux serveurs ont chacun une IP réelle (192.168.0.2 pour le Maître et 192.168.0.3 pour l'esclave). En revanche, le service est accédé l'IP virtuelle 192.168.0.10.
$ ssh root@dns1 ip addr sh eth0
2: eth0: mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:50:56:a3:00:0d brd ff:ff:ff:ff:ff:ff
inet 192.168.0.2/24 brd 192.168.0.255 scope global eth0
inet 192.168.0.10/32 scope global eth0
inet6 fe80::250:56ff:fea3:d/64 scope link
valid_lft forever preferred_lft forever
$ ssh root@dns2 ip addr sh eth0
2: eth0: mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 00:50:56:a3:00:0c brd ff:ff:ff:ff:ff:ff
inet 192.168.0.3/24 brd 192.168.0.255 scope global eth0
inet6 fe80::250:56ff:fea3:c/64 scope link
valid_lft forever preferred_lft forever
$ ping dns
PING dns.k-tux.com (192.168.0.10) 56(84) bytes of data.
64 bytes from dns.k-tux.com (192.168.0.10): icmp_seq=1 ttl=63 time=0.499 ms
^C
--- dns.k-tux.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 535ms
rtt min/avg/max/mdev = 0.499/0.499/0.499/0.000 ms
En terme de configuration Keepalived, nous aurons donc 2 types d'instances vrrp.Ici, nous effectuons une vérification toutes les 6 secondes qui, selon le résultat du check, pourra potentiellement faire basculer l'IP virtuelle 192.168.0.10 d'un serveur à l'autre. Pour cela nous devons définir un
vrrp_script, qui fera en temps et en secondes les traitements voulus.
Sur le master :
vrrp_script check_named { # Requires keepalived-1.1.13
script "killall -0 named" # cheaper than pidof
interval 6 # check every 6 seconds
weight -60 # add 60 points of prio if OK
}
vrrp_instance dns_on_master {
state MASTER
interface eth0
virtual_router_id 91
priority 200
advert_int 1
smtp_alert
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.10
}
track_script {
check_named
}
notify_master "/etc/rc.d/init.d/named reload"
notify_backup "/etc/rc.d/init.d/named reload"
}
Et sur le slave :
vrrp_script check_named { # Requires keepalived-1.1.13
script "killall -0 named" # cheaper than pidof
interval 6 # check every 6 seconds
weight -60 # add 60 points of prio if OK
}
vrrp_instance dns_on_slave {
state SLAVE
interface eth0
virtual_router_id 91
priority 150
smtp_alert
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.10
}
track_script {
check_named
}
notify_master "/etc/rc.d/init.d/named reload"
notify_backup "/etc/rc.d/init.d/named reload"
}
Le test le plus probant est d'arrêter un des deux serveurs dns, au hasard le master (celui qui a la plus haute priorité détient logiquement l'IP virtuelle) : on doit observer une bascule de l'IP virtuelle 192.168.0.10 de dns1 à dns2. Le
smtp_alert nous rajoute une couche d'information en nous mailant la bascule.
Conclusion
Quelques détails suffisent à changer la donne, et coupler Keepalived avec une infrastructure bien étudiée permet de balayer assez facilement les petits soucis relatifs à des pannes de service.De plus c'est un outil simple, intuitif, riche en terme d'options et paramétrable à souhait.Pourquoi s'en passer ?

Original post of K-Tux.
Votez pour ce billet sur Planet Libre.