Intro

Cet article présente la mise en place d'un "cluster" permettant une haute disponibilité ... Attention , ce n'est pas une répartition de charge , mais bien un basculement automatique en cas de panne d'un des deux nodes ...

Plan

  1. le matériel
  2. les distributions
  3. mysql en réplication voir aussi le billet réplication mysql
  4. apache2 / php5
  5. synchro des data
  6. heartbeat
  7. tests

Cet article est écrit au fur et à mesure de l'évolution de la mise en place de cette structure ... n'hésitez donc pas à revenir pour voir la suite de l'article ...

Le matériel

J'ai opté pour deux serveurs identiques , pour une simplicité d'administration , et de compatibilité . Les serveurs choisis sont deux PowerEdge R200 dell

La configuration choisis est la suivante :

Config Quad Code Intel Xeon 2.83Ghz Ram 4Go DD 25Go (un seul disque) 2 cartes réseaux Gbits

Définition Les serveurs seront configurés comme suite :

Nom: faramir Ip1 : 10.0.0.220 Ip2 : 192.168.0.220

Nom: boromir Ip1 : 10.0.0.221 Ip2 : 192.168.0.221

Le cluster possédera 3 adresses :

10.0.0.223 10.0.0.224 10.0.0.225

Voilà , pour le matériel , pour la disposition , les interfaces #1 en 10.0.0.x seront les adresses accessibles par le réseau local , et les interfaces #2 seront paramétrés uniquement pour les dialogues serveur<->serveur (prise de pouls ,synchro des data, replication mysql ) afin de ne pas saturer le réseau local .

Les distributions

J'ai choisi debian Etch (qui est la version stable au moment ou j'écris cet article ).

Je ne suis pas allé directement sur la version testing qui est sid , pour la simple raison que Etch suffit amplement , et de plus , je cite : Veuillez noter que les mises à jour relatives à la sécurité pour la distribution de test ne sont pas gérées par l'équipe en charge de la sécurité. En conséquence de quoi ces mises à jour ne sont soumises à aucune contrainte de temps. suite ici

L'installation de etch s'est trés bien passé , pour des raisons de simplicité , j'ai utilisé une seule partition pour la totalité du système , ce qui n'est pas forcément un bon choix , mais dans mon cas , ce sont des serveurs disponibles uniquement en interne , pas de portes ouvertes vers l'extérieur , ce qui limite de voir mon système être saturé par les log ou autres ... De plus l'espace disque est plus que suffisant , et ne risque pas de grossir prématurément au point de bloquer le système .

jusqu'ici l'installation a été rigoureusement la même sur les deux machines faramir et boromir

Une fois les systèmes installés et fonctionnels , j'ai mis en place mysql .

mysql en réplication

Edite 11/12/2009 : Voir aussi le billet réplication mysql

Mysql n'ayant pas énormément d'options de compilation , j'ai utilisé la version disponible dans les dépots ....

apt-get install mysql-server

Enfin installé sur chaque machine , vient la configuration de la réplication .

La réplication type maître->esclave , permet d'avoir une copie exacte des bases de données du serveur maître sur le serveur esclave ... les insertions doivent toujours être faites sur le poste maître sinon , la réplication est cassé .. Par contre , les requêtes de type select peuvent trés bien être faites directement sur l'esclave ou le maître .. tant que les données ne changent pas ...

Si un mauvais jour , le serveur maître tombe en panne , on bascule sur le serveur esclave qui prend le relais , et devient donc maître ... une fois l'ancien serveur maître réparé , il devient esclave afin de simplifier les choses niveau importation de données ect ...

Ici : faramir est le maître et boromir est l'esclave

Nous allons commencer par la configuration du maître

my.cnf du maître

vous allez juste commenter cette ligne afin de permettre la connexion à partir de l'esclave :

#bind-address           = 127.0.0.1

Puis vérifier que vous avez bien décommenté ces deux lignes :

server-id               = 1
log_bin                 = /var/log/mysql/mysql-bin.log

Nous allons ensuite ajouter l'utilisateur qui va se connecter au maître pour synchroniser les data ...

soit par phpmyadmin , soit directement en ligne de commande

mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'%' IDENTIFIED BY '<password>'; (Remplacer <password> par votre password!)
mysql> FLUSH PRIVILEGES; 
my.cnf de l'esclave

Vérifier que vous avez bien décommenté ces deux lignes et changer le server-id=1 par server-id=2:

server-id               = 2
log_bin                 = /var/log/mysql/mysql-bin.log

Puis ajouter en fin de fichier les lignes suivantes (a adapter à votre cas):

master-host=<adresse ip du serveur maitre>
master-user=slave_user
master-password=<password>
master-connect-retry=60

Redémarrer votre serveur mysql

/etc/init.d/mysql restart

Puis nous allons importer les données déjà présentes sur le maître ..

mysql> LOAD DATA FROM MASTER;
mysql> quit;

Enfin , nous allons démarrer notre esclave :

mysql> SLAVE START;
mysql> quit;

Il ne vous reste plus qu'à tester la réplication , en ajoutant des données sur votre serveur maître (jamais sur l'esclave)

Apache2 et PHP5

Je vais donner les grandes étapes de l'installation d'apache2 et php5 , celle-ci étant déjà expliqué dans un précédent billet .. Je vais éditer toutes les étapes qui ont été nécessaires pour que l'installation fonctionne sur une etch toute neuve .

Apache2

Récupération de l'archive

cd /usr/local/src
wget http://mirror.mkhelif.fr/apache/httpd/httpd-2.2.10.tar.gz
tar xzf httpd-2.2.10.tar.gz
rm httpd-2.2.10.tar.gz
cd httpd-2.2.10/

fichier de configuration

A adapter dans votre cas

vim my_configure

le contenu

#!/bin/sh

#Optimisation pour la compilation
export CC="gcc"
export CFLAGS="-02"

#Config des sources pour l'env
./configure --prefix=/usr/local \
	--enable-rewrite \
	--enable-so \
	--enable-cache \
	--enable-mem-cache \
	--enable-alias \
	--enable-vhost-alias \
	--enable-ssl=shared \
	--disable-status \
	--disable-cgi \
	--disable-cgid \
	--enable-unique-id \

Paquets que j'ai été obligé d'installer pour que la compilation se passe bien

apt-get install build-essential libssl-dev

Lancement de la compilation

./my_configure
make
make install
PHP5

Récupération de l'archive

cd /usr/local/src/
wget http://fr.php.net/distributions/php-5.2.6.tar.gz
tar xzf php-5.2.6.tar.gz
rm php-5.2.6.tar.gz
cd php-5.2.6/

fichier de configuration

A adapter dans votre cas

vim my_configure

le contenu

#!/bin/sh

export OPTIM=-02
./configure --prefix=/usr/local \
        --with-apxs2=/usr/local/bin/apxs \
        --with-xsl \
        --enable-soap \
        --with-gettext \
        --enable-mbstring --with-mbstring=all \
        --disable-debug \
        --enable-memory-limit \
        --enable-ftp \
        --with-mcrypt \
        --enable-zip \
        --disable-cgi \
        --enable-calendar \
        --enable-exif \
        --enable-pdo \
        --with-pdo-mysql \
        --with-mysql \
        --with-pdo-sqlite \
        --with-sqlite \
        --with-zlib \

Paquets que j'ai été obligé d'installer pour que la compilation se passe bien

apt-get install libxml2-dev libmcrypt-dev libmysqlclient15-dev libxslt1-dev

Lancement de la compilation

./my_configure
make
make install

Vérification/ajout des trois lignes suivantes dans httpd.conf

vim /usr/local/conf/httpd.conf

vérifier les lignes suiventes sont présentes et décomentés

LoadModule php5_module        modules/libphp5.so
AddType application/x-httpd-php .php .phtml
AddType application/x-httpd-php-source .phps

php.ini Par défaut , il n'y a pas de fichier php.ini de cree , les valeurs sont donc toutes par défaut , si vous souhaitez l'ajouter pour y modifier des valeurs même plus tard , vous devez le copier à partir des sources

cp /usr/local/src/php-5.2.6/php.ini-dist /usr/local/lib/php.ini

Lanceur d'apache Le "lanceur" d'apache , se trouve dans /usr/local/bin/ , et se nomme apachectl , pour que votre serveur se lance au démarrage , nous allons creer un lien dans /etc/init.d

ln -s /usr/local/bin/apachectl /etc/init.d/apache2
update-rc.d apache2 defaults

Et voilà , votre serveur web est fin prêt .. il ne vous reste plus qu'à le sécuriser et/ou activer les vhosts , ces deux points feront l'objet de future articles ...

Note: vous devez faire exactement les même manœuvres expliqués ci-dessus sur les deux serveurs

synchro des data

Pour la synchronisation , j'ai cherché une solution simple et rapide à mettre en place . Le serveur web ayant une majorité de données statiques la synchronisation peut être faite toutes les 2 minutes , cela ne posera aucun souci en cas de panne ...

Je suis d'abord allé voir du coté d'UNISON ... UNISON permet une synchronisation dans les deux sens , ce qui est un gros avantage dans certains cas , mais ici , c'est toujours le serveur maître qui va envoyer des données sur l'esclave ... de plus , je n'ai pas trouvé l'option pour supprimer les fichiers qui l'ont été sur le serveur maître , ce qui rendait impossible la suppression de fichier ... Bref UNISON ne me convient pas ...

Je suis donc parti sur une solution simple avec rsync

Dans un premier , temps , j'ai vérifié les connexions en ssh entre les deux serveurs , grace à des clef rsa . Voici le principe :

Clef RSA serveur maitre
ssh-keygen -t rsa

Taper deux ou trois fois sur "Entrée" sans entrer de pass phrase ... car le but ici , est de ne pas avoir de mot de passe à saisir ...

Puis éditer la clef public créé

cat .ssh/id_rsa.pub

Vous aller avoir cette fameuse clef sous cette forme:

ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAw+Z0uzNQndQJtOLaRC9MnLt6IVTwHVg4Am370biDHTvuFy8jImJi+DV3OkA5SgQO3ei48OnX6KP9tKWBeIY/AriNkXaXGUzmvxngMeioXWySUc1OEUQ6vRirsv5avEc8F96McfF3b6aafRO/M3hMN/RjJjoqz1vrZtFps277ivFJJLho05mHqnq3z1LuqP13Prrg8ZRQwEDr0QC7X6GGHU/KkvhSoimGQCpjEAw/+QtddMOJUE/zFbBc4W+1Uzi/ZimUKJTz3czxlrioCNBY8Ut0HbwzvMu7fgJUcIcjL5YZJ4ppn/X2EQxFCzvKgO8sM259PPOgiTgjPNLVTN0d6Q== utilisateur@faramir

Copiez là , et connectez vous sur le serveur esclave . Ouvrir / creer le fichier authorized_keys

vim .ssh/authorized_keys

Et copier la clef du serveur maître dans ce fichier ... NOTE : le nom d'hote ( ici faramir ) doit être connu sur le serveur esclave , il doit donc y avoir la ligne <adresse ip> faramir dans le fichier /etc/hosts afin de pouvoir faire la relation nom d'hote <-> adresse ip

Faites la même procédure mais dans l'autre sens , générer la clef rsa sur l'esclave , et copiez là sur le maître ...

Ainsi , les deux serveurs faramir et boromir peuvent communiquer de façon crypté sans avoir à entrer de mots de passe .

Création du script :

Un script trés simple , lancé toutes les 2 minutes , afin de synchroniser les données du serveur :

vim synchro.sh

et voici un exemple de script :

#!/bin/bash

#la synchro faramir -> boromir

rsync -avz --stats --delete --itemize-changes --partial --timeout=30 --exclude-from=/home/user/scripts/EXCLUDES.EXCL --progress -e "ssh -l util-ssh -p22 " /home/user/www/ user@<adresse id serv esclave>:www/ 2>> backup-src.error

une doc sur rsync

Ainsi , ce script , synchronise le dossier /home/user/www du serveur maitre avec le dossier /home/user/www du serveur esclave.

Ajout dans la crontab

Pour lancer le script de synchronisation toutes les deux minutes , nous allons l'ajouter dans la crontab

crontab -e

Ajouter la ligne de ce style ( a adapter dans votre cas )

  • /2 * * * * /home/user/scripts/synchro.sh >>/dev/null

Et voilà , notre script de synchronisation , sera lancé toutes les deux minutes ...

Nous avons donc à ce stade , un serveur maître et un serveur esclave avec APACHE/PHP5 fonctionnel MYSQL fonctionnel et synchroniser en temps reel le répertoire WWW synchronisé toutes les deux minutes

Il ne reste plus qu'à mettre en place la prise de pouls pour basculer automatiquement sur le serveur esclave en cas d'arrêt du serveur maître .

C'est donc ici qu'entre en jeux HEARTBEAT

HEARTBEAT

L'installation est on ne peut plus simple ....

apt-get install heartbeat

Une fois installé , il reste trois fichiers à configurer , qui se trouvent dans :

/etc/heartbeat/

Les trois fichiers sont :

  1. ha.cf
  2. haresources
  3. authkeys

Comme expliqué dans README.config

ha.cf ( paramétres de heartbeat)

voici mon fichier ha.cf:

bcast         eth1

debugfile     /var/log/ha-debug
logfile       /var/log/ha-log
logfacility   local0

keepalive     2
deadtime      10
warntime      6

udpport       694
node          faramir
node          boromir

auto_failback off

Ici , je précise l'interface qui sera utilisé pour la prise de pouls (eth1 qui correspond au réseau type : 192.168.0.0/24) , definition ensuite des fichiers de log , puis keepalive le delai entre deux battements de pouls , deadtime duré limite , qui une fois dépassé , le node sera considéré comme mort . warntime delai avant d'enregistrer dans les log , qu'un battement est en retard. udpport numéro udp du port pour la communication entre serveur ( prise de pouls ) node noms/adresses des machines faisant partie de l'ensemble . il faut absoluement que les noms de machines soient connu sur chacun des serveurs , pour en être certains , il est conseillé d'ajouter dans le fichier /etc/hosts les déclarations des machines déclaré comme node.

auto_failback off ici , le retour à la normal ne se fait que manuellement .. en effet ici , si le serveur maître tombe , le second prend le relai , les enregistrements dans la base se fait donc directement sur l'esclave , nous devons donc ensuite considérer devient maître , et le maître esclave ...

haresources ( liste des serveurs synchronisés )
faramir IPaddr::10.0.0.223 IPaddr::10.0.0.224 IPaddr::10.0.0.225

Ce fichier , défini ici quel serveur est le maître , et quelles sont les adresses ip virtuelles ... Ici , le maître est faramir , et pour accéder au serveur , l'on peut utiliser 3 adresses : 10.0.0.223 10.0.0.224 10.0.0.225

Pour executer un script en cas de défaillance , il nous suffit d'ajouter à la fin de la ligne de haresources , le nom d'un script qui peut répondre , aux commandes { start | stop | status }

Les scripts sont cherchés dans les répertoires suivant , et dans cette ordre :

/etc/heartbeat/resource.d /etc/rc.d.init.d/

Plusieurs scripts sont déjà disponible dans le répertoire resource.d

authkeys ( méthode d'authentification des machines entre elles )
auth 2
1 crc
2 md5 "le site lindev est interessant"

Ce ficher se comporte comme ceci : la premiére ligne , suivie du chiffre défini quel mode d'authentification sera utilisé . Puis chaque ligne qui comprend un chiffre , et la méthode d'authentification .

Ici , j'utilise une authentification md5 , avec le mot de passe "le site lindev est intéressant"

Voilà , ces trois fichiers doivent être rigoureusement les mêmes sur chaque serveur , le service peut ensuite être redémarré ...

Attention : l'ordre de démarrage de ce service a son importance , vous devez démarrer le maître , puis l'esclave ...

En cas de basculement , l'esclave prend le relais ... même si vous relancez le serveur maître ... Pour revenir dans l'etat initiale , relancer heartbeat sur le serveur esclave .. le maître reprendra la main.

Voilà , il ne reste plus qu'à tester en coupant la prise de pouls sur le serveur maître , l'on doit passer automatiquement sur le serveur esclave ... pour ce faire , puisque la prise de pouls s'effectue sur eth1 :

ifdown eth1

Une fois votre test terminé , réactiver eth1 :

ifup eth1

puis redémarrer le service heartbeat sur le serveur esclave .. sinon , vous allez rester sur le serveur esclave ( le node maître ne sera pas réinséré ) .

Attention: ne pas faire d'enregistrement dans la base de données pendant vos tests , sinon , la réplication sera brisé ...

En espérant que cet article vous a plu ... N'hésitez pas à commenter ..