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) :

1 $ yum install -y httpd ImageMagick

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

 1 $ cd /var/www/html/
 2 
 3 $ vi index.html
 4 <html>
 5   <head>
 6     <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
 7     <meta http-equiv="Pragma" content="no-cache" />
 8     <meta http-equiv="Expires" content="0" />
 9     <title>Page de Tests</title>
10   </head>
11   <body>
12     Page du serveur <b>XX</b>
13     <img src="image1.png">
14     <img src="image2.png">
15     <img src="image3.png">
16     <img src="image4.png">
17   </body>
18 </html>

Création des images :

Sur le httpd1

1 $ 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

1 $ 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) :

1 $ 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

1 $ service httpd stop

Installation des pacakges (sur les 2 serveurs) :

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

Configuration du cluster :

sur un serveur, ici httpd1 :
 1 ! Déclaration du cluster
 2 $ ccs -f /etc/cluster/cluster.conf --createcluster ClusterWeb
 3 ! Déclaration des membres du cluster
 4 $ ccs -f /etc/cluster/cluster.conf --addnode httpd1
 5 Node httpd1 added.
 6 $ ccs -f /etc/cluster/cluster.conf --addnode httpd2
 7 Node httpd2 added.
 8 
 9 ! On indique à CMAN (Cluster Management) comment dialoguer avec Pacemaker
10 $ ccs -f /etc/cluster/cluster.conf --addfencedev pcmk agent=fence_pcmk
11 
12 $ ccs -f /etc/cluster/cluster.conf --addmethod pcmk-redirect httpd1
13 Method pcmk-redirect added to httpd1.
14 
15 $ ccs -f /etc/cluster/cluster.conf --addmethod pcmk-redirect httpd2
16 Method pcmk-redirect added to httpd2.
17 
18 $ ccs -f /etc/cluster/cluster.conf --addfenceinst pcmk httpd1 pcmk-redirect port=httpd1
19 $ ccs -f /etc/cluster/cluster.conf --addfenceinst pcmk httpd2 pcmk-redirect port=httpd2
20 
21 ! Dupliquer la configuration du cluster sur l'autre membre
22 $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 !

1 ! Désactivation du Quorum
2 $ echo "CMAN_QUORUM_TIMEOUT=0" >> /etc/sysconfig/cman
3 
4 ! Gestion des services
5 $ service cman start
6 $ service pacemaker start
7 $ chkconfig --level 2345 cman on
8 $ 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.

1 $ pcs property set stonith-enabled=false
2 $ pcs property set no-quorum-policy=ignore
3 $ pcs resource defaults migration-threshold=1
Vérifier l'état du cluster (sur les 2 serveurs) :
 1 $ pcs status
 2 Cluster name: ClusterWeb
 3 Last updated: Mon Dec 22 22:07:51 2014
 4 Last change: Mon Dec 22 22:06:18 2014
 5 Stack: cman
 6 Current DC: httpd2 - partition with quorum
 7 Version: 1.1.11-97629de
 8 2 Nodes configured
 9 0 Resources configured
10 
11 
12 Online: [ httpd1 httpd2 ]
13 
14 Full list of resources:
Configuration Apache pour check de status (sur les 2 serveurs) :
1 ! Ajouter la configuration du server-status
2 $ vi /etc/httpd/conf/httpd.conf
3 <Location /server-status>
4 SetHandler server-status
5 Order deny,allow
6 Deny from all
7 Allow from 127.0.0.1
8 </Location>
Déclaration des ressources (sur 1 des serveurs):
1 ! Déclaration de la ressource avec son @IP, interval de check
2 $ pcs resource create IPClusterWeb ocf:heartbeat:IPaddr2 ip=192.168.5.150 cidr_netmask=32 op monitor interval=10s
3 
4 ! On a une préférence que le serveur httpd1 soit "maitre"
5 $ pcs constraint location IPClusterWeb prefers httpd1=INFINITY
6 
7 ! Déclaration de la ressoure Apache (service)
8 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) :
 1 $ pcs status
 2 Cluster name: ClusterWeb
 3 Last updated: Mon Dec 22 22:19:53 2014
 4 Last change: Mon Dec 22 22:18:39 2014
 5 Stack: cman
 6 Current DC: httpd2 - partition with quorum
 7 Version: 1.1.11-97629de
 8 2 Nodes configured
 9 2 Resources configured
10 
11 
12 Online: [ httpd1 httpd2 ]
13 
14 Full list of resources:
15 
16   IPClusterWeb   (ocf::heartbeat:IPaddr2):    Started httpd1
17   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) :
 1 ! On ajoute une contrainte qui indique que les ressources IP et Web sont sur le même serveur
 2 $ pcs constraint colocation add IPClusterWeb WebSite INFINITY
 3 
 4 ! La ressource IP serra vu Up seulement quand la ressource Web serra Up
 5 $ pcs constraint order IPClusterWeb then WebSite
 6 Adding IPClusterWeb WebSite (kind: Mandatory) (Options: first-action=start then-action=start)
 7 
 8 ! Vérification
 9 $ pcs status
10 Cluster name: ClusterWeb
11 Last updated: Mon Dec 22 22:25:12 2014
12 Last change: Mon Dec 22 22:24:11 2014
13 Stack: cman
14 Current DC: httpd2 - partition with quorum
15 Version: 1.1.11-97629de
16 2 Nodes configured
17 2 Resources configured
18 
19 
20 Online: [ httpd1 httpd2 ]
21 
22 Full list of resources:
23 
24   IPClusterWeb   (ocf::heartbeat:IPaddr2):    Started httpd1
25   WebSite    (ocf::heartbeat:apache):  Started httpd1

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

1 $ 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

 1 $ pcs status
 2 Cluster name: ClusterWeb
 3 Last updated: Mon Dec 22 22:54:02 2014
 4 Last change: Mon Dec 22 22:49:47 2014
 5 Stack: cman
 6 Current DC: httpd2 - partition WITHOUT quorum
 7 Version: 1.1.11-97629de
 8 2 Nodes configured
 9 2 Resources configured
10 
11 
12 Node httpd1: OFFLINE (standby)
13 Online: [ httpd2 ]
14 
15 Full list of resources:
16 
17   IPClusterWeb   (ocf::heartbeat:IPaddr2):    Started httpd2
18   WebSite    (ocf::heartbeat:apache):  Started httpd2

Redémmarrage de httpd1

 1 $ pcs status
 2 Cluster name: ClusterWeb
 3 Last updated: Mon Dec 22 22:57:04 2014
 4 Last change: Mon Dec 22 22:49:47 2014
 5 Stack: cman
 6 Current DC: httpd2 - partition with quorum
 7 Version: 1.1.11-97629de
 8 2 Nodes configured
 9 2 Resources configured
10 
11 
12 Online: [ httpd1 httpd2 ]
13 
14 Full list of resources:
15 
16 IPClusterWeb (ocf::heartbeat:IPaddr2):    Started httpd1
17 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.

 1 $ pcs status
 2 Cluster name: ClusterWeb
 3 Last updated: Mon Dec 22 23:00:06 2014
 4 Last change: Mon Dec 22 22:49:47 2014
 5 Stack: cman
 6 Current DC: httpd2 - partition with quorum
 7 Version: 1.1.11-97629de
 8 2 Nodes configured
 9 2 Resources configured
10 
11 
12 Online: [ httpd1 httpd2 ]
13 
14 Full list of resources:
15 
16 IPClusterWeb (ocf::heartbeat:IPaddr2):    Started httpd2
17 WebSite  (ocf::heartbeat:apache):  Started httpd2
18 
19 Failed actions:
20 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.

1 $ crm_resource --resource WebSite --cleanup

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

Commandes :

  1 ! Status du cluster
  2 $ pcs status
  3 
  4 ! Stop le Cluster
  5 $ pcs cluster stop
  6 
  7 ! Start du Cluster
  8 $ pcs cluster start
  9 
 10 ! Mise en pause d'un serveur
 11 $ pcs cluster standby httpd1
 12 $ pcs status
 13 Cluster name: ClusterWeb
 14 Last updated: Mon Dec 22 22:47:37 2014
 15 Last change: Mon Dec 22 22:47:33 2014
 16 Stack: cman
 17 Current DC: httpd2 - partition with quorum
 18 Version: 1.1.11-97629de
 19 2 Nodes configured
 20 2 Resources configured
 21 
 22 
 23 Node httpd1: standby
 24 Online: [ httpd2 ]
 25 
 26 Full list of resources:
 27 
 28   IPClusterWeb (ocf::heartbeat:IPaddr2):   Started httpd2
 29   WebSite  (ocf::heartbeat:apache):    Started httpd2
 30 ! bascule OK
 31 
 32 ! Remise en ligne du serveur
 33 $ pcs cluster unstandby httpd1
 34 
 35 
 36 ! Affichage de la configuration
 37 $ pcs config
 38 
 39 ! Affichage de la configuration en XML
 40 $ pcs cluster cib
 41 
 42 ! Sauvegarde de la configuration XML dans un fichier
 43 $ pcs cluster cib fichier-backup-de-configuration
 44 
 45 ! Restauration de configuration
 46 $ pcs cluster cib-push fichier-backup-de-configuration
 47 
 48 ! Affichage des ressources
 49 $ pcs resource
 50 ou
 51 $ crm_resource --list
 52  IPClusterWeb  (ocf::heartbeat:IPaddr2):   Started
 53  WebSite   (ocf::heartbeat:apache):    Started
 54 
 55 ! Propriété du cluster
 56 $ pcs property
 57 Cluster Properties:
 58  cluster-infrastructure: cman
 59  dc-version: 1.1.11-97629de
 60  last-lrm-refresh: 1419344527
 61  no-quorum-policy: ignore
 62  stonith-enabled: false
 63 
 64 
 65 ! Affichage des contrainte
 66 $ # pcs constraint
 67 Location Constraints:
 68   Resource: IPClusterWeb
 69     Enabled on: httpd2 (score:100)
 70     Enabled on: httpd1 (score:INFINITY)
 71   Resource: WebSite
 72     Enabled on: httpd1 (score:INFINITY)
 73     Enabled on: httpd2 (score:INFINITY)
 74 Ordering Constraints:
 75   start IPClusterWeb then start WebSite (kind:Mandatory)
 76 Colocation Constraints:
 77   IPClusterWeb with WebSite (score:INFINITY)
 78 
 79 
 80 ! Nettoyer les actions failed pour que le cluster bascule dans sa situation nominale
 81 $ crm_resource --resource WebSite --cleanup
 82 
 83 ! Affichage des ressources "standard"
 84 $ pcs resource standards
 85 
 86 ! Affichage des ressources "providers"
 87 $ pcs resource providers
 88 
 89 ! Affichage des ressources "agents"
 90 $ pcs resource agents
 91 
 92 ! Spécifique à un agent
 93 $ pcs resource agents ocf:heartbeat
 94 
 95 ! Vérification syntaxique de la configuration
 96 $ crm_verify -L
 97 ou
 98 $ pcs cluster verify
 99 
100 ! Node sur lequel on se trouve
101 $ crm_node -n
102 httpd1
103 
104 
105 ! Liste des nodes
106 $ crm_node -l
107 httpd1 httpd2
108 
109 ! Déplacement de ressource (dans mon lab il ne fonctionne que sur les ressources n'ayant pas de contrainte)
110 $ pcs resource move MaRessourceWeb httpd2
111 
112 ! Supprimer la configuration du cluster locale du node (attention les fichiers de configuration sont supprimés) et services arrêtés.
113 $ pcs cluster destroy

Informations supplémentaire

Quelques commandes Documentation officielle