LVS aka Linux Virtual Servers est la solution par défaut offerte par les distributions Linux en matière de Load Balancing.
Cette solution permet de répartir la charge utilisateur sur une ferme de serveurs, assurant ainsi une granularité possible dans la montée en puissance et en charge de vos services internet mis à la disposition d’une population de plus en plus grande.
Nous verrons dans cet article que le choix des outils permettant d’automatiser la surveillance et le déclanchement des divers process permettant d’assurer le HA est celui de Keep-Alived, même si l’objet n’est pas ici d’expliquer le fonctionnement de cet outil.
1) Préconisations
1.1) Système
Les noyaux linux postérieurs à la version 2.2.14 intègrent les fonctionnalités LVS, si vous n’êtes pas à ce niveau, vous devrez patcher le kernel avec le module « IPVS » prévu pour votre distribition.
Généralement, les serveurs LVS sont doublés, en mode FailOver, et supervisés par un module chargé de faire la bascule du primaire vers le secondaire en cas de défaillance du primaire, en effet, rien ne sert par exemple d’avoir une ferme de serveurs Web si votre LVS ne fonctionne plus et que personne ne peut plus y accéder… Pour cela, il existe plusieurs solutions classiques telles que HeartBeat ou KeepAlived. Dans notre exemple, nous utiliserons KeepAlived.
Dans nos tests, nous avons utilisé une openSuSE 11.4 64bits (kernel 2.6.37) et qui intègre donc la fonctionnalité IPVS. Les serveurs LVS possèdent chacun trois cartes ethernet dont un couple est configuré pour le réseau de production en bonding et la troisième carte sert pour la gestion du FailOver du serveur LVS (protocole VRRP) avec l’utilitaire KeepAlived.
Téléchargements :
- OpenSuSE : http://software.opensuse.org/114/fr
- Doc LVS : http://www.linuxvirtualserver.org/Documents.html
- IPVS (si kernel < 2.2.14) : http://rpm.pbone.net/index.php3?simple=1&stat=3&search=ipvs
- KeepAlived (optionnel) : http://www.keepalived.org/software/keepalived-1.2.2.tar.gz
1.2) Matériel
Evidement plus votre machine est puissante mieux cela sera, cependant, il ne faut pas perdre à l’esprit que votre solution LVS se comportera à priori comme un switch (niveau 4 du modèle ISO), même si certains « patchs » peuvent l’amener à interagir au niveau 7. A ce titre les interfaces réseaux doivent être le premier niveau de qualité, la CPU (nombre de processeurs / coeurs) le deuxième niveau.
Le premier travail d’un serveur LVS va consister en un routage, d’une adresse IP (adresse virtuelle, ou « IPV ») et un port connu du grand public et la redirection d’un flux réseau qui sera transmis, en fonction de la « charge » estimée sur les serveurs de la ferme et de sa disponibilité, vers le serveur le plus « disponible » (le moins chargé). L’analyse de la charge d’un serveur dépend d’un algorithme et demande donc de la CPU, mais la notion primaire demeure celle de la charge réseau, il vous appartient de l’estimer correctement.
Nous verrons qu’il existe plusieurs façons de déterminer la charge d’un serveur, de plus ou moins pertinentes, sachant que plus l’algorithme de détermination de charge est complexe plus vos serveurs LVS nécessiteront de la CPU, ne l’oubliez pas.
Dans le meilleur des mondes, des cartes Gb sur vos serveurs LVS ainsi que des machines avec un maximum de coeurs selon l’avis et le budget de votre DSI
2) Configuration de LVS
2.1) LVS : un « switch » intelligent
Les fonctionalités de base de LVS sont de répondre à un client IP qui cherche à joindre un serveur sur une IP « <ip> » en dispatchant cette demande sur divers serveurs identiques et pouvant répondre à la demande. Les protocoles possibles sont tous ceux que TCP/IP ou UDP/IP peuvent proposer. La persistance de session est ainsi assurée par IPVS en fonction de l’adresse IP de l’émetteur de la demande (niveau 4), en d’autre termes, un internaute qui est dirigé vers le serveur n°X d’une ferme web à son premier accès sera de nouveau redirigé vers le même serveur lors des accès suivants grâce à LVS.
Nous allons donc indiquer à LVS, pour chaque IPV à gérer, quels sont les serveurs rééls et composant la ferme en face de cette adresse. Nous indiquerons de plus à LVS la méthode que celui-ci devra utiliser pour « estimer » la charge d’un serveur.
Le serveur LVS « primaire » de notre cluster de LVS en FailOver se nomme un DIRECTOR.
2.2) Indiquer l’IPV de votre ferme à votre serveur LVS
Prenons le cas d’une ferme Web Classique basée sur 2 LVS en FailOver et 3 serveurs réels.
Il existe donc dans notre exemple 3 serveurs rééls, chacun avec une adresse IP réelle @1, @2 et @3. Cependant, hors de question de donner cette information aux internautes, pour eux, un seul serveur existe d’un point de vue extérieur avec une seule adresse IP @v, c’est l’adresse IP Virtuelle de votre ferme Web , ou IPV.
Cette IPV est (au moins) fixée au sein du serveur LVS grâce à l’utilitaire ipvsadm et les paquets arriveront donc en premier sur cette adresse avant d’être dispatchée sur l’un ou l’autre des serveurs réels.
Si l’adresse IP « virtuelle » pour joindre votre ferme web est 192.168.1.10, il faudra utiliser sur votre serveur LVS la commande suivante:
shell> ifconfig eth0:v0 192.168.1.10 netmask 255.255.255.0 broadcast 192.168.1.255 up
Il faudra ensuite autoriser Linux à faire transiter les paquets d’une interface à d’autres interfaces (routage de l’IPV vers les IPR – ip réelles), il faut pour cela activer l’ip forwarding. Il faut également calibrer vos serveurs LVS pour qu’ils se comportent d’une certaine façon face au protocole ARP. La raison technique est décrite dans cet article, cela consiste grossièrement à éviter que vos serveurs LVS n’interceptent des paquets qui sont en fait destinés initialement aux serveurs réels.
Voici le contenu de /etc/sysctl.conf (à minima, à adapter selon votre configuration) :
net.ipv4.icmp_echo_ignore_broadcasts = 1 net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.all.forwarding = 1 net.ipv4.conf.default.promote_secondaries = 1 net.ipv4.conf.all.promote_secondaries = 1 net.ipv4.conf.lo.forwarding=0 net.ipv4.conf.lo.arp_ignore=1 net.ipv4.conf.lo.arp_announce=2 net.ipv4.conf.all.arp_ignore=1 net.ipv4.conf.all.arp_announce=2
2.2) ipvsadm
C’est le nom de l’utilitaire qui va (généralement) nous servir à configurer dynamiquement notre serveur LVS dynamiquement, il est apporté par les distributions aux kernels > 2.2.14, et sera apporté par les rpm ipvs que vous aurez pris soin d’installer dans la négative. Sans cet utilitaire, vous ne pouvez pas configurer votre serveur LVS. Les utilitaires de configuration automatique tels que KeepAlived se basent eux aussi sur ipvsadm.
2.2.1) Indiquer la présence d’une IPV à votre serveur LVS:
shell> ipvsadm --add-service --tcp-service 192.168.1.10:80 --scheduler rr
Ceci signifie que votre serveur LVS va accepter les paquets à destination de 192.168.1.10 sur le port 80 pour les transmettre aux serveurs réels que nous allons décrire ci-dessous.
L’algorithme de répartition de charge ici est « –scheduler rr », c’est à dire du Round Robin (Un pour Un). Nous verrons en 2.4 les différents algorithmes disponibles.
2.2.2) Indiquer la présence des 3 serveurs réels à LVS :
shell> ipvsadm --add-server --tcp-service 192.168.1.10:80 --real-server 192.168.1.1:80 --masquerading --weight 10 shell> ipvsadm --add-server --tcp-service 192.168.1.10:80 --real-server 192.168.1.2:80 --masquerading --weight 10 shell> ipvsadm --add-server --tcp-service 192.168.1.10:80 --real-server 192.168.1.3:80 --masquerading --weight 10
Explications:
- –tcp-service: les paquets transmis au serveur réel seront ceux qui arrivent sur l’IPV 192.168.1.10 et le port 80 du serveur LVS
- –real-server: nos serveurs réels ont les @ip 192.168.1.1, 192.168.1.2 et 192.168.1.3, ils écoutent sur le port 80
- –masquerading: le Director va utiliser le protocole NAT pour faire transiter les flux TCP avec les serveurs réels (voir 2.3.1)
- –weight: notion de poids (de priorité pour le LoadBalancing)
Comme vous le découvrirez en 2.2.1) et en 2.2.2) , la route par défaut peut varier selon les configiurations, il se peut quand (comme dans 2.2.1) vous soyez obligé d’utiliser l’adresse du serveur LVS alors que dans d’autres cas (voir 2.2.2) vous deviez indiquer l’adresse IP de votre routeur / firewall.
2.2.3) Vérifier la prise en compte des ordres tables ipvs
shell> ipvsadm --list
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.1.10:http rr persistent 360
-> 192.168.1.1:http Route 1 2 0
-> 192.168.1.2:http Route 1 0 0
-> 192.168.1.3:http Route 1 0 0
TCP 192.168.1.10:https rr persistent 360
-> 192.168.1.1:https Route 1 0 0
-> 192.168.1.2:https Route 1 0 0
-> 192.168.1.3:https Route 1 0 0
Nous voyons dans cet exemple que les paquets qui arriveront sur l’adresse ip virtuelle 192.168.1.10 sur le port 80 (http) seront redirigés selon la règle du Round Robin (rr) sur les serveurs de la ferme, l’un après l’autre.
Remarque: Nous avons refait les mêmes définition avec le port 443 (https) pour ls connexions sécurisées de notre fermer de serveurs Web.
Remarque: A l’instant où nous passons la commande « ipvsadm -l » sur notre Director, nous constatons que 2 sessions sont établies vers le serveur physique 192.168.1.1.
2.3) Routage direct (DR) ou Translations d’adresses (NAT)
Il existe principalement deux méthodes pour établir un dialogue entre un serveur LVS et un serveur d’une ferme dont il est chargé d’assurer la balance de charge.
Une troisième méthode moins usitée est celle de l’établissement de tunnel entre les serveurs LVS et les serveurs réels (TUN), cette méthode n’est pas décrite dans cet article car très peu usitée, cf DOC en cas de besoin.
2.3.1) NAT (Network Address Translation)
Le mode NAT, le plus classique et le plus simple à mettre en oeuvre consiste à translater l’adresse IP cible (ipv) d’un paquet reçu par l’adresse réelle du serveur choisi par l’algorithme d’analyse de charge.
C’est le même principe que l’en rencontre dans tous les routeurs d’entreprise pur que les employés puissent sortir sur l’internet, le même principe que pour votre InternetBox personelle :
Il est à noter que, en plus de demander au serveur LVS de gérer la balance de charge, nous allons lui demander en permanence de retoucher les trames TCP/IP afin d’effectuer la translation de la VIP vers toutes les adresses réelles, ce qui peut s’avérer gourmand en CPU, à surveiller de près.
Remarque: Dans le cas où vous opteriez pour le NAT, il ne faudra pas oublier d’indiquer à tous les serveurs de votre ferme que la route par défaut est le Director, à savoir la patte LAN de votre serveur LVS.
Remarque: Un exemple d’implémentation de serveur LVS avec le protocole NAT est décrit dans l’exemple ci-dessus en 2.2.2).
2.3.2) DR (Direct Routing)
2.3.2.a) Présentation
Le mode DR, comme son nom le suggère, ne va pas utiliser de translation d’adresse mais va faire suivre les paquets directement au serveur désigné comme idéal par l’algorithme d’analyse de charge. Une fois le paque traité par le serveur réel, celui-ci ne va pas renvoyer la réponse au serveur LVS qui n’en a que faire mais va directement la transmettre à sa gateway comme le montre le schéma ci dessous :
On allège ainsi le LVS de la gestion de tous les flux de retour et de la gestion des translations d’adresses, c’est largement plus performant et donc c’est l’option qui doit être considérée en premier.
Pour indiquer à votre serveur LVS qu’un serveur doit répondre au protocole DR, vous devrez l’indiquer à ipvsadm avec la commande:
shell> ipvsadm --add-server --tcp-service 192.168.1.10:80 --real-server 192.168.1.1:80 --gatewaying --weight 10 shell> ipvsadm --add-server --tcp-service 192.168.1.10:80 --real-server 192.168.1.2:80 --gatewaying --weight 10 shell> ipvsadm --add-server --tcp-service 192.168.1.10:80 --real-server 192.168.1.3:80 --gatewaying --weight 10
2.2.2.b) Problématique du routage
Nous sommes donc dans ce cas là dans une problématique de routage pur. Le serveur LVS va router le paquet ayant pour adresse cible l’IPV vers un des serveurs rééls, c’est là que les ennuis commencent : étant donné que l’adresse cible est l’IPV et que le serveur réel possède une autre adresse ip, l’adresse IP réelle,il va en toute logique refuser le paquet. Pour pallier à ce problème, nous allons simplement rajouter, sur tous les serveurs rééls de la ferme, une adresse ip secondaire (alias) qui sera l’IPV. Attention, il ne faut surtout pas rajouter cet alias à une carte ethernet du serveur car auquel cas, des trames sortiront sur le réseau (brodcast) de tous les serveurs avec la même IPV, vous aurez alors des conflits d’IP sur tout le média => catastrophe, plus rien ne fonctionnera.
Pour pallier à ce problème, il suffit d’ajouter l’alias à la loopback qui ne s’annonce pas sur les réseaux par définition mais qui permettra à un serveur réel de considérer que un paque à destination de l’IPV est bien pour lui.
Généralement, il suffit d’aller modifier le fichier /etc/sysconfig/network/ifcfg-lo tel que :
#DESC de l'IPV de votre ferme :
IPADDR_0=192.168.1.10
NETMASK_0=255.255.255.255 NETWORK_0=192.168.1.0 BROADCAST_0=192.168.1.255
#---------------------------------- IPADDR=127.0.0.1 NETMASK=255.0.0.0 NETWORK=127.0.0.0 BROADCAST=127.255.255.255 STARTMODE=onboot USERCONTROL=no FIREWALL=no
Remarque: Dans le cas où vous opteriez pour le DR, il ne faudra pas oublier d’indiquer à tous les serveurs de votre ferme que la route par défaut est l’adresse IP de la patte interne de votre routeur / firewall.
2.3) Algorithmes d’analyse de charge (RR, WRR, …)
Un algorithme de répartition de charge est à indiquer à votre serveur LVS lorsque vous créez une IPV (un cluster) grâce au commutateur –scheduller (voir 2.2.1))
Les algorithmes d’analyse de répartition de charge des IPVS sont larges, en voici un bref descriptif des plus usités:
- rr (Round-Robin): Répartition 1 pourt 1. Un internaute par serveur à tour de role, c’est la distribution équitable des demandes sur les serveurs, la plus basique et la moins gourmande.
- wrr (Weighted Round-Robin): Même répartition que « rr » mais en donnant plus de charge aux serveurs affectés de poids supérieurs.
- lc (Least Connected): La répartition de charge s’éffectue sur le mode rr mais en prenant en compte prioritairement les serveurs qui possèdent le moins de connexions actives à un instant « t ».
- wlc (Weighted Least Connected): Même répartition que « lc » mais en donnant plus de charge aux serveurs affectés de poids supérieurs.
D’autres algorithmes plus rares d’utilisation existent, consulter la doc pour plus d’informations
Rappel: le protocole d’analyse de charge est à utiliser avec ipvsadm lors de la définition d’un Cluster sur le Director et en fin de commande (voir 2.2.1)
2.4) LVS /FailOver :
Evidement, si votre serveur de répartition de charge ne répond plus, quelle qu’en soit la raison, inutile d’avoir une ferme de site web en dessous si votre solution de HA s’arrête ici. Pour pallier à cela, il vous faut installer une couche supplémentaire qui gère cette notion de Haute Disponibilité et la possibilité de démarrer rapidement dynamiquement un serveur secondaire si le primaire ne répond plus. Deux grandes voies se dessinent : HeartBeat et KeepAlived. Pour des raisons purement subjectives nous avons choisi KeepAlived alors que HeartBeart rempli strictement le même rôle… Il fallait bien en choisir un
KeepAlived apporte la configuration automatique du serveur LVS, et oui, tout ce que vous avez lu est à mettre à la poubelle, c’était pour tester votre attention
(envoyer les insultes à contact@edfgdf.fr svp, c’est très tendance).
En fait KeepAlived apporte la configuration automatique du serveur et la gestion d’un serveur en FailOver de votre Director, ce qui vous permet aisément d’assurer totalement la haute disponibilité de vos services TCP/IP.
2.4.1) Téléchargement
2.4.2) Installation
Décompressez l’archive dans un répertoire temporaire :
shell> cd /datas/downloads/ shell> tar -zxvf keepalived-1.2.2.tar.gz
Compilez les fichiers objets en indiquant le repertoire d’installation avec
shell> ./configure --prefix=/data/keepAlived/
Vous pouvez rencontrer des erreurs à ce statde, elle ne concernent généralement que des packages manquant mais nécessaires dans votre distribution, ne les négilgez pas au risque de dysfonctionnements ultérieurs.
Linkez et terminez votre installation par
shell> make ... shell> make install ...
Voilà, KeepAlived est installé …
L’install vous amène les fichiers suivants:
- keepalived et son fichier de conf keepalived.conf (placez le de preference dans /etc/keepalived/)
- ./rc.d/keepalied pour le fichier d’init de init.d (places le dans /etc/init.d/rc3.d et créez les liens)
- genhash (un utilitaire md5 pour keepalived afin de vérifier le contenu de certains flux retournés)
A vous de disposer ces fichiers dans vos répertoires préférés pour que tout fonctionne bien.
2.4.3) Utilisation
Tout se trouve dans la configuration (élémentaire) de /etc/keepalived/keepalived.conf.
2.4.3.a) Configuration globales
Les configurations globales de keepAlived consistent principalement en la définition d’un nom (ID) pour votre serveur LVS Director et quelques informations pour envoyer des emails d’alertes tel que :
global_defs {
notification_email {
admin1@domaine.com admin2@domaine.com
}
notification_email_from director-1@domaine.com
smtp_server smtp.domaine.com
smtp_connect_timeout 30
router_id LVS1
}
routeur_id doit être unique sur les différents serveurs LVS que vous allez configurer et qui vont composer votre cluster en FailOver. Les autres paramètres sont triviaux.
2.4.3.b) Configuration du protocole de surveillance du FailOver (VRRP)
vrrp_instance VRRP1 {
state MASTER
interface eth0
virtual_router_id 50
priority 50
advert_int 1
authentication {
auth_type PASS
auth_pass 6841665145
}
virtual_ipaddress {
192.168.1.10
}
}
- state: MASTER ou BACKUP, il définit le serveur primaire (actif) de vos serveurs LVS, c’est grâce à cette information que KeepAlived saura basculer sur un serveur esclave si le master ne répond plus.
- interface: quelle est l’interface réseau dédiée à la surveillance du cluster en VRRP. On évite de positionner l’interface de production afin de ne pas perturber les temps de réponse et de déclencher une bascule à tort.
- virtual_router_id: un numéro UNIQUE pour l’ensemble de vos serveurs LVS
- priority: Désirez-vous basculer prioritairement vers un serveur plustôt qu’au autre en cas d’echec VRRP? Si non, mettez la même valeur dans tous les serveurs LVS.
- authentication: un login / pass pour que les serveurs dialogue en VRRP de façon sécurisée entre eux (il doit être identique de partout évidement…)
- virtual_ipadress: le nom est assez parlant, l’IPV ou les IPV de votre serveur LVS
- 192.168.1.1
- 192.168.1.2
- 192.168.1.3
virtual_server 192.168.1.10 80 {
delay_loop 10
lb_algo RR
lb_kind DR
persistence_timeout 360
protocol TCP
real_server 192.168.1.1 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
}
}
real_server 192.168.1.2 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
}
}
real_server 192.168.1.3 80 {
weight 1
TCP_CHECK {
connect_port 80
connect_timeout 3
}
}
}
Voici un bref descriptif de ces paramètres:
- virtual_server: l’adresse IP Virtuelle de votre serveur virtuel et son port d’écoute
- delay loop: intervalle en secondes entre les différents tests de présence des serveurs réels
- protocol: ici on utilise TCP (on peut aussi utiliser UDP dans certains cas)
- lb_algo: algorithme de LoadBalancing (rr, wrr, dr, wdrr, … : voir 2.4))
- lb_kind: méthode de routage (NAT ou DR, voir 2.3))
- real_server: définition d’un serveur réél dans cette ferme, adresse réelle et port d’écoute
- weight: poids du serveur pour load balancing
- tcp_check: on va régulièrement vérifier que le port 80 de ce serveur réel répond, et, au bout de 3 secondes en echec, on considère que le serveur est mort, le serveur LVS va alors l’éliminer dynamiquement de la ferme jusqu’à ce que celui-ci réponde de nouveau.
- HTTP_GET: Vous pourrez établir une connexion sur le port 80, récupérer une page de votre site web et en vérifier le contenu, ce qui est largement plus recommandé dans le cadre d’une Ferme Web que TCP_CHECK
- SSL_GET:Même chose que HTTP_GET mais pour le protocole HTTPS
- MISC_CHECK: Vous permet de définir des tests personalisés
Exemple HTTP_GET:
C’est l’algorithme MD5 qui va nous permettre de vérifier que le contenu d’une page ne varie pas et est réglementaire. Prenez par exemple la page /test.php de votre site web, faite lui faire une connexion à votre database, une opération élémentaire en php afin que le résultat présente par exemple « TRUE » en cas de réussite ou « FALSE » en cas d’echec.
Utilisez l’utilitaire genhash pour calculer le hash MD5 de ce retour http avec la commande suivante :
shell> genhash -s 192.168.1.1 -p 80 -u /test.php shell> 53f43f0f4f1c99c10230f5f0758915f1
Ici, la clé MD5 du résultat de cette page test est donc « 53f43f0f4f1c99c10230f5f0758915f1″. Il faut que ce fichier soit évidement sur chaque serveur réel de votre ferme.
Vous devez donc simplement remplacer la clause TCP_CHECK (voir 2.4.3.c)) par celle-ci:
HTTP_GET {
url {
path /test.php
digest 53f43f0f4f1c99c10230f5f0758915f1
}
connect_timeout 3
nb_get_retry 3
delay_before_retry 2
}
Le descriptif des paramètre est trivial … On va essayer d’aspirer http://192.168.1.1:80/test.php avec un timeout de 3 secondes et nous allons réessayer 3 fois par intevalle de 2 secondes avant de considérer un echec. Une réussite est vraie si le checksum MD5 du contenu retourné est conforme à la clé indiqué par « digest ».
Le test GET_HTTPS se configure de la même façon.
Exemple MISC_CHECK:
Imaginez que l’indication de conne santé d’un serveur réel dépende du déclanchement d’un script (qui doit retourner 1 en cas de bon fonctionnement et 0 en cas d’echec), alors la clause HTTP_CHECK sera replacée par :
MISC_CHECK { misc_path /data/scripts/mon_script.sh param1 param2 }
Assez simple à priori
2.4.4) Gestion d’un serveur LVS secondaire (« backup ») :
Dans le cadre d’un cluster en FailOver, il faut au moins un deuxième serveur LVS, sachant que vous pouvez sécuriser l’ensemble à plus que 2 serveurs dans le cluster (parano quand tu nous tiens …).
Pour ce faire, rien d’extraordinaire, il suffit simplenent de disposer d’une deuxième serveur à l’identique en configuration du Director et d’apporter les modifications suivantes au fichier /etc/keepalived/keepalived.conf :
vrrp_instance VRRP2 {
state BACKUP
interface eth0
virtual_router_id 51
priority 50
advert_int 1
authentication {
auth_type PASS
auth_pass 6841665145
}
virtual_ipaddress {
192.168.1.10
}
}
3) Utilisation de LVS et monitoring



