Retrouvez cet article dans : Linux Magazine 97
1. Introduction
En entreprise, certains services réseau sont considérés comme primordiaux (serveur Intranet, messagerie, annuaire...). En outre, les serveurs qui les hébergent peuvent être fortement chargés, produisant alors des temps de réponse fortement dégradés. Nous avons donc deux problèmes simultanés à résoudre : 1) une nécessité de haute-disponibilité (high-availability ou H-A) ; 2) un besoin de performance et de dimensionnement (scalability). Existe-t-il des solutions simples, gratuites et open source et qui nécessitent un investissement matériel minimal ? La réponse est oui, bien sûr ! Dans cet exposé, nous allons vous montrer pas à pas, comment créer un cluster H-A avec équilibrage de charge (load-balacing) à l’aide de seulement deux serveurs. Notez que même si la haute-disponibilité seule vous intéresse, l’ajout de la fonction d’équilibrage de charge vous permettra de vérifier que votre serveur de secours est bien lui aussi toujours fonctionnel.2. Un peu de théorie – vraiment très peu !
Un cluster (une grappe en français) est un groupe de machines rendant le même service de manière transparente pour les clients. En effet, ceux-ci ne savent pas qu’ils s’adressent à un cluster. En outre, les services activés sur les nœuds du cluster ne doivent pas non plus être " conscients " de leur appartenance à un cluster. Deux principes sont mis en œuvre pour aboutir à cette transparence : 1) Un serveur particulier, appelé " l’équilibreur de charge " (le load-balancer aussi appelé le " director ") est placé entre les clients et les nœuds du cluster. Son rôle consiste à aiguiller les requêtes du client vers un nœud particulier.
2) Si le load-balancer tombe en panne, le cluster est indisponible, donc ce serveur est redondé. Le schéma de principe devient alors :


- Si le load-balancer agit comme une passerelle pour les serveurs réels, il s’agira de mettre en place de la translation d’adresses (NAT).

- Si le load-balancer est sur le même sous-réseau que les serveurs réels, la solution la plus propice sera le Retour-Direct (DR ou Direct Return). Cette solution est plus performante, car elle décharge le load-balancer de la gestion des réponses. Elle est toutefois plus délicate à mettre en œuvre (c’est néanmoins celle qui est proposée dans cet article).

- Il existe une autre solution, moins courante, qui met en œuvre des tunnels quand on veut faire communiquer le load-balancer et les serveurs réels à travers Internet.
3. Préparation de notre plate-forme
Dans le reste de l’article, nous utiliserons deux machines nommées " N1 " et " N2 ". L’adresse réelle de ces machines sera RIP1 et RIP2, leurs valeurs réelles sont indiquées dans le schéma ci-après, mais ce que nous dirons, est, bien sûr, indépendant de ces valeurs. VIP est l’adresse IP virtuelle portée par le load-balancer. Chaque fois que vous verrez les notations

Nous supposons que les deux serveurs N1 et N2 ont été installés avec la même distribution et utilisent un noyau Linux 2.6.
Les serveurs doivent être synchronisés via NTP [NTP]. Ce pré-requis est indispensable, mais je suis sûr que tous vos serveurs sont déjà synchronisés sur un serveur de temps. ;-).
Comme service supporté par notre cluster, nous choisissons Apache, car c’est l’un des besoins les plus simples et les plus courants.
Normalement, le contenu délivré par les serveurs Apache doit être le même sur N1 et N2, mais pour tester notre équilibrage de charge, nous allons commencer par créer une page statique " personnalisée " sur chacun des serveurs.
Sous la racine du serveur Apache (sa valeur est donnée par la directive DocumentRoot dans le fichier de configuration httpd.conf), placez un fichier nommé testcluster.html et contenant la chaîne N1 pour le serveur N1 et N2 pour le serveur N2.
Rappel pour trouver le fichier de configuration de votre serveur Apache :
Tapez la commande httpd –V, puis repérez les valeurs des variables HTTPD_ROOT et SERVER_CONFIG_FILE. Si SERVER_CONFIG_FILE a pour valeur un nom de fichier absolu : bingo ! C’est le bon ! Sinon, le nom complet est donné par la concaténation des deux variables.
Au besoin, démarrez le serveur Apache sur chacun des nœuds, puis vérifier avec un navigateur que vous pouvez obtenir les pages nouvellement créées en naviguant à l’adresse réelle des serveurs.
# wget http://$RIP1/testcluster.html # wget http://$RIP2/testcluster.htmlAttention Lorsque, dans les paragraphes suivants, vous ferez des tests avec un navigateur, veillez bien à en désactiver le cache, faute de quoi, vous ne constaterez pas toujours l’effet du load-balancing. En cas de doute, la commande
4. Mise en place du load-balancer
4.1 Vérification des pré-requis
Pour réaliser cette tâche, nous allons utiliser la fonctionnalité IPVS (IP Virtual Server) qui est incluse dans le noyau 2.6, ainsi que dans le noyau 2.4, depuis la version 2.4.26. IPVS est composé d’un ensemble de modules noyau dont le rôle est de rediriger les paquets entrants vers d’autres serveurs en utilisant divers algorithmes de distribution. IPVS fait partie du projet Linux Virtual Server [LVS]. Vous pouvez vérifier que vous disposez de ces modules par la commande :# ls /lib/modules/`uname –r`/kernel/net/ipv4/ipvs/ up_vs_dh.ko ip_vs_ftp.ko ip_vs.ko ...Pour gérer le moteur IPVS, nous avons besoin d’une commande nommée
# tar xvfz ipvsadm-1.24.tar.gz # make # make install
4.2 Réalisation manuelle de l’équilibrage de charge
Nous décidons arbitrairement que la machine N1 sera le load-balancer. La machine N1 doit prendre la VIP en plus de son adresse réelle. Nous allons créer pour cela un alias sur la carteN1# ip addr add $VIP netmask 255.255.255.0 dev eth0Attention Linux fait une différence entre les adresses " aliasées " qui sont supportées par une interface virtuelle et les adresses " secondaires " qui sont portées par l’interface réelle. La commande
# ifconfig eth0:1 1.2.3.4définit une interface " aliasée "
# ip addr add 5.6.7.8 netmask 255.255.255.0 dev eth0définit une adresse IP secondaire. La commande
rr(Round-Robin) : les requêtes sont transmises à tour de rôle sur chaque nœud du cluster.wrr(Weighted Round Robin) : identique au précédent, mais peut gérer une pondération associée à chaque nœud, l’objectif étant de charger les machines proportionnellement à leur puissance.lc(Least Connection) : IPVS transmet la requête au serveur sur lequel il y a le moins de connexions actives.wlc(Weighted Least-Connection) : sa variante pondérée...lblc,lblcr,dhetsh: déterminent le nœud en fonction de l’adresse IP source ou destination.
N1# ipvsadm –A –t $VIP:80 –s rrÀ tout moment, la commande
N1# ipvsadm –L IP Virtual Server version 1.2.0 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.199:http rrPuis, on ajoute la liste des serveurs réels. On indique qu’on souhaite du Retour-Direct avec l’option
N1# ipvsadm –a –t $VIP:80 –r $RIP1:80 –gLes règles gérées par IPVS deviennent alors :
N1# ipvsadm –L IP Virtual Server version 1.2.0 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.199:http rr -> N1:http Local 1 0 0On peut alors tester que l’on peut obtenir la page
N1# ipvsadm –a –t $VIP:80 –r $RIP2:80 –gPuisque l’ordonnanceur sélectionné est le Round-Robin (
N2# ip addr add $VIP netmask 255.255.255.255 dev loMais cela ne suffit pas, il faut empêcher N2 de répondre aux requêtes ARP concernant la VIP. Pour cela, nous allons modifier les paramètres
N2# ip addr del $VIP netmask 255.255.255.255 dev lo N2# echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore N2# echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce N2# ifconfig lo:0 $VIP netmask 255.255.255.255 upVous constatez que le
# echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore # echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce # echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore # echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce # route add –host $VIP lo:0Tout d’abord, il faut savoir que, dans cet exemple, la configuration de l’interface
4.3 Gestion de la persistance des sessions
Selon l’application servie par le cluster, il faut éventuellement s’assurer qu’un client sera toujours affecté au même nœud du cluster. C’est par exemple le cas si vous utilisez PHP et que les sessions sont gérées via des fichiers locaux. IPVS sait gérer la persistance des connexions : la première requête est redirigée sur un nœud en fonction de l’algorithme d’ordonnancement sélectionné. Les autres requêtes seront assurées d’aboutir sur le même nœud. Notons que des algorithmes comme le source hashing (5. Automatisation de la gestion du load-balancer
5.1 Principe
Tel que nous l’avons mis en œuvre, notre load-balancer fonctionne... tant que tous les nœuds sont fonctionnels ! Je m’explique : que se passe-t-il si le nœud N2 est arrêté ou même si tout simplement le service Apache sur N2 est interrompu ? Le load-balancer va rediriger une requête sur deux vers N2 et retournera donc, pour ces requêtes, une erreur au client. Pour résoudre ce problème, nous allons mettre en œuvre sur le load-balancer un processus spécialisé, nommé5.2 Installation des pré-requis
Pour installer5.2.1 Installation à partir des sources
Ils sont disponibles à l’adresse suivante : http://www.ultramonkey.org/download/heartbeat/2.0.8/ Téléchargez la dernière version (ici : la 2.0.8), puis compilez-la ainsi :# tar xvfz heartbeat-2.0.8* # cd heartbeat-2.0.8 # ./configure # make # make install
5.2.2 Installation à partir des RPM
Vous pouvez préférer l’utilisation de packages " clés en main " disponibles à l’adresse http://linux-ha.org/download/index.html#2.0.8 Commencez par le package# rpm –Uvh heartbeat-pils* heartbeat-stonith* heartbeat-2.0.8* # rpm –Uvh –nodeps heartbeat-ldirectord*
5.2.3 Arborescence des répertoires et fichiers créés
Selon la méthode d’installation choisie, les fichiers de configuration sont situés sous5.2.4 Test préalable et installation des modules Perl manquants
Nous vérifions que le directeur est fonctionnel en l’exécutant manuellement :# cd /usr/local # sbin/ldirectord –d etc/ha.d/ldirectord.cf startS’il se plaint avec un message du type :
Can’t locate Mail/Send.pm in @INC (@INC contains: ..... ) at ldirectord line 3417. BEGIN failed--compilation aborted at ldirectord line 3417alors, il manque des modules Perl. Dans cet exemple, il manque le module
# perl –MCPAN –e ‘install Mail::Send’Notez que si vous n’avez jamais utilisé CPAN auparavant, vous devrez répondre à des questions pour configurer CPAN [CPAN].
5.3 Mise en œuvre
checktimeout=10 ; timeout de 10s avant de déclarer un serveur "mort"
; en cas d’échec de l’établissement de la connexion réseau
checkinterval=10 ; effectue un test de "vie" toutes les 10s
emailalert="root" ; adresse mail de l’Administrateur
emailalertfreq=0 ; une seule alerte par problème
emailalertstatus=stopping ; seules les situations d’arrêt nous intéressent
virtual=$VIP:80
# Pour vérifier le bon fonctionnement des noeuds du cluster, on
# peut définir avec les paramètres "request" et "receive", l’URL
# à obtenir et le contenu retourné.
# Nous préférons définir ce test serveur par serveur, ce qui permet
# de mieux affiner le test.
# Dans notre cas, ldirectord demande à chaque noeud la page
# "testcluster.html" et vérifie que la réponse est bien "N1" ou
# "N2" selon les noeuds.
# (le mot-clé "gate" rappelle que nous faisons du Retour-Direct)
checktype=negotiate ; test par question / réponse
real=$IP1:80 gate 1 “testcluster.html”, “N1”
real=$IP2:80 gate 1 “testcluster.html”, “N2”
service=http
checkport=80
protocol=rr ; toujours le Round-Robin
Si vous devez aussi supporter le protocole HTTPS, définissez simplement une autre rubrique N1# ipvsadm –CPuis, lançons le directeur en mode debug pour tester la configuration :
N1# cd /usr/local N1# sbin/ldirectord –d etc/ha.d/ldirectord.cf start DEBUG2: Running exec(/usr/local/sbin/ldirectord -d ldirectord.cf start) Running exec(/usr/local/sbin/ldirectord -d ldirectord.cf start) ... DEBUG2: Running system(/sbin/ipvsadm -A -t 192.168.1.199:80 -s rr ) Running system(/sbin/ipvsadm -A -t 192.168.1.199:80 -s rr ) DEBUG2: Added virtual server: 192.168.1.199:80 Added virtual server: 192.168.1.199:80 DEBUG2: Disabled server=192.168.1.61 DEBUG2: Disabled server=192.168.1.62 DEBUG2: Checking negotiate: real server=negotiate:http:tcp:192.168.1.61:80::80:1:testcluster\.html:node (virtual=tcp:192.168.1.199:80) DEBUG2: check_http: url=”http://192.168.1.61:80/index.html” virtualhost=”192.168.1.61” LWP::UserAgent::new: () LWP::UserAgent::request: () LWP::UserAgent::send_request: GET http://192.168.1.61:80/testcluster.html LWP::UserAgent::_need_proxy: Not proxied LWP::Protocol::http::request: () LWP::Protocol::collect: read 11 bytes LWP::UserAgent::request: Simple response: OKVous constaterez la mise en place des règles pour IPVS, puis les tests périodiques des serveurs réels (toutes lesDEBUG2: Running system(/sbin/ipvsadm -a -t 192.168.1.199:80 -r 192.168.1.61:80 -g -w 1)Running system(/sbin/ipvsadm -a -t 192.168.1.199:80 -r 192.168.1.61:80 -g -w 1) DEBUG2: Added real server: 192.168.1.61:80 (192.168.1.199:80) (Weight set to 1) ...
N1 # ipvsadm IP Virtual Server version 1.2.0 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.199:http rr -> N2:http Route 1 0 0 -> N1:http Local 1 0 0Puis, arrêtez le service
N2# /etc/init.d/httpd stopLors du prochain test fait par
DEBUG2: Checking negotiate: real server =negotiate:http:tcp:192.168.1.62:80::80:1: testcluster\.html:node (virtual=tcp:192.168.1.199:80) DEBUG2: check_http: url=http://192.168.1.62:80/testcluster.html virtualhost="192.168.1.62" LWP::UserAgent::new: () LWP::UserAgent::request: () LWP::UserAgent::send_request: GET http://192.168.1.62:80/testcluster.html LWP::UserAgent::_need_proxy: Not proxied LWP::Protocol:http::request: ()La commandeLWP::UserAgent::request: Simple response: Internal Server Error DEBUG2: Running system(/sbin/ipvsadm –d –t 192.168.1.199:80 –r 192.168.1.62:80)
N1 # ipvsadm –L IP Virtual Server version 1.2.0 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.199:http rr -> N1:http Local 1 0 0À tout moment, vous pouvez vérifier le bon fonctionnement d’IPVS en affichant les compteurs de répartition des paquets par la commande :
N1# ipvsadm –l --stats
5.4 Réglages de la gestion des logs d’Apache
Nous allons peaufiner notre configuration en évitant de polluer les " access logs " d’Apache avec les requêtes émises par le directeur. Sur tous les nœuds du cluster (ici N1 et N2), il faut éditer la configuration du serveur Apache et y ajouter la ligne suivante :SetEnvIf Request_URI ^/testcluster\.html$ nologPuis, il faut modifier la ligne
CustomLog logs/access_log combined env=!nologCes directives indiquent qu’il faut tout d’abord définir une variable d’environnement pour chaque requête de la forme
6. Mise en place de la haute-disponibilité
6.1 Principe
À ce stade, nous disposons d’un cluster de deux nœuds offrant le service Apache avec, sur l’un des nœuds, un directeur capable d’assurer l’équilibrage de charge. Nous avons vu que le directeur est capable de déterminer le bon ou mauvais fonctionnement des services Apache et sait adapter sa configuration en conséquence. Oui, mais, que se passe-t-il si le directeur s’arrête ou si le nœud qui l’héberge devient indisponible ? Le directeur est un SPOF (Single Point of Failure) (toute relation avec une personne existante ou ayant existé sera fortuite ;-)), il faut donc prévoir un directeur de secours. C’est là qu’intervient le dernier composant de notre architecture :- Avec la version 1,
heartbeatne gère que les clusters de deux nœuds. - Avec la version 2,
heartbeats’est étoffé, son architecture interne a été repensée et il sait maintenant gérer les clusters de seize nœuds. La configuration deheartbeatutilise maintenant un fichier XML qui est automatiquement répliqué sur les nœuds. Mais, dans cet article, nous continuerons à employer la syntaxe de la version 1 qui est compatible avec la version 2.
6.2 Installation des pré-requis
L’installation de6.3 Mise en œuvre
Cet article ne prétend pas couvrir toutes les fonctionnalités deha.cfqui définit le cluster et les méthodes de surveillance des nœuds ;haresourcesqui liste les ressources à gérer (migrer) ;authkeysqui indique la méthode d’authentification/chiffrement à utiliser pour la communication entre les nœuds.
6.3.1 Fichier ha.cf
Ce fichier décrit les paramètres de la " mécanique "
# Par quels liens, établit-on la surveillance: eth0, ttyS0 ? # et quels types de paquets doit-on émettre: bcast, mcast, ucast ? # Nous choisissons le Multicast sur eth0 et le port série # il est possible de spécifier un groupe pour le Multicast: # syntaxe: mcast [dev] [mcast group] [port] [ttl] [loop] # si le loop est “1” (au lieu de “0”) le paquet est aussi reçu en loopback mcast eth0 225.0.0.7 694 1 0 baud 19200 serial /dev/ttyS0 debugfile /var/log/ha.debug logfile /var/log/ha.log logfacility local0 # temps entre 2 battements (2 signifie 2s, sinon 2000ms) keepalive 2 # temps nécessaire avant de déclarer un noeud comme mort deadtime 10 # temps avant d’avertir dans le log warntime 6 # valeur utilisée pour le démarrage (au moins 2 fois le deadtime) initdead 60 # le nom des noeuds DOIT être celui retourné par ‘uname -n’ node N1 node N2 # “off” indique que le primaire ne retrouve pas son rôle quand il ressuscite # (c’est plus sûr de contrôler manuellement ce retour "à la normale") auto_failback offDans cet exemple, les machines N1 et N2 sont connectées par un câble série croisé (connexion " back-to-back " avec un câble NULL-Modem), ce qui permet une surveillance des plus sûres, car ne faisant pas intervenir de composants tiers comme un switch Ethernet par exemple. La valeur du timeout
6.3.2 Fichier authkeys
Ce fichier décrit le mécanisme d’authentification utilisé par les nœuds du cluster. Plusieurs méthodes sont disponibles :- le calcul d’un crc, idéal pour ses performances en cas de liaison série ;
- le chiffrement avec MD5 ou SHA-1, à l’aide d’un secret partagé.
auth 1 1 md5 "secret" 2 crc 3 sha1 “autre secret”Ici, nous utilisons la méthode " 1 ", soit MD5.
6.3.3 Fichier haresources
Notre fichierN1 IPaddr2::$VIP ldirectord(N’oubliez pas de remplacer
$VIP 32 255.255.255.255 loAinsi, si le nœud N2 doit rendre la ressource, le script
6.3.4 Configuration du nœud N2
Les fichiers6.3.5 Mise en route
Il faut arrêter l’éventuel processusN1# ip addr del $VIP dev eth0Puis, on arrête le service Apache sur le nœud N2 qui ne fait pas encore partie du cluster.
N2# /etc/init.d/httpd stopSur N1 et N2, on surveille, dans un terminal, les logs de
N?# tail –f /var/log/ha.logPuis, on lance
N1# /etc/init.d/heartbeat startVoici un extrait des logs produits par
... heartbeat[3856]: 2007/06/26_09:38:27 info: Configuration validated. Starting heartbeat 2.0.8 ... heartbeat[3857]: 2007/06/26_09:38:28 info: glib: UDP multicast heartbeat started for group 225.0.0.7 port 694 interface eth0 (ttl=1 loop=1) ... heartbeat[3857]: 2007/06/26_09:38:28 info: Local status now set to: ‘up’Quand le messageheartbeat[3857]: 2007/06/26_09:38:29 info: Link N1:eth0 up. heartbeat[3857]: 2007/06/26_09:39:28 WARN: node N2: is dead... ResourceManager[3986]: 2007/06/26_09:39:31 info: Acquiring resource group: N1 IPaddr2::$VIP ldirectord IPaddr2[4010]: 2007/06/26_09:39:31 INFO: Resource is stopped ResourceManager[3986]: 2007/06/26_09:39:31 info: Running /usr/local/etc/ha.d/resource.d/IPaddr2 $VIP startIPaddr2[4078]: 2007/06/26_09:39:32 INFO: /sbin/ip -f inet addr add $VIP/24 brd 192.168.1.255 dev eth0... IPaddr2[4069]: 2007/06/26_09:39:32 INFO: Success ResourceManager[3986]: 2007/06/26_09:39:34 info: Running /usr/local/etc/ha.d/resource.d/ldirectord start heartbeat[3857]: 2007/06/26_09:39:40 info: Local Resource acquisition completed. (none)heartbeat[3857]: 2007/06/26_09:39:40 info: local resource transition completed.
N2# /etc/init.d/heartbeat start N2# /etc/init.d/httpd start Voici un extrait des logs produits par heartbeat sur N2 : heartbeat[10331]: 2007/06/26_10:01:13 info: Configuration validated. Starting heartbeat 2.0.8 ... heartbeat[10332]: 2007/06/26_10:01:13 info: glib: UDP multicast heartbeat started for group 225.0.0.7 port 694 interface eth0 (ttl=1 loop=1) ... heartbeat[10332]: 2007/06/26_10:01:13 info: Local status now set to: ‘up’On constate que N2 voit bien le nœud N1 comme actif et qu’il considère que les ressources sont déjà prises par N1 (heartbeat[10332]: 2007/06/26_10:01:14 info: Link N1:eth0 up. ... heartbeat[10332]: 2007/06/26_10:01:14 info: Link N2:eth0 up. ... heartbeat[10332]: 2007/06/26_10:01:15 info: remote resource transition completed.heartbeat[10332]: 2007/06/26_10:01:15 info: Local Resource acquisition completed. (none) heartbeat[10332]: 2007/06/26_10:01:15 info: Initial resource acquisition complete (T_RESOURCES(them))
6.3.6 Tests de bon fonctionnement
Test 1 : arrêt du service Apache sur N2N2# /etc/init.d/httpd stopPas de surprise, comme nous l’avons déjà montré à l’étape 1, le directeur, situé sur N1, supprime N2 du cluster (vérifiez avec la commande
N2# /etc/init.d/heartbeat stopN1 détecte que N2 " disparaît ", car, dans les logs, le message suivant s’affiche :
heartbeat: WARN: node N2: is dead heartbeat: info: Dead node N2 gave up resources. heartbeat: info: Link N2:eth0 deadTest 3 : déconnexion de N1 du réseau Avant toute chose, on relance
N2# /etc/init.d/heartbeat start N2# /etc/init.d/httpd startN’oubliez pas de tester que le cluster est opérationnel, puis nous allons simuler une panne de N1 :
N1# /etc/init.d/httpd/stop N1# /etc/init.d/heartbeat stopLes logs sur N2 montrent que heartbeat a détecté la disparition de N1 et s’est attribué la VIP sur eth0 :
heartbeat: info: Received shutdown notice from ‘N1’ ... heartbeat: INFO: Removing conflicting loopback lo heartbeat: INFO: /sbin/ip –f inet addr delete $VIP dev lo heartbeat: INFO: /sbin/ip route delete $VIP dev lo heartbeat: INFO: /sbin/ip –f inet addr add $VIP/24 dev eth0 ... heartbeat: info: all HA resource acquisition completed (standby).La commande
N2# ipvsadm IP Virtual Server version 1.2.0 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.199:http rr -> node2.zereso.org:http Local 1 0 0Test 4 : N1 est à nouveau opérationnel Comme souvent avec les clusters, si la bascule en cas de panne du service redondé (ici le directeur) se passe correctement, qu’advient-il lorsque celui-ci est rendu à nouveau opérationnel ? Souvent cette opération est manuelle, ce que traduit l’option
N1# /etc/init.d/heartbeat start N1# /etc/init.d/httpd startN2 est toujours le directeur et il a détecté la présence du service Apache sur N1, ce que confirme la commande
N2# ipvsadm IP Virtual Server version 1.2.0 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.199:http rr -> node1.zereso.org:http Route 1 0 0 -> node2.zereso.org:http Local 1 0 0Mais un test à partir d’un navigateur montre qu’un affichage sur deux " tombe " en timeout : c’est normal, N1 n’a pas pris la VIP sur son interface cachée et sa configuration ARP est incorrecte. Nous reproduisons les commandes effectuées sur N2 au §4.2 :
N1# ifconfig lo:0 down N1# echo 1 > /proc/sys/net/ipv4/conf/eth0/arp_ignore N1# echo 2 > /proc/sys/net/ipv4/conf/eth0/arp_announce N1# ifconfig lo:0 $VIP netmask 255.255.255.255 upLe cluster est alors complètement fonctionnel. Notons que si maintenant nous arrêtons
6.3.7 Finalisation du démarrage
Notre configuration est presque au point. Un seul petit problème persiste : le test 4 précédent montre qu’au démarrage d’un nœud du cluster, la configuration ARP n’est pas faite et la VIP n’est pas affectée à l’interface cachée. Vous m’objecterez qu’avec un cluster de deux nœuds seulement, on peut réaliser manuellement ces opérations, mais rien ne vaut quand même une petite automatisation. Pour cela, je vous propose le script d’initialisation suivant, qui doit être copié et activé au démarrage, avant#! /bin/sh
#
# lvsdr Start/Stop network configuration for LVS with Direct-Return
#
# chkconfig: 345 74 06
# description: just set some network parameters in case this host belongs to
# a LVS cluster. We assume the cluster is managed by heartbeat and this
# host may also run heartbeat. This script must be launched before heartbeat.
#
# Source function library.
. /etc/init.d/functions
# For RedHat like distros:
# Get config.
if [ -f /etc/sysconfig/network ]; then
. /etc/sysconfig/network
else
echo $"Networking not configured - exiting"
exit 1
fi
# Check that networking is up.
if [ "$NETWORKING" = "no" ]; then
exit 0
fi
# Our stuff starts here:
prog="lvsdr"
# You can change here the Default Interface if it is not specified by IPaddr2:
DFLT_INTERFACE=eth0
declare -a VIPS INTERFS
# Try to determine the VIP and the INTERFACE if they are not set:
if [ "$VIPS" = "" ]; then
HA_INIT=/etc/init.d/heartbeat
if [ -f $HA_INIT ]; then
HA_DIR=`grep "^HA_DIR=" $HA_INIT 2>/dev/null`
HA_DIR=`echo $HA_DIR | cut -d’;’ -f1 | cut -d’=’ -f2`
LINES=(`sed -r –n \
"/IPaddr2::.*ldirectord/s/.*IPaddr2::([^[:space:]]*).*/\1/p" \
$HA_DIR/haresources | tr -s ‘\t ‘ `)
IND=0
while [ $IND -lt ${#LINES[@]} ]; do
#echo ${LINES[$IND]}
VIPS[$IND]=`echo ${LINES[$IND]} | cut -d/ -f1`
INT=`echo ${LINES[$IND]} | cut -d/ -f3`
if [ “$INT” != ${VIPS[$IND]} ]; then
INTERFS[$IND]=$INT
fi
IND=$[ $IND + 1 ]
done
fi
fi
if [ ${#VIPS[@]} -eq 0 ]; then
echo „Warning: could not determine VIP to handle in file $HA_DIR/haresources“
exit 0
fi
RETVAL=0
check_interface() {
if [ -d /proc/sys/net/ipv4/conf/$INTERFACE ]; then
return 0
fi
echo "Interface $INTERFACE not present"
return 1
}
start() {
echo -n $"Starting $prog: "
IND=0
while [ $IND -lt ${#VIPS[@]} ]; do
INTERFACE=${INTERFS[$IND]:-eth0}
if check_interface $INTERFACE; then
ip addr add ${VIPS[$IND]}/32 \
brd 255.255.255.255 dev lo 2>/dev/null
echo 1 > /proc/sys/net/ipv4/conf/$INTERFACE/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/$INTERFACE/arp_announce
fi
IND=$[ $IND + 1 ]
done
success
echo
return $RETVAL
}
stop() {
echo -n $“Stopping $prog: „
IND=0
while [ $IND -lt ${#VIPS[@]} ]; do
INTERFACE=${INTERFS[$IND]:-eth0}
if check_interface $INTERFACE; then
ip addr del ${VIPS[$IND]}/32 \
brd 255.255.255.255 dev lo 2>/dev/null
echo 0 > /proc/sys/net/ipv4/conf/$INTERFACE/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/$INTERFACE/arp_announce
fi
IND=$[ $IND + 1 ]
done
success
echo
return $RETVAL
}
status() {
ip addr show | grep „${VIPS[0]}.*lo$“ >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo „$prog is running“
else
echo „$prog is not running“
fi
return 0
}
restart() {
stop
start
}
# See how we were called.
case „$1“ in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart|reload)
restart
;;
*)
echo $“Usage: $0 {start|stop|status|restart|reload}“
exit 1
esac
exit $?
Le script est disponible à l’adresse : http://www.maje.biz/downloads/lvsdr
6.3.8 Gestion de la persistance des sessions (bis)
Au chapitre §4.3, nous avons déjà évoqué ce besoin. Dans notre nouvelle architecture, le directeur est redondé, mais qu’advient-il des sessions en cours si N1 est indisponible ? Le directeur est activé sur N2 qui démarre donc avec une table de sessions vide. Pour éviter cela, il faut lancer les commandes suivantes :N1# ipvsadm –-start-daemon master N2# ipvsadm –-start-daemon backupComment faire en sorte que ces commandes soient lancées correctement au démarrage ? Vous pouvez ajouter la commande suivante dans la fonction
ipvsadm –-start-daemon backupPuis, on modifiera le script
case "$1" in
start)
ipvsadm –-stop-daemon backup
ipvsadm –-start-daemon master
action "Starting ldirectord" $DAEMON $2 start
;;
stop)
ipvsadm –-stop-daemon master
ipvsadm –-start-daemon backup
action "Stopping ldirectord" $DAEMON $2 stop
;;
...
esac
7. Outils complémentaires
7.1 Supervision du cluster avec Ganglia
Une fois que le cluster est en production, vous pouvez mettre en œuvre l’outil Ganglia [GANG] pour visualiser l’état global du cluster, ainsi que la distribution de la charge. Ganglia charge très peu les nœuds et est hautement dimensionnable (dans notre cas, avec deux nœuds, ces qualités ne seront pas vraiment mises en évidence !).7.1.1 Architecture
Ganglia est constitué de trois composants :gmond: installé sur chaque nœud, il collecte les métriques de performances (charge CPU, occupation mémoire...)gmetad: installé uniquement sur un nœud particulier (ou n’importe quelle machine) qu’on appellera le " cluster manager ", il collecte les indicateurs mis à disposition par les démonsgmond(par multicast sur le port 8649/tcp). Notons, qu’avec une architecture plus complexe, les démonsgmetadpeuvent communiquer entre eux pour consolider les indicateurs en créant une architecture arborescente.- Une interface de consultation Web, écrite en PHP. Cette interface est à l’écoute du port 8651/tcp et reçoit les données provenant du démon local
gmetad.
7.1.2 Installation
Sur le cluster manager, installez PHP, Apache et RRDTool [RRDT]. Puis, téléchargez l’archive# tar xvfz ganglia-3.0.4.tar.gz # cd ganglia-3.0.4 # ./configure --with-gmetad # make # make installSur les autres nœuds du cluster installez uniquement
# tar xvfz ganglia-3.0.4.tar.gz # cd ganglia-3.0.4 # ./configure # make # make install(Un petit partage réseau s’impose, si vous avez beaucoup de nœuds à installer !)
7.1.3 Configuration
Le démondata_source "Mon Cluster" N1 N2Les démons
# cp gmetad/gmetad.init /etc/init.d/ # cp gmond/gmond.init /etc/init.d/puis, créez les liens symboliques adéquats avec les commandes de gestion des services de votre distribution.
7.1.4 L’interface Web
Passez en revue le contenu du fichierAlias /ganglia/ /chemin/vers/le/répertoire/web/Redémarrez Apache :
# /etc/init.d/httpd reloadVous pouvez alors accéder à la page d’accueil qui donne l’état du cluster. Vous pouvez sélectionner une période de temps spécifique ou bien obtenir les détails sur les performances de chacun des nœuds.

7.2 Exécuter des commandes sur tous les nœuds avec DSH
Nous venons de mettre en place un cluster constitué de deux nœuds, mais l’envie va vous gagner de réaliser des clusters plus ambitieux. Dans ce cas, il est fort probable que vous voudrez exécuter des commandes sur tous les nœuds du cluster. Une boucle en# dsh -a -r ssh dateexécute la commande
# ./configure # make # make install
8. Pour aller plus loin
Dans cet article, nous avons surtout insisté sur les problématiques réseau et, en particulier, sur les détails concernant la paramétrisation des piles TCP/IP des nœuds du cluster. Le cluster ainsi construit est tout à fait opérationnel, mais vous pouvez renforcer encore sa robustesse avec les techniques suivantes :- L’utilisation du plug-in
ipfail: permet de basculer les ressources, non pas quand un nœud est détecté indisponible, mais quand sa connectivité avec des machines distantes (des ping nodes) n’est plus assurée [IPFAIL] - La mise en œuvre de liens réseau redondants (bonding) : avec un seul lien réseau, la carte Ethernet et le port du switch auquel elle est connectée sont des SPOF ! Il faudrait doubler les ports ou les cartes Ethernet et connecter chaque lien à un switch différent. Le module
bonding, fourni en standard avec le noyau Linux permet de réaliser cette opération simplement, en configurant les liens en mode actif/passif ou actif/actif [HS18]. - La mise en œuvre de technique de " fencing " (que je traduirais par " extinction préventive ") : le pire cas pour un cluster de deux nœuds se produit quand chacun des nœuds considère que l’autre est indisponible. Ils décident alors d’acquérir la ressource simultanément. Imaginez les dégâts si la ressource est un système de fichiers non distribué comme ext3... Pour éviter cela, on met en place des équipements gérables à distance (power switch, cartes d’administration iLO, Drac...) qui permettent au premier nœud qui considère que l’autre est " mort " de l’éteindre électriquement. Ce procédé est appelé " STONITH " (pour Shoot The other One In The Head) avec
heartbeatet nécessite des directives supplémentaires dans le fichierha.cf.
Il y aurait en outre beaucoup à rajouter sur heartbeat, sa configuration et les commandes de gestion complémentaires. Un article ultérieur pourra montrer la nouvelle architecture de la version 2 et ses spécificités. En attendant, il ne tient plus qu’à vous d’assurer la redondance de vos services réseau !
Références
[NTP] http://tldp.org/HOWTO/TimePrecision-HOWTO/ntp.html [LVS] http://www.linuxvirtualserver.org [OCF] http://opencf.org [ARP] http://kb.linuxvirtualserver.org/wiki/Using_arp_announce/arp_ignore_to_disable_ARP [PROC] DAUDEL (Olivier), /proc et /sys, O’Reilly. [LINCLU] KOPPER (Karl), Linux Enterprise Cluster, No Starch Press. [HS18] GNU/Linux Magazine France, hors-série n°18. [CPAN] http://www.perl.com/doc/manual/html/lib/CPAN.html [HRBT] http://www.linux-ha.org [GANG] http:/ganglia.info [RRDT] http://oss.oetiker.ch/rrdtool/download.en.html [DSH] http://www.netfort.gr.jp/~dancer/software/downloads/ [IPFAIL] http://pheared.net/devel/c/ipfail/, http://www.ultramonkey.org/3/ipfail.html





Laissez une réponse
Vous devez avoir ouvert une session pour écrire un commentaire.