Contexte :

Nous allons mettre en place une solution de HA Open Source entre 2 serveur Web sans solution de loadbalaning (Type HAPorxy, F5 LTM, Alteon, …). Cette solution est basée sur Pacemaker.
Nous partirons du principe que nous avons deux machines Linux fonctionnelles (httpd1 et httpd2) sans iptables et SELinux, dans mon lab se sera deux CentOS 6.
Un point important, la résolution de nom, soit vous renseigner correctement le fichier /etc/hosts soit vous renseignez le DNS, dans ce lab j’ai utilisé /etc/hosts.

Schéma du lab :

Schéma du lab

Installation et configuration des serveurs Web :

Installation (sur les 2 serveurs) :

$ yum install -y httpd ImageMagick

Création d’une page web (sur les 2 serveurs) :

$ cd /var/www/html/

$ vi index.html
<html>
  <head>
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Expires" content="0" />
    <title>Page de Tests</title>
  </head>
  <body>
    Page du serveur <b>XX</b>
    <img src="image1.png">
    <img src="image2.png">
    <img src="image3.png">
    <img src="image4.png">
  </body>
</html>

Création des images :

Sur le httpd1

$ for i in 1 2 3 4; do convert -background red -fill black  -size 165x70  -pointsize 24  -gravity center  label:httpd1_img${i} image${i}.png; done

Sur le httpd2

$ for i in 1 2 3 4; do convert -background yellow -fill black  -size 165x70  -pointsize 24  -gravity center  label:httpd2_img${i}  image${i}.png; done

Démarrage du service web (sur les 2 serveurs) :

$ service httpd start

Note : on ne configure pas les services au démarrage car c’est le cluster qui va le gérer.

Test de bon fonctionnement des Webs :

Serveur httpd1 Page de test serveur httpd1

Serveur httpd2 Page de test serveur httpd2

Partie Haute-Disponibilité :

Arrêt d’Apache (sur les 2 serveurs) :

Sur les 2 serveurs

$ service httpd stop

Installation des pacakges (sur les 2 serveurs) :

$ yum install -y pacemaker cman pcs ccs resource-agents

Configuration du cluster :

sur un serveur, ici httpd1 :
! Déclaration du cluster
$ ccs -f /etc/cluster/cluster.conf --createcluster ClusterWeb
! Déclaration des membres du cluster
$ ccs -f /etc/cluster/cluster.conf --addnode httpd1
Node httpd1 added.
$ ccs -f /etc/cluster/cluster.conf --addnode httpd2
Node httpd2 added.

! On indique à CMAN (Cluster Management) comment dialoguer avec Pacemaker
$ ccs -f /etc/cluster/cluster.conf --addfencedev pcmk agent=fence_pcmk

$ ccs -f /etc/cluster/cluster.conf --addmethod pcmk-redirect httpd1
Method pcmk-redirect added to httpd1.

$ ccs -f /etc/cluster/cluster.conf --addmethod pcmk-redirect httpd2
Method pcmk-redirect added to httpd2.

$ ccs -f /etc/cluster/cluster.conf --addfenceinst pcmk httpd1 pcmk-redirect port=httpd1
$ ccs -f /etc/cluster/cluster.conf --addfenceinst pcmk httpd2 pcmk-redirect port=httpd2

! Dupliquer la configuration du cluster sur l'autre membre
$scp /etc/cluster/cluster.conf root@192.168.5.14:/etc/cluster/
Sur les 2 serveurs :

Un point bloquant peut être le quorum : c’est le nombre minimum de nœuds en ligne pour être capable de valider une décision. Dans le cas d’un cluster avec Pacemaker, il faut que plus de la moitié des nœuds soit en ligne. Avec un cluster à deux nœuds, il n’y a plus de quorum dès qu’un nœud est perdu. Il va donc falloir demander à Pacemaker d’ignorer le quorum dans cette situation. Le fonctionnement par défaut quand le quorum n’est pas atteint est de couper toutes les ressources !

! Désactivation du Quorum
$ echo "CMAN_QUORUM_TIMEOUT=0" >> /etc/sysconfig/cman

! Gestion des services
$ service cman start
$ service pacemaker start
$ chkconfig --level 2345 cman on
$ chkconfig --level 2345 pacemaker on
sur un serveur, ici httpd1 :

Stonith ou “Shoot The Other Node In The Head” . C’est une méthode d’isolation d’un nœud (fencing) qui pour une raison ou une autre ne répond plus. L’idée est d’éviter à tout prix le fameux split-brain qui peut amener tous vos nœuds à fournir le même service (ou à ne plus le fournir du tout). Le nœud jugé hors service sera donc, en général, redémarré ou arrêté électriquement (via IPMI par exemple). Nous n’en avons pas besoins dans notre lab.

$ pcs property set stonith-enabled=false
$ pcs property set no-quorum-policy=ignore
$ pcs resource defaults migration-threshold=1
Vérifier l’état du cluster (sur les 2 serveurs) :
$ pcs status
Cluster name: ClusterWeb
Last updated: Mon Dec 22 22:07:51 2014
Last change: Mon Dec 22 22:06:18 2014
Stack: cman
Current DC: httpd2 - partition with quorum
Version: 1.1.11-97629de
2 Nodes configured
0 Resources configured


Online: [ httpd1 httpd2 ]

Full list of resources:
Configuration Apache pour check de status (sur les 2 serveurs) :
! Ajouter la configuration du server-status
$ vi /etc/httpd/conf/httpd.conf
<Location /server-status>
SetHandler server-status
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
Déclaration des ressources (sur 1 des serveurs):
! Déclaration de la ressource avec son @IP, interval de check
$ pcs resource create IPClusterWeb ocf:heartbeat:IPaddr2 ip=192.168.5.150 cidr_netmask=32 op monitor interval=10s

! On a une préférence que le serveur httpd1 soit "maitre"
$ pcs constraint location IPClusterWeb prefers httpd1=INFINITY

! Déclaration de la ressoure Apache (service)
pcs resource create WebSite ocf:heartbeat:apache configfile=/etc/httpd/conf/httpd.conf statusurl="http://localhost/server-status" op monitor interval=1min
Vérifier l’état du cluster (sur 1 des serveurs) :
$ pcs status
Cluster name: ClusterWeb
Last updated: Mon Dec 22 22:19:53 2014
Last change: Mon Dec 22 22:18:39 2014
Stack: cman
Current DC: httpd2 - partition with quorum
Version: 1.1.11-97629de
2 Nodes configured
2 Resources configured


Online: [ httpd1 httpd2 ]

Full list of resources:

  IPClusterWeb	(ocf::heartbeat:IPaddr2):	Started httpd1
  WebSite	(ocf::heartbeat:apache):	Started httpd2

C’est bien, mais L’IP du cluster n’est pas sur le même serveur que la ressource Web …

Affiner la configuration (sur 1 des serveurs) :
! On ajoute une contrainte qui indique que les ressources IP et Web sont sur le même serveur
$ pcs constraint colocation add IPClusterWeb WebSite INFINITY

! La ressource IP serra vu Up seulement quand la ressource Web serra Up
$ pcs constraint order IPClusterWeb then WebSite
Adding IPClusterWeb WebSite (kind: Mandatory) (Options: first-action=start then-action=start)

! Vérification
$ pcs status
Cluster name: ClusterWeb
Last updated: Mon Dec 22 22:25:12 2014
Last change: Mon Dec 22 22:24:11 2014
Stack: cman
Current DC: httpd2 - partition with quorum
Version: 1.1.11-97629de
2 Nodes configured
2 Resources configured


Online: [ httpd1 httpd2 ]

Full list of resources:

  IPClusterWeb	(ocf::heartbeat:IPaddr2):	Started httpd1
  WebSite	(ocf::heartbeat:apache):	Started httpd1

La commande de status du service Apache indique qu’il est seulement démarré sur le serveurs “maitre”.

$ service httpd status

Aller à l’URL http://192.168.5.150 dans un navigateur (fonctionnement nominal) :

Page du cluster nominal

Cas de bascule

On éteint le serveur httpd1
Page du cluster bascule

$ pcs status
Cluster name: ClusterWeb
Last updated: Mon Dec 22 22:54:02 2014
Last change: Mon Dec 22 22:49:47 2014
Stack: cman
Current DC: httpd2 - partition WITHOUT quorum
Version: 1.1.11-97629de
2 Nodes configured
2 Resources configured


Node httpd1: OFFLINE (standby)
Online: [ httpd2 ]

Full list of resources:

  IPClusterWeb	(ocf::heartbeat:IPaddr2):	Started httpd2
  WebSite	(ocf::heartbeat:apache):	Started httpd2

Redémmarrage de httpd1

$ pcs status
Cluster name: ClusterWeb
Last updated: Mon Dec 22 22:57:04 2014
Last change: Mon Dec 22 22:49:47 2014
Stack: cman
Current DC: httpd2 - partition with quorum
Version: 1.1.11-97629de
2 Nodes configured
2 Resources configured


Online: [ httpd1 httpd2 ]

Full list of resources:

IPClusterWeb	(ocf::heartbeat:IPaddr2):	Started httpd1
WebSite	(ocf::heartbeat:apache):	Started httpd1

En stoppant juste le service Apache sur httpd1 la bascule n’est pas aussi franche, il y a une bonne dizaine de secondes pour que cela soit effectif.

$ pcs status
Cluster name: ClusterWeb
Last updated: Mon Dec 22 23:00:06 2014
Last change: Mon Dec 22 22:49:47 2014
Stack: cman
Current DC: httpd2 - partition with quorum
Version: 1.1.11-97629de
2 Nodes configured
2 Resources configured


Online: [ httpd1 httpd2 ]

Full list of resources:

IPClusterWeb	(ocf::heartbeat:IPaddr2):	Started httpd2
WebSite	(ocf::heartbeat:apache):	Started httpd2

Failed actions:
WebSite_monitor_60000 on httpd1 'not running' (7): call=13, status=complete, last-rc-change='Mon Dec 22 22:58:47 2014', queued=0ms, exec=0ms

Il faut faire un cleanup pour repasser sur httpd1, vu que c’est l’admin qui à stopper le service alors que c’est le cluster qui gère normalement les services.

$ crm_resource --resource WebSite --cleanup

=> Idem dans le cas du kill des process Apache !

Commandes :

! Status du cluster
$ pcs status

! Stop le Cluster
$ pcs cluster stop

! Start du Cluster
$ pcs cluster start

! Mise en pause d'un serveur
$ pcs cluster standby httpd1
$ pcs status
Cluster name: ClusterWeb
Last updated: Mon Dec 22 22:47:37 2014
Last change: Mon Dec 22 22:47:33 2014
Stack: cman
Current DC: httpd2 - partition with quorum
Version: 1.1.11-97629de
2 Nodes configured
2 Resources configured


Node httpd1: standby
Online: [ httpd2 ]

Full list of resources:

  IPClusterWeb	(ocf::heartbeat:IPaddr2):	Started httpd2
  WebSite	(ocf::heartbeat:apache):	Started httpd2
! bascule OK

! Remise en ligne du serveur
$ pcs cluster unstandby httpd1


! Affichage de la configuration
$ pcs config

! Affichage de la configuration en XML
$ pcs cluster cib

! Sauvegarde de la configuration XML dans un fichier
$ pcs cluster cib fichier-backup-de-configuration

! Restauration de configuration
$ pcs cluster cib-push fichier-backup-de-configuration

! Affichage des ressources
$ pcs resource
ou
$ crm_resource --list
 IPClusterWeb	(ocf::heartbeat:IPaddr2):	Started
 WebSite	(ocf::heartbeat:apache):	Started

! Propriété du cluster
$ pcs property
Cluster Properties:
 cluster-infrastructure: cman
 dc-version: 1.1.11-97629de
 last-lrm-refresh: 1419344527
 no-quorum-policy: ignore
 stonith-enabled: false


! Affichage des contrainte
$ # pcs constraint
Location Constraints:
  Resource: IPClusterWeb
    Enabled on: httpd2 (score:100)
    Enabled on: httpd1 (score:INFINITY)
  Resource: WebSite
    Enabled on: httpd1 (score:INFINITY)
    Enabled on: httpd2 (score:INFINITY)
Ordering Constraints:
  start IPClusterWeb then start WebSite (kind:Mandatory)
Colocation Constraints:
  IPClusterWeb with WebSite (score:INFINITY)


! Nettoyer les actions failed pour que le cluster bascule dans sa situation nominale
$ crm_resource --resource WebSite --cleanup

! Affichage des ressources "standard"
$ pcs resource standards

! Affichage des ressources "providers"
$ pcs resource providers

! Affichage des ressources "agents"
$ pcs resource agents

! Spécifique à un agent
$ pcs resource agents ocf:heartbeat

! Vérification syntaxique de la configuration
$ crm_verify -L
ou
$ pcs cluster verify

! Node sur lequel on se trouve
$ crm_node -n
httpd1


! Liste des nodes
$ crm_node -l
httpd1 httpd2

! Déplacement de ressource (dans mon lab il ne fonctionne que sur les ressources n'ayant pas de contrainte)
$ pcs resource move MaRessourceWeb httpd2

! Supprimer la configuration du cluster locale du node (attention les fichiers de configuration sont supprimés) et services arrêtés.
$ pcs cluster destroy

Informations supplémentaire

Quelques commandes Documentation officielle