Aller au contenu | Aller au menu | Aller à la recherche

Installation et configuration d'un cluster

LVS Project LogoCluster ! Le mot est lancé et il fait peur !! Mot compliqué et lié à des termes abscons comme Node ou Concentrateur. Et puis, sur le marché, ça fait sérieux et ça coute cher, donc c'est clairement pas le truc à refiler à des débutants !!
... Enfin, c'est l'idée que j'en avais, car au final, c'est pas si compliqué que ça ; tout ce qu'il faut, ce sont des bonnes connaissances en réseau.

Qu'est-ce que j'appelle ici Cluster ?
Il s'agit d'un mécanisme double, permettant l'accès à une information quel que soit l'état de mes ressources. Ainsi, je veux pouvoir être en état d'accéder à ce que je souhaite même si la moitié de mon infra est morte. Pour cela, trois notions sont habitellement associés :

  • Le cluster failover qui permet de basculer sur une ressource secondaire si le serveur primaire en down
  • Le load balancer qui permet de répartir équitablement l'usage des ressources pour ne pas laisser tout s'executer sur la même (ce qui permet d'une part, de ne pas la faire flancher trop rapidement et, d'autre part, d'avoir de meilleures perfs)
  • La redondance d'information entre les ressources constituant le cluster afin de ne pas perdre de données en cas de bascule (légérement hors-sujet, je dois l'avouer, mais fortement lié à l'architecture désirée)


Un peu de vocabulaire

  • On appelle node, le serveur effectuant la tâche demandé par le client. C'est sur ce serveur que l'applicatif désiré par le client se trouve.Un peu de vocabulaire
  • On appelle node, le serveur effectuant la tâche demandé par le client. C'est sur ce serveur que l'applicatif désiré par le client se trouve.
  • On appelle concentrateur (on voit aussi le terme de directeur, parfois), le serveur prenant en charge la requête du client et la répartie en fonction de la charge (load balancer) ou de l'état des Nodes (failover).

On le voit ici (et également dans le schéma ci-dessous), le concentrateur ne fait juste office de passerelle intelligente se s'occupe que de router les paquets sur les nodes les plus adaptés. Pour l'utilisateur, c'est transparent (car il se connecte toujours via la même IP) mais il est fort probable que les divers traitements demandés soient gérés par des serveurs différents.

  • On appelle concentrateur (on voit aussi le terme de directeur, parfois), le serveur prenant en charge la requête du client et la répartie en fonction de la charge (load balancer) ou de l'état des Nodes (failover).

On le voit ici (et également dans le schéma ci-dessous), le concentrateur ne fait juste office de passerelle intelligente se s'occupe que de router les paquets sur les nodes les plus adaptés.

0. Présentation de l'infrastructure
Infrastructure Cluster Ce que je souhaite réaliser ici est l'un des usages les plus communs pour un cluster : un serveur Web doit être up 100% du temps. Pour ce faire, on monte un cluster avec 2 nodes strictement identiques dans leur configuration : même serveur Apache, même version, et même SGBDR (Car dès lors que l'on a un petit site Web, on a forcément besoin d'une base de données). La difficulté ici, est que si un node tombe,comment se passera le stockage dans le base de données ? Même question pour quand le node remontera ? Ici, on a beaucoup de chances, car MySQL gère un type de connexion Maître/Maître qui permet la mise-à-jour du cluster quel que soit le node sur lequel les données ont été écrites.
Au regard du schéma, je sens poindre une question : Oui, mais si le concentrateur tombe, comment qu'on fait ? Question très judicieuse mais qui ne sera pas abordé ici (sachez toutefois que des solutions existent). Dans le cas présent, j'ai postulé que le Concentrateur, c'est le petit frère de Rambo, il a fait le Viet-Nam, la Thailande, la Corée du Nord, alors merde, c'est pas une petit coupure de courant qui va le faire chier !!

N'ayant pas des masses de matos, j'ai cloné 2 fois la même VM sur VirtualBox de façon à avoir des machines strictement identiques. Tout juste ai-je rajouté MySQL et Apache sur les deux nodes.

1. Autoriser le transfert des paquets sur Concentrateur
Pour ceux qui ont déjà monté des gateway, cette opération devrait déjà être réalisé :-D Il s'agit juste d'autoriser le transfert des paquets du sous-réseau des nodes, vers le réseau global. En effet, comme le montre le schéma au-dessus, le concentrateur a deux interfaces pour permettre le NAT entre les deux réseaux. Du coup, il suffit d'autoriser le transfert de paquet et de rajouter une règle de NAT à iptables :

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

A noter que, dans mon cas, l'interface vers le réseau public étant eth0, ma règle iptables route les paquets vers cette interface.

2. Préparation des nodes
Dès lors que le forwarding des paquets a été autorisés, on peut tenter d'accéder au réseau global à partir des nodes (en reconfigurant /etc/resolv.conf, vous pouvez même faire vos mises à jour ;-) ).

ping 192.168.1.1

Si le ping répond comme il faut, il ne reste plus qu'à bloquer le transfert de paquets SUR cette machine, puis créer une page bidon pour tester Apache (j'ai utilisé ip addr show car l'IP apparaît bien, mais n'importe quoi fera l'affaire)

echo 0 > /proc/sys/net/ipv4/ip_forward
ip addr show > /var/www/html/index.html
service httpd restart

3. Installation load balancer
Pour la mise en place de ma solution de load balancing, comme souvent, de nombreuses possibilités s'offraient à moi. Dans le cas présent, j'ai décidé d'utiliser LVS car c'est un projet récent, sympa et bien supporté. En plus, les RPMs existent et sont déjà diffusés par Red Hat ;-)

[root@localhost ~]# yum install ipvsadm

Une fois LVS, installé, il faut charger ses modules dnas le noyau mais attention ! Des modules supplémentaires doivent être défini. En effet, ce qui rend un Concentrateur spécial et qui fait de lui plus qu'une gateway est sa capacité à définir sur quel node doit être envoyé les informations transmises. Pour cela, plusieurs algorithmes de décisions existent tels que le Round Robin (RR, accès séquentiel) ou le Weighted Round Robin (WRR, accès séquentiel ou une node de poids double est deux fois plus sollicité que les autres). Dans mon cas, j'ai décidé de rester sur du Round Robin classique.

[root@localhost ~]# modprobe ip_vs
[root@localhost ~]# modprobe ip_vs_rr
[root@localhost ~]# ipvsadm -A -t 192.168.1.35:80 -s rr
[root@localhost ~]# ipvsadm -a -t 192.168.1.35:80 -r 192.168.0.2:80 -m -w 1
[root@localhost ~]# ipvsadm -a -t 192.168.1.35:80 -r 192.168.0.3:80 -m -w 1

Je charge donc les modules nécessaires et précise à ipvsadm que l'algorithme de décision sur le port 80 (puisqu'on tente de faire un cluster avec un serveur Web) se fera sur la base de Round Robin. Ensuite, j'ajoute des serveurs à cette règle de clusters en faisant du NAT vers les ports 80 de mes deux nodes avec un poids de 1.

Comme on ne fait que du Round Robin, on n'a, a priori, pas besoin de spécifier un poids quelconque. Toutefois, par défault, LVS ne prendra pas en compte un node de poids 0 (ce qui, d'ailleurs, se tient)

Voilà, la configuration du load balancer est terminée !! Facile, non ?

4. Test avec le poste client
Il ne reste donc plus qu'à tester le fonctionnement. Pour cela, à partir du poste client (une machine hors du cluster), je lance plusieurs curl 192.168.1.35 vers le concentrateur qui redirige tout ça vers les différents nodes. Un résultat équivalent à celui ci-dessous devraient confirmer le bon fonctionnement du cluster :

iMac-de-Jean-Baptiste-Langlois:~ mithweth$ curl 192.168.1.35
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:d3:5b:e9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.2/24 brd 192.168.0.255 scope global eth0
    inet6 fe80::a00:27ff:fed3:5be9/64 scope link 
       valid_lft forever preferred_lft forever
iMac-de-Jean-Baptiste-Langlois:~ mithweth$ curl 192.168.1.35
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:6c:73:0a brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.3/24 brd 192.168.0.255 scope global eth0
    inet6 fe80::a00:27ff:fe6c:730a/64 scope link 
       valid_lft forever preferred_lft forever

On voit bien que, alors qu'on effectue le même appel, la valeur affichée est différente.

5. Haute disponibilité

A faire APRES conf du load balancer : En effet, l'idée est d'ajouter ou supprimer des enresgistrements à ipvsadm en fonction de l'état des serveurs, donc il faut qu'auparavant ipvsadm soit correctement configuré.

Dans le cas de mise en Haute Disponibilité d'un cluster, la plupart du temps, c'est Heartbeat qui est la solution recommandée. Toutefois, bien que connu et supporté, Heartbeat gère surtout l'état d'un node (up ou down) mais pas l'état d'un daemon installé sur ce node. Or, dans mon cas, je me moque de savoir si mon serveur tombe, dès lors que Apache fonctionne correctement. Pour superviser l'état de service et déclencher des scripts sous certaines conditons, j'ai pris le parti d'utiliser plutôt Mon. Celui-ci peut vérifier l'état de plusieurs daemons ou l'état de certains flux réseaux, et le signaler ou bien exécuter un script pour, par exemple, le relancer. Dans notre cas présent, il faudrait que si Apache ne répond pas, le node inhérent soit retiré de la liste de ipvsadm.
Pour installer MON, on peut très bien télécharger et recompiler les sources, mais j'ai trouvé des packages RPM de la dernière version (mon-1.2.0-8.el6.i686.rpm ou mon-1.2.0-8.el6.x86_64.rpm) que j'ai attaché à ce post. Toutefois, comme les RPMs semblent avoir été compilé avec les pieds, voici comment installer le RPM qui va bien sur votre RedHat de vos rêves ; Ne vous inquiétez pas, ça marche !! (Au moins avec ma CentOS 6.4 8-) ).

yum -y install perl-CPAN make gcc pam-devel # Installe pkg de dev
perl -MCPAN -e 'install "Time::HiRes"; install "Time::Period"; install "Convert::BER"; install "Authen::PAM"'
rpm -ivh --nodeps mon-1.2.0-8.el6.x86_64.rpm # ne pas oublier le --nodeps
yum -y remove make gcc pam-devel # desInstalle pkg de dev

Mon est désormais bien installé. Il ne reste plus qu'à configurer le fichier de configuration de Mon /etc/mon/mon.cf. Copier ainsi le fichier ci-dessous, en changeant l'IP des ondes à la ligne hostgroup

cfbasedir   = /etc/mon
pidfile     = /var/run/mon.pid
statedir    = /var/lib/mon/state.d
logdir      = /var/lib/mon/log.d
dtlogfile   = /var/lib/mon/log.d/downtime.log
alertdir    = /usr/lib64/mon/alert.d
mondir      = /usr/lib64/mon/mon.d
maxprocs    = 20
histlength  = 100
randstart   = 60s
authtype    = pam
userfile    = /etc/mon/userfile

hostgroup servers 192.168.0.2 192.168.0.3

watch servers
   service http
        interval 5s
        monitor http.monitor
        period wd {Sun-Sat}
            upalert ha.alert
            alert ha.alert

En fait, la partie importante est situé dans watch <hostgroup_name>. Ici, la configuration précise de faire le test d'état du port 80 toutes les 5 secondes du Dimanche à Samedi sur les serveurs du hostgroup et qu'en cas d'erreur lancer le script ha.alert. En cas de rétablissement après une panne, il faudra relancer le script ha.alert.

En fait, en cas de rétablissement d'un service, le script indiqué est toujours exécuté avec le paramètre -u, ce qui permet de différencier les actions à effectuer dans un seul et même script.

Ce script ha.alert n'apparait toutefois pas dans le répertoire /usr/lib64/mon/alert.d pour la simple et bonne réponse que c'est un script que j'ai fait moi-même : si un des daemons générant une réponse sur le port 80 (Apache) le script désactive l'enregistrement de ipvsadm permettant le routage vers le mode concerné. Cette désactivation consiste à changer le poids de ce routage de 1 à 0 et vice versa en cas de rétablissement du daemon.

#!/bin/sh

read SERVER
WEIGHT=0
while getopts "s:g:h:t:l:u" opt; do
  case $opt in
    u) WEIGHT=1;;
    s) SERVICE=$OPTARG;;
    *) ;;
  esac
done

GW=`grep GATEWAY /etc/sysconfig/network | cut -d = -f 2`
IFACE=`netstat -rn | grep $GW | awk '{print $NF;}'`
DFTIP=`grep IPADDR /etc/sysconfig/network-scripts/ifcfg-$IFACE | cut -d = -f 2`

logger -i -p local3.info -t mon "node $SERVER weight is now $WEIGHT"
ipvsadm -e -t $DFTIP:$SERVICE -r $SERVER:$SERVICE -m -w $WEIGHT

Il faut donc copier le script ci-dessus, le nommer ha.alert, lui donner les droits d'exécution et redémarrer mon.

chmod a+x /usr/lib64/mon/alert.d/ha.alert
service mon restart


6. Réplication de MySQL
Comme indiqué plus haut, peu importe le serveur Apache avec lequel on communique, il faut que les données échangées avec la base de données soient les mêmes pour donner l'illusion qu'un unique serveur est à l'oeuvre. Pour cela, la réplication de Maitre à Maitre de MySQL va nous aider. Tout comme Apache, il faut que la configuration des nodes concernés soit strictement la même, ainsi la configuration suivante est à reporter sur chacun des nodes.

Node 1

Ajouter la ligne suivante dans /etc/sysconfig/iptables

-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT

Ajouter les lignes suivantes dans le fichier /etc/my.cnf (Configuration MySQL)

server-id=2
log-bin=mysql-bin

On redémarre alors iptables, mysqld et on se connecte au serveur MySQL où on va créer un utilisateur spécifiquement pour la réplication (changer le <mot de passe> par le mot de passe de votre choix)

mysql> grant replication slave on *.* to 'replication'@'%' identified by '<mot de passe>';
mysql> change master to master_host='192.168.0.2', master_port=3306, master_user='replication', master_password='<mot de passe>';
mysql> slave start;



Node 2

Ajouter la ligne suivante dans /etc/sysconfig/iptables

-A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT

Ajouter les lignes suivantes dans le fichier /etc/my.cnf (Configuration MySQL)

server-id=3
log-bin=mysql-bin

On redémarre alors iptables, mysqld et on se connecte au serveur MySQL où on va créer un utilisateur spécifiquement pour la réplication (changer le <mot de passe> par le mot de passe de votre choix)

mysql> grant replication slave on *.* to 'replication'@'%' identified by '<mot de passe>';
mysql> change master to master_host='192.168.0.3', master_port=3306, master_user='replication', master_password='<mot de passe>';
mysql> slave start;


La réplication est enfin configurée ! Pour le vérifier il suffit de taper, dans la console MySQL, la commande suivante :

mysql> show slave status\G

Si, parmi les instructions retournés, les deux lignes suivantes apparaissent, c'est que la réplication est fonctionnelle.

Slave_IO_Running: Yes
Slave_SQL_Running: Yes
QR code
Jean-Baptiste Langlois

Auteur: Jean-Baptiste Langlois

Restez au courant de l'actualité et abonnez-vous au Flux RSS de cette catégorie

Commentaires (0)

Soyez le premier à réagir sur cet article

Ajouter un commentaire Fil des commentaires de ce billet

:-) ;-) :-/ :mdr: :-D :-( :-C 8-) :-O :-s :siffle: :-P :love: :oops: :money: :caca:


À voir également

Icinga avec LDAPS

Connexion en LDAPS avec Icinga

Authentification sur Icinga via un serveur LDAP nécessitant un certificat

Lire la suite

icinga-api-2.PNG

Remonter les checks Icinga grâce à Ruby

Classe Ruby permettant de remonter des informations grâce à l'interface REST de Icinga-Web

Lire la suite