DeuxiĂšme partie de la sĂ©rie consacrĂ©e Ă  Ansible. Cette fois nous parlerons plus en dĂ©tail de l’inventaire, Ă  quoi ça sert, comment l’organiser, comment l’exploiter, etc.

L’inventaire Ansible

L’inventaire est la liste de hosts qu’Ansible est capable de gĂ©rer. Il peut se dĂ©finir de deux façons : sous forme INI ou bien en YAML. L’inventaire par dĂ©faut est celui situĂ© dans /etc/ansible/hosts, mais celui-ci peut ĂȘtre un fichier appelĂ© Ă  la volĂ©e.

Exemple d’inventaire au format INI :

mail.example.com

[webservers]
foo.example.com
bar.example.com

[dbservers]
one.example.com
two.example.com
three.example.com

Le mĂȘme, en YAML.

all:
  hosts:
    mail.example.com:
  children:
    webservers:
      hosts:
        foo.example.com:
        bar.example.com:
    dbservers:
      hosts:
        one.example.com:
        two.example.com:
        three.example.com:

Groupement de hosts

Pour que l’inventaire soit facile Ă  maintenir et l’exĂ©cution d’Ansible cohĂ©rente, il est possible de regrouper les hosts sous diffĂ©rentes banniĂšres. De mĂȘme, vous pouvez faire des groupes de groupes pour Ă©viter de rĂ©pĂ©ter plusieurs fois les mĂȘmes Ă©lĂ©ments et ainsi potentiellement les oublier en cas de rajout.

Deux groupes par dĂ©faut existent systĂ©matiquement, qu’ils soient nommĂ©s ou non :

  • all : prend la totalitĂ© des hosts de l’inventaire
  • ungrouped : prend uniquement les hosts membres d’aucun groupe en dehors de all.

Pour grouper des hosts, il suffit d’utiliser l’instruction children qui permet de dĂ©finir la hiĂ©rarchie.

Admettons que nous avons une application dont les serveurs sont rĂ©partis Ă  plusieurs emplacements gĂ©ographiques, et avec une plateforme de production situĂ©e Ă  Paris et une prĂ©-production Ă  Lille. On pourrait concevoir l’inventaire ainsi :

all:
  hosts:
    srv1.example.com
  children:
    webservers:
      hosts:
        web1.example.com
        web2.example.com
        web3.example.com
    dbservers:
      hosts:
        db1.example.com
        db2.example.com
        db3.example.com
    paris:
      hosts:
        web1.example.com
        web3.example.com
        db1.example.com
        db3.example.com
    lille:
      hosts:
        web2.example.com
        db2.example.com
    prod:
      hosts:
        web1.example.com
        web2.example.com
        db1.example.com
        db2.example.com
    preprod:
      hosts:
        web3.example.com
        db3.example.com

Dans cet exemple, les servers webX et dbX sont rĂ©pĂ©tĂ©s entre leur rĂŽle, leur emplacement, et leur type de plateforme. L’Ă©criture suivante permet d’exploiter les sous groupes et limiter la redondance d’information.

all:
  hosts:
    srv1.example.com
  children:
    webservers:
      hosts:
        web1.example.com
        web2.example.com
        web3.example.com
    dbservers:
      hosts:
        db1.example.com
        db2.example.com
        db3.example.com
    paris:
      hosts:
        web1.example.com
        web3.example.com
        db1.example.com
        db3.example.com
    lille:
      hosts:
        web2.example.com
        db2.example.com
    prod:
      children:
        paris:
    preprod:
      children:
        lille:

Avec cet exemple, nous savons que la production est Ă  Paris et la pre-production Ă  Lille. Il suffit donc d’indiquer le groupe Paris et Lille Ă  leurs emplacements respectifs. Par contre, on garde un dĂ©doublement d’information concernant le rĂŽle technique des serveurs et leur localisation. Et si la preprod et la prod venaient Ă  s’inverser, les plateformes seraient les mĂȘmes mais les membres du groupe prod et preprod changeront.

Les groupes webservers et dbservers peuvent ĂȘtre inutiles aussi si jamais dans notre besoin, nous considĂ©rons que nous gĂ©rons les plateformes par localisation et non par rĂŽle technique.

En version INI, nous aurions le résultat suivant :

srv1.example.com #le serveur n'est pas groupé

[prod:children]
paris

[preprod:children]
lille

[webservers]
web1.example.com
web2.example.com
web3.example.com

[dbservers]
db1.example.com
db2.example.com
db3.example.com

[paris]
web1.example.com
web3.example.com
db1.example.com
db3.example.com

[lille]
web2.example.com
db2.example.com

Les variables d’inventaires

Il est parfaitement possible d’assigner des variables pour un host au sein de l’inventaire, par exemple un port d’Ă©coute, une IP, un user, etc. NĂ©anmoins, si ce besoin commence Ă  devenir trop consĂ©quent, il conviendra de recourir Ă  des fichiers sĂ©parĂ©s qui seront nativement chargĂ©s par Ansible : les group_vars et hosts_vars notamment.

Exemple d’attribution de variable Ă  un host.

[lille]
web1.example.com http_port=80
web2.example.com http_port=81

Les variables de hosts sont utiles pour dĂ©finir des informations de bas niveau tel que des configurations spĂ©cifiques SSH. Exemple pour indiquer Ă  Ansible le port et l’utilisateur de connexion :

[lille]
web1.example.com ansible_port=1234 ansible_user=user1
web2.example.com ansible_port=2222 ansible_user=user2

Group_vars et inventaires

Comme dit plus haut, si on a besoin de gĂ©rer beaucoup de variables sur un dĂ©ploiement, il conviendra d’utiliser les fichiers group_vars ou hosts_vars. Le lien entre le fichier group_vars et l’inventaire se fait avec le nom du groupe.

Exemple d’arborescence :

inventory/
    production/
        hosts #ce fichier contient l'inventaire
        group_vars/
            all.yml #ce fichier contient des variables applicables Ă  l'ensemble des hosts de l'inventaire
            webservers.yml # ce fichier contient des variables applicables uniquement aux membres du groupe webservers
            dbservers.yml # ce fichier contient des variables applicables uniquement aux membres du groupe dbservers
        hosts_vars/
            all.yml #ce fichier contient des variables applicables Ă  l'ensemble des hosts de l'inventaire
            webservers.yml # ce fichier contient des variables applicables uniquement aux membres du groupe webservers
            dbservers.yml # ce fichier contient des variables applicables uniquement aux membres du groupe dbservers
    preprod/
        hosts #ce fichier contient l'inventaire
        group_vars/
            all.yml #ce fichier contient des variables applicables Ă  l'ensemble des hosts de l'inventaire
            webservers.yml # ce fichier contient des variables applicables uniquement aux membres du groupe webservers
            dbservers.yml # ce fichier contient des variables applicables uniquement aux membres du groupe dbservers
        hosts_vars/
            all.yml #ce fichier contient des variables applicables Ă  l'ensemble des hosts de l'inventaire
            webservers.yml # ce fichier contient des variables applicables uniquement aux membres du groupe webservers
            dbservers.yml # ce fichier contient des variables applicables uniquement aux membres du groupe dbservers

La principale diffĂ©rence avec une arborescence de ce type, c’est que nous utilisons deux fichiers d’inventaire diffĂ©rents. Un pour la prod, un pour la preprod. L’inventaire est le fichier host prĂ©sent dans le sous dossier inventory/preprod et inventory/prod.

Cela change la façon dont on appellera l’inventaire lors d’une exĂ©cution Ansible.

# en prod
ansible-playbook -i inventory/production/hosts monplaybook.yml

# en preprod
ansible-playbook -i inventory/preprod/hosts monplaybook.yml

Il s’agit ainsi d’une approche diffĂ©rente de l’inventaire que nous avions fait en exemple. En effet, dans notre inventaire nous avions mis la totalitĂ© de nos serveurs de preprod et prod et deux groupes pour les diffĂ©rencier. Ces groupes auraient permis de lancer des actions en contextualisant le code (si membre du groupe prod, alors…). Avec des inventaires sĂ©parĂ©s entre prod et preprod, le code exĂ©cutĂ© peut thĂ©oriquement ĂȘtre le mĂȘme et c’est l’inventaire qui le contextualisera.

Nous verrons comment exploiter les group_vars et host_vars dans le billet qui sera dédié aux rÎles Ansible.

Points d’attention

L’inventaire est un Ă©lĂ©ment fortement structurant d’un playbook ou d’un rĂŽle Ansible. Son organisation conditionnera comment vous Ă©crirez vos procĂ©dures, c’est donc un composant qui nĂ©cessite une certaine rĂ©flexion.

Comprendre la portée des variables du host_vars et du group_vars est essentiel pour éviter des réécritures de code coûteuses en temps.

Exemples de portée de variables :

  • L’application dĂ©ployĂ©e par Ansible possĂšde des arborescences de dossier censĂ©es ĂȘtre identiques entre tous les hosts qui ont le rĂŽle “webserver” => ces valeurs sont Ă  mettre dans group_vars/webservers.yml
  • L’application dĂ©ployĂ©e par Ansible est un ensemble de plusieurs bases de donnĂ©es qui ont chacune un nom d’instance diffĂ©rent => cette valeur est Ă  mettre dans hosts_vars/dbservers.yml
  • L’application Ă©coute le port 443 en production et 4443 en preproduction => cette variable est Ă  mettre dans le group_vars avec la valeur attendue pour le contexte
  • Les serveurs web dĂ©ployĂ©s sur les hosts Ă©coutent chacun un port diffĂ©rent, un load balancer expose en frontal le port utilisĂ© par les clients => le port spĂ©cifique de chaque host est Ă  mettre dans le hosts_vars

Nous verrons dans le billet consacré aux rÎles comment exploiter les variables du group_vars et hosts_vars.

Conclusion

Nous avons donc vu ce qu’est l’inventaire et comment on peut l’organiser et l’exploiter. A titre personnel, j’ai une prĂ©fĂ©rence pour le format INI que je trouve beaucoup plus lisible que le YAML pour le coup.

Dans le prochain billet, nous rédigerons et exécuterons notre premier playbook.