Files
BaC/content/2022-11-28-Ansible-et-la-hiérarchie-des-groupes.md
2025-02-27 12:52:48 +01:00

8.5 KiB
Raw Blame History

+++ title = "Ansible et la hiérarchie des groupes" date = 2022-11-28 [taxonomies] tags = [ "ansible", "système" ] +++

Le mauvais groupe, il est hiérarchique… le bon groupe… il est hiérarchique, mais cest pas pareil.

Le bon programmeur, apparemment…

Je suis récemment tombé sur une petite particularité (certains diront un quirk) dAnsible qui ma paru suffisamment intéressant pour tenter de lexpliquer, ou au moins den expliquer ma compréhension.

Et là, la marmotte dAnsible, elle met le chocolat de lhéritage des groupes dans le papier du group_vars

Notre histoire commence un beau matin de printemps avec un playbook Ansible de bon alois qui se baladait innocemment dans la forêt enchantée du système dinformation. Ce playbook contenait de nombreuses variables et de nombreux hôtes. Toutes ces variables et ces hôtes formaient une hiérarchie complexe où beaucoup de variables se surchargeaient les unes les autres dans un ballet ininterrompu et franchement difficilement compréhensible.

Du point de vue du contrôleur (donc la machine qui fait tourner Ansible), les groupes en question servent essentiellement à organiser de manière logique les choses.

Mais du point de vue de la machine que se passe-t-il? Et du point de vue de lhôte, comment cest perçu?

Tu vas pouvoir constater que la réponse nest pas si simple que ça.

Vu de lhôte, les groupes, on sen tape

Du point de vue lhôte (donc la machine sur laquelle se connecte le contrôleur Ansible), les groupes nont que peu dimportance: ils sont vus ni plus ni moins que comme des tags et rien de plus. Dailleurs, à ma connaissance, ils ne sont accessibles quà travers la variable Ansible group_names qui contient simplement une liste, à plat donc, de tous les groupes auquel appartient lhôte. On peut très facilement récupèrer cette liste comme suit:

---

- hosts: all
  gather_facts: false
  tasks:
    - name: tamerelol
      debug:
        msg: "{{ group_names }}"

Ce qui donne ce résultat:

ok: [HP-elite-book-cuisine.buttse.cx] => {
    "msg": [
        "borg_client",
        "borgbackup",
        "webservers",
        "disabled_syslog"
    ]
}

Cela peut être pratique dans certains cas:

  • mettre à jour seulement les machines dans le groupe X
  • exécuter une commande sur lensemble des machines dans le groupe Y
  • filtrer dans un template Jinja2

Mais le fait est: du point de vue de lhôte, cest une inforamtion plate et absolument pas hiérarchisée.

Donc si quelquun vous dit que les groupes Ansible sont juste des tags, il a basiquement raison, mais seulement du point de vue de lhôte. Le contrôlleur, cest une toute autre histoire…

Vu du contrôleur, les groupes, cest la vie

Du point de vue de contrôleur en revanche, les groupes ont une très grande importance: cest eux qui déterminent la façon dont les variables vont être déterminées et appliquées aux hôtes. En gros, du point de vue des group_vars de linventaire (et seulement de linventaire, je vous rappelle quil y a dautres priorités dans Ansible, en particulier concernant les variables dhôtes, les group_vars des playbooks, jen passe et des meilleurs, la résolution est la suivante:

  • on commence par appliquer les variables qui sont dans le all (celui-ci a la priorité la plus basse donc);
  • si elles sont surchargées par des variables dans le premier niveau de linventaire, ces dernières prennent la priorité (et donc surcharge logiquement le all)
  • si des variables sont définies plus bas dans la hiérarchie des groupes, elles surchargeront logiquement le niveau de leur parent
  • et seront surchargées par les variables définies au niveau de leurs enfants

Il ny a quune petite exception à cette règle, qui peut savérer très trompeuse dans certains cas, ce sont les variables qui sont définies au même niveau dans la hiérarchie des groupes. Dans ce cas, Ansible fait une résolution dans lordre alphabétique de définition des groupes (donc les groupes en a* seront surchargés par les groupes en b*, etc…).

Concrètement, si vous avez une hiérarchie de groupes qui ressemblent à ça:

> ansible-inventory -i production.yml --graph borgbackup
@borgbackup:
  |--@borg_client:
  |  |--macbook-pro-chiottes.buttse.cx
  |  |--HP-elite-book-cuisine.buttse.cx
  |--@borg_server:
  |  |--meinbackup.buttse.cx

Vous pouvez des variables « globales » (au niveau du groupe borgbackup donc) et les surcharger éventuellement au niveau du dessous. Petite illustration. Admettons que je définisse une variable borg_vars dans group_vars/borgbackup.yml comme suit:

> cat group_vars/borgbackup.yml
---

borg_vars: "je suis le niveau le plus en haut"

Et que je définisse la même variable un peu plus «bas» dans group_vars/borg_client.yml:

> cat group_vars/borg_client.yml
---

borg_vars: "je suis le niveau du client et je surcharge le serveur"

On va tenter de voir comment cest défini derrière:

> ansible-playbook -u root -i production.yml test.yml

PLAY [all] ********************************************************************************************************************

TASK [tamerelol] **************************************************************************************************************
lundi 28 novembre 2022  10:03:20 +0100 (0:00:00.032)       0:00:00.032 ********
ok: [meinbackup.buttse.cx] => {
    "msg": "je suis le niveau le plus en haut"
}
ok: [HP-elite-book-cuisine.buttse.cx] => {
    "msg": "je suis le niveau du client et je surcharge le serveur"
}
ok: [macbook-pro-chiottes.buttse.cx] => {
    "msg": "je suis le niveau du client et je surcharge le serveur"
}

Comme tu peux le constater, la hiérarchie des groupes a bien été respectée pour surcharger la variable borg_vars. Évidemment, sil y avait eu un groupe en dessous de borg_client, on aurait aussi pu surchager la variable en question dedans aussi et ça aurait fait à peu près le même effet.

Ce dont il faut se méfier le plus, cest si des serveurs sont définis en même temps sur plusieurs niveaux. Dans ce cas, on revient au cas initiale (résolution dans lordre alphabéique). On peut le démontrer assez facilement dans notre cas en ajoutant lhôte meinbackup.buttse.cx directement dans le groupe borg_client. En faisant cela, on obtient bien:

ok: [meinbackup.buttse.cx] => {
    "msg": "je suis le niveau du client et je surcharge le serveur"
}

Parce que, du point de vue dAnsible, borg_client est alphabétiquement avant borgbackup. Dailleurs, borg_server étant juste après borg_client mais avant borgbackup, si jajoute cette variable dans group_vars/borg_server.yml, elle surcharge bien celle de group_vars/borg_client.yml, on constate bien que cest le cas:

> cat group_vars/borg_server.yml
---

borg_vars: "normalement, je devrais avoir la priorité pour borg_server"
> ansible-playbook -u root -i production.yml test.yml
[…]
TASK [tamerelol] **************************************************************************************************************
lundi 28 novembre 2022  10:03:20 +0100 (0:00:00.032)       0:00:00.032 ********
ok: [meinbackup.buttse.cx] => {
    "msg": "normalement, je devrais avoir la priorité pour borg_server"
}
ok: [HP-elite-book-cuisine.buttse.cx] => {
    "msg": "je suis le niveau du client et je surcharge le serveur"
}
ok: [macbook-pro-chiottes.buttse.cx] => {
    "msg": "je suis le niveau du client et je surcharge le serveur"
}
[…]

Donc si quelquun vous dit que les groupes Ansible sont effectivement hiérarchiques, il a basiquement raison, mais seulement du point de vue du contrôleur et de la définition de la précédence des variables.

Conclusage

Cest un beau bordel mine de rien ces histoires de variables Ansible. Déjà que la précédence nest pas toujours simple (je vous mets au défi de me dire de tête qui est plus prioritaire entre une variable dinventaire, une variable de playbook et une variable de groupes), Ansible en rajoute une couche avec cette histoire de précédence dans les hiérarchies de groupes et de précédence dans les noms de groupe, histoire de bien simplifier les choses pour le quidam moyen.

Bref, jespère que ça taura permis de mieux comprendre la chose et de ne pas te faire surprendre. Et surtout, on noublie pas: quand deux personnes affirment des choses contradictoires, elles ne parlent peut-être simplement pas de la même chose ou du même point de vue.