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.