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).
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.
Jusqu’ici pas de problème. Notre cluster est simple, il utilise seulement deux ressources. Si je rajoute par contre une deuxième VIP à mon service et que je groupe le tout c’est le début des ennuis : si je souhaite couper une des VIPs pour une opération de maintenance ou pour en changer, j’impacte mon service puisque le SERVICE aura besoin des 2 VIPs 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
============ 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: [: ] [: ] ... ............... 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.
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 ]
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
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
Nous ne sommes pas encore sur le comportement recherché qui est de pouvoir couper indépendamment une VIP sans impacter le service.
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.
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
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
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 ]
On s’approche du but… Mais il y a encore un petit détail à régler. Contrairement à la commande group, il n’y a pas d’ordre de démarrage de vos ressources. Si par exemple vous souhaitez que votre VIP soit configurée avant le SERVICE qui se met en écoute dessus, il va falloir utiliser la contrainte order.
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.
Et pourquoi un score advisory et pas un score mandatory (infini) comme pour la contrainte de colocation ?
- Avec un score infini, on indique que la VIP doit absolument démarrer avant le SERVICE : très bien c’est ce qu’on cherche. Mais cela implique que le SERVICE devra être arrêté avant de couper la VIP. On retombe sur un des problèmes précédents que l’on cherche à éviter.
- Avec un score mandatory (0), Pacemaker essaye de démarrer la VIP avant le SERVICE et de stopper la VIP après le SERVICE à condition de ne pas impacter la ressource suivante dans la contrainte définie. Clairement, en cas d’arrêt d’une des VIPs, il ne coupera pas le SERVICE.
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 !
Cluster Pacemaker : group/colocation/order sur binbash.fr
Flux RSS