Cluster Pacemaker : group/colocation/order
Dans les précédents articles sur le thème clusters/Pacemaker, nous avons aperçu rapidement une solution qui permet de regrouper les ressources sur un seul et même nœud (une VIP et son service par exemple) : l’utilisation de la commande group. J’avais alors évoqué la problématique liée à son utilisation et le fait qu’il était parfois préférable d’utiliser une solution à base de colocation/order. Le but étant d’éviter l’arrêt en cascade des ressources groupées. Je vais essayer ici de détailler la problématique et d’y apporter une solution.
Pourquoi grouper les ressources
Si vous ne groupez pas vos ressources, elles vont être lancées sur des nœuds différents (c’est le fonctionnement par défaut de Pacemaker qui va chercher à optimiser votre cluster). Si je reprends l’exemple de la VIP et de son service et que je ne groupe pas les ressources, il y a de fortes chances pour que la VIP se retrouve sur un nœud et le service sur l’autre. C’est ce qu’il se passe avec cet exemple : je déclare deux ressources VIP et SERVICE (deux ressources qui ne font rien, c’est juste pour tester le comportement du cluster).
La configuration :
property no-quorum-policy="ignore"
property stonith-enabled="false"
primitive VIP ocf:heartbeat:Dummy
primitive SERVICE ocf:heartbeat:Dummy
On obtient ce résultat visible via crm_mon :
============
Last updated: Wed Apr 17 11:15:25 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
2 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
VIP (ocf::heartbeat:Dummy): Started test-ha1
SERVICE (ocf::heartbeat:Dummy): Started test-ha2
La VIP et le SERVICE sont sur deux nœuds différents. Pour corriger ce comportement, on peut :
- Utiliser la commande group : les ressources doivent fonctionner ensemble.
- Utiliser des contraintes sur les ressources avec colocation et order : on lie une ressource à une autre.
Grouper les ressources
Une première solution est de grouper les ressources avec la commande group (attention l’ordre des ressources est important) :
group NOM_DU_GROUPE VIP SERVICE
Quand je groupe des ressources, ici la VIP et le SERVICE, je signifie que :
- La VIP et le SERVICE doivent fonctionner ensemble sur le même nœud.
- Dans cet exemple la VIP doit démarrer avant le SERVICE.
- Le SERVICE à besoin de la VIP pour fonctionner.
- Si la VIP est arrêtée (volontairement ou pas), le SERVICE s’arrête.
- L’inverse n’est pas vrai : la VIP peut fonctionner sans le SERVICE.
Je groupe ma VIP et mon SERVICE :
crm(live)configure# group MON_SERVICE_HA VIP SERVICE
crm(live)configure# commit
Et j’obtiens dans mon crm_mon :
============
Last updated: Wed Apr 17 12:52:28 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
1 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
Resource Group: MON_SERVICE_HA
VIP (ocf::heartbeat:Dummy): Started test-ha1
SERVICE (ocf::heartbeat:Dummy): Started test-ha1
J’ai le comportement recherché. Les deux ressources fonctionnent sur le même noeud. On va tester l’arrêt du SERVICE, la VIP ne doit pas s’arrêter :
root@test-ha1:~# crm resource stop SERVICE
root@test-ha1:~# crm_mon -1
============
Last updated: Wed Apr 17 12:56:47 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
1 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
Resource Group: MON_SERVICE_HA
VIP (ocf::heartbeat:Dummy): Started test-ha1
SERVICE (ocf::heartbeat:Dummy): Stopped
La VIP fonctionne toujours… Je redémarre le SERVICE et je coupe cette fois la VIP :
root@test-ha1:~# crm resource stop VIP
root@test-ha1:~# crm_mon -1
============
Last updated: Wed Apr 17 12:57:54 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
1 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
Tout a été arrêté. En effet, le SERVICE a besoin de la VIP pour fonctionner.
Pour illustrer ce problème, je reprends ma configuration précédente et je rajoute une VIP :
crm(live)configure# property no-quorum-policy="ignore"
crm(live)configure# property stonith-enabled="false"
crm(live)configure# primitive VIP1 ocf:heartbeat:Dummy
crm(live)configure# primitive VIP2 ocf:heartbeat:Dummy
crm(live)configure# primitive SERVICE ocf:heartbeat:Dummy
crm(live)configure# group MON_SERVICE_HA VIP1 VIP2 SERVICE
crm(live)configure# commit
La sortie du crm_mon :
============
Last updated: Wed Apr 17 13:10:55 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
1 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
Resource Group: MON_SERVICE_HA
VIP1 (ocf::heartbeat:Dummy): Started test-ha1
VIP2 (ocf::heartbeat:Dummy): Started test-ha1
SERVICE (ocf::heartbeat:Dummy): Started test-ha1
J’ai une intervention à faire sur la VIP2. Je souhaite l’arrêter et dans l’idéal ne pas impacter mon SERVICE qui utilise aussi la VIP1 :
root@test-ha1:~# crm resource stop VIP2
root@test-ha1:~# crm_mon -1
============
Last updated: Wed Apr 17 13:12:49 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
1 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
Resource Group: MON_SERVICE_HA
VIP1 (ocf::heartbeat:Dummy): Started test-ha1
VIP2 (ocf::heartbeat:Dummy): Stopped
SERVICE (ocf::heartbeat:Dummy): Stopped
Conclusion : ce n’est pas possible avec cette configuration. Elle est à privilégier dans le cas d’un cluster qui utilise des relations simples entre ses ressources. Dans le cas contraire, ici dans mon exemple, il est préférable d’utiliser des contraintes sur les ressources avec colocation.
Lier les ressources avec colocation
L’alternative à la commande group est la contrainte colocation : le principe est le même, on va lier des ressources entre elles. A la différence que nous allons pouvoir ici utiliser la notion de “score” pour décrire plus précisément l’emplacement des ressources entre elles. La syntaxe de la commande :
crm(live)configure# help colocation
This constraint expresses the placement relation between two
or more resources. If there are more than two resources, then the
constraint is called a resource set. Collocation resource sets have
an extra attribute to allow for sets of resources which don't depend
on each other in terms of state. The shell syntax for such sets is
to put resources in parentheses.
Usage:
...............
colocation <id> <score>: <rsc>[:<role>] <rsc>[:<role>] ...
...............
Example:
...............
colocation dummy_and_apache -inf: apache dummy
colocation c1 inf: A ( B C )
...............
Si je reprends mon exemple de configuration avec mes deux VIPs, la configuration devient :
crm(live)configure# property no-quorum-policy="ignore"
crm(live)configure# property stonith-enabled="false"
crm(live)configure# primitive VIP1 ocf:heartbeat:Dummy
crm(live)configure# primitive VIP2 ocf:heartbeat:Dummy
crm(live)configure# primitive SERVICE ocf:heartbeat:Dummy
crm(live)configure# colocation SERVICE-avec-VIP inf: VIP1 VIP2 SERVICE
crm(live)configure# commit
Quelques explications sur la syntaxe de colocation et sur la gestion du score :
- SERVICE-avec-VIP est l’id de ma contrainte.
- Le score mandatory va décrire le fonctionnement de notre contrainte : mandatory est équivalent à INFINITY (traduit par inf si vous faites un crm configure show). Cela signifie que vos ressources fonctionneront toujours ensemble. A l’inverse, si j’utilise le mot clé -INFINITY, les ressources ne seront jamais ensemble. Le mot clé advisory est lui équivalent à un score de 0 et peut se traduire par les ressources devraient fonctionner ensemble. Ce cas-là sera moins utilisé en tout cas pas seul et fera intervenir d’autres contraintes ou éléments de la configuration.
- Enfin la liste des ressources à lier… Encore une fois l’ordre est important. Dans cet exemple, je me retrouve avec le même fonctionnement que précédemment à savoir :
- Si je coupe VIP1, tout s’arrête.
- Si je coupe VIP2, SERVICE s’arrête et VIP1 fonctionne toujours.
- Si je coupe SERVICE, VIP1 et VIP2 fonctionnent toujours.
Arrêt VIP1
root@test-ha1:~# crm resource stop VIP1
root@test-ha1:~# crm_mon -1
============
Last updated: Thu Apr 18 15:23:35 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
3 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
Arrêt VIP2
root@test-ha1:~# crm resource stop VIP2
root@test-ha1:~# crm_mon -1
============
Last updated: Thu Apr 18 15:24:55 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
3 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
VIP1 (ocf::heartbeat:Dummy): Started test-ha1
Arrêt SERVICE
root@test-ha1:~# crm resource stop SERVICE
root@test-ha1:~# crm_mon -1
============
Last updated: Thu Apr 18 15:25:22 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
3 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
VIP1 (ocf::heartbeat:Dummy): Started test-ha1
VIP2 (ocf::heartbeat:Dummy): Started test-ha1
Pour y parvenir nous utilisons les parenthèses pour indiquer les ressources qui n’ont pas de dépendances entre elles. Exemple :
colocation SERVICE-avec-VIP inf: ( VIP1 VIP2 ) SERVICE
Je précise donc que :
- Je peux couper indépendamment la VIP1 et/ou la VIP2 sans impacter le SERVICE
- Si je coupe le SERVICE, les deux VIPs s’arrêtent.
Arrêt VIP1
root@test-ha1:~# crm resource stop VIP1
root@test-ha1:~# crm_mon -1
============
Last updated: Thu Apr 18 15:36:14 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
3 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
VIP2 (ocf::heartbeat:Dummy): Started test-ha1
SERVICE (ocf::heartbeat:Dummy): Started test-ha1
Arrêt VIP2
root@test-ha1:~# crm resource stop VIP2
root@test-ha1:~# crm_mon -1
============
Last updated: Thu Apr 18 15:36:45 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
3 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
VIP1 (ocf::heartbeat:Dummy): Started test-ha1
SERVICE (ocf::heartbeat:Dummy): Started test-ha1
Arrêt SERVICE
root@test-ha1:~# crm resource stop SERVICE
root@test-ha1:~# crm_mon -1
============
Last updated: Thu Apr 18 15:37:36 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
3 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
Donner un ordre de démarrage aux ressources
Pour s’assurer qu’un service démarre avant un autre, il faut utiliser la contrainte order. Comme nous l’avons vu précédemment, contrairement à la commande group, la contrainte colocation ne définit par d’ordre de démarrage (et d’arrêt) de vos ressources. Je reprends l’exemple précédent du SERVICE qui a besoin de ses deux VIPs pour fonctionner et je rajoute qu’il faut si possible (la nuance est importante) démarrer les VIPs avant le SERVICE :
order SERVICE-apres-VIPs advisory: ( VIP1 VIP2 ) SERVICE
La syntaxe est semblable à celle de colocation modulo l’interprétation des parenthèses : dans cet exemple, on indique que VIP1 et VIP2 peuvent démarrer en parallèle. En résumé :
- Je rajoute une contrainte order avec “SERVICE-apres-VIPs” comme id.
- Le SERVICE démarrera, de préférence, après les VIP1 et VIP2.
- Les VIP1 et VIP2 peuvent démarrer en parallèle.
Pour finir, la configuration finale de ce cluster :
crm(live)configure# property no-quorum-policy="ignore"
crm(live)configure# property stonith-enabled="false"
crm(live)configure# primitive VIP1 ocf:heartbeat:Dummy
crm(live)configure# primitive VIP2 ocf:heartbeat:Dummy
crm(live)configure# primitive SERVICE ocf:heartbeat:Dummy
crm(live)configure# colocation SERVICE-avec-VIP inf: ( VIP1 VIP2 ) SERVICE
crm(live)configure# order SERVICE-apres-VIP 0: ( VIP1 VIP2 ) SERVICE
crm(live)configure# commit
Je vérifie l’ordre effectif de démarrage des mes ressources :
root@test-ha1:~# grep "Initiating action" /var/log/daemon.log
Apr 19 14:01:55 test-ha1 crmd: [789]: info: te_rsc_command: Initiating action 13: start VIP1_start_0 on test-ha1 (local)
Apr 19 14:01:55 test-ha1 crmd: [789]: info: te_rsc_command: Initiating action 14: start VIP2_start_0 on test-ha1 (local)
Apr 19 14:01:55 test-ha1 crmd: [789]: info: te_rsc_command: Initiating action 15: start SERVICE_start_0 on test-ha1 (local)
Si je coupe la VIP2 par exemple, je ne dois pas impacter mon SERVICE :
root@test-ha1:~# crm resource stop VIP2
root@test-ha1:~# crm_mon -1
============
Last updated: Mon Apr 19 14:08:57 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
3 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
VIP1 (ocf::heartbeat:Dummy): Started test-ha1
SERVICE (ocf::heartbeat:Dummy): Started test-ha1
Quand je relance la VIP2, rien n’est impacté…
Si je coupe le SERVICE, dans ce cas là, tout s’arrête :
root@test-ha1:~# crm resource stop SERVICE
root@test-ha1:~# crm_mon -1
============
Last updated: Mon Apr 19 14:11:42 2012
Stack: openais
Current DC: test-ha1 - partition with quorum
Version: 1.0.9
2 Nodes configured, 2 expected votes
3 Resources configured.
============
Online: [ test-ha1 test-ha2 ]
Conclusion
J’espère avoir éclairci un peu ces notions… On peut essayer de résumer en se disant qu’il est préférable d’utiliser le couple colocation/order à la place de la commande group. Une utilisation généraliste dans le cas d’un SERVICE et de ses n VIPs serait :
colocation SERVICE-avec-VIP inf: ( VIP1 VIP2 VIPn) SERVICE
order SERVICE-apres-VIP 0: ( VIP1 VIP2 VIPn) SERVICE
Il faudra se poser la question de qui doit démarrer avant qui mais également l’impact que peut avoir l’arrêt puis la relance d’une ressource sur la ressource qui suit dans la contrainte de colocation/order. Dans l’exemple de cet article, il faudrait se demander comment se comportera le SERVICE qui a été démarré avec n VIPs si on en coupe une ? Le SERVICE devient HS (il a perdu une VIP sur laquelle il est en écoute) ? Et quand la VIP est redémarrée, le SERVICE se remet en écoute sur cette adresse ?
Bons tests !