Comprendre la précédence des variables Ansible
AnsibleDevOps

Comprendre la précédence des variables Ansible

·10 min de lecture

Introduction

La gestion des variables Ansible peut s'avérer complexe en raison du nombre de possibilité de déclaration et leur emplacement.

ça peut entraîner des erreurs de configuration et des déploiements KO si l'ordre de priorité n'est pas correctement compris.

Cet article décrypte comment définir et prioriser les variables dans Ansible pour garantir des configurations justes.


Les sources de variables dans Ansible

Ansible permet de définir des variables à plusieurs endroits, chacune ayant un niveau de priorité. En tout, il y en a 22 !!

On ne va pas toutes les lister mais les principales. La liste complète est disponible dans la documentation officielle. (par ordre de priorité) :

  1. Variables defaults des roles : Ce sont les variables définies dans defaults/main.yml d'un role. Comme son nom l'indique, ce sont les valeurs pa rdéfaut pour éviter une erreur au lancement.
  2. Variables d'inventaire : Elles incluent les variables dans les fichiers group_vars et host_vars.
  3. Variables d'inventaire hiérarchisé : Les groupes d'inventaire enfants surchargent les variables des groupes parents.
  4. Facts : Ces valeurs sont obtenues via le module setup ou les facts personnalisés.
  5. Variables définies dans un playbook : Les variables ajoutées directement dans un playbook sous la section vars.
  6. Variables vars de roles : Ce sont les variables définies dans vars/main.yml du role.
  7. Variables passées via la ligne de commande : Celles définies avec l'option -e lors de l'exécution d'un playbook. Elles ont toujours la priorité maximale.

Savoir ou positionner ses variables

Prenons un scénario simple pour illustrer ça. Imaginons qu'on doive configurer une application web avec un port d'écoute, et que ce port (app_port) est défini à différents niveaux :

Variables par défaut des roles

Dans defaults/main.yml d'un role nommé web_app :

yaml
1defaults:
2  app_port: 8080
3

Variables d'inventaire

Dans group_vars/webservers.yml :

yaml
1app_port: 9090
2

Variables d'inventaire dans un groupe enfant (children)

Dans group_vars/production.yml, supposons que le groupe production est enfant de webservers :

yaml
1app_port: 7070
2

Variables dans un playbook

Dans le playbook principal :

yaml
1- name: Deploy application
2  hosts: webservers
3  vars:
4    app_port: 8000
5  roles:
6    - web_app
7

Variables passées via la ligne de commande

Lors de l'exécution d'Ansible :

bash
1ansible-playbook deploy.yml -e "app_port=6060"
2

Résultat

L'ordre de priorité détermine la valeur finale de app_port :

  • 8080 (defaults) est surchargé par 9090 (inventaire de webservers).
  • 9090 est surchargé par 7070 (inventaire du groupe production).
  • 7070 est ensuite surchargé par 8000 (playbook).
  • 8000 est finalement surchargé par 6060 (ligne de commande).

La valeur finale utilisée sera donc 6060.


Gestion des inventaires multi-sources et ordre ASCII

Lorsqu'on utilise des inventaires multi-sources, par exemple avec un inventaire dynamique et un statique, Ansible applique un ordre ASCII pour déterminer quelles variables sont chargées en premier. Par exemple, si vous avez les fichiers suivants dans votre répertoire d'inventaire :

  • group_vars/01-aws.yml
  • group_vars/10-static.yml

Ansible charge les variables de 01-aws.yml avant celles de 10-static.yml. ça signifie que les variables définies dans 10-static.yml prendront la priorité sur celles de 01-aws.yml. Pour exploiter cet ordre, il est recommandé de nommer vos fichiers avec un préfixe numérique ou alphabétique qui reflète leur priorité.

Exemple pratique

Dans group_vars/01-aws.yml :

yaml
1app_port: 8080
2environment: development
3

Dans group_vars/10-static.yml :

yaml
1app_port: 9090
2environment: production
3

Si vous exécutez un playbook dans le contexte de l'inventaire global, la valeur finale de app_port sera 9090, car 10-static.yml est chargé après 01-aws.yml.


Tests et validation des variables

Pour s'assurer que les variables sont correctement résolues, on peut utiliser le module debug dans un playbook. Par exemple :

yaml
1- name: Debug variable app_port
2  hosts: webservers
3  tasks:
4    - debug:
5        msg: "La valeur de app_port est {{ app_port }}"
6

Détails supplémentaires sur les sources de variables

Variables par défaut des roles

Les variables dans defaults/main.yml sont pratiques pour définir des valeurs génériques. Elles ne doivent pas contenir de valeurs critiques ou sensibles, car elles sont facilement surchargées.

Pour autant, même si vous savez que la valeur par défaut ne servira jamais, je recommande de les noter, ne serait-ce qu'à des fins de documentations pour l'exhaustivité des variables.

Variables d'inventaire

Les fichiers dans group_vars et host_vars permettent de personnaliser les variables selon des groupes ou des hôtes spécifiques. Exemple :

  • Dans group_vars/webservers.yml :
    yaml
    1app_port: 9090
    2environment: production
    3
  • Dans host_vars/web1.yml :
    yaml
    1app_port: 8081
    2

Si un hôte appartient au groupe webservers, mais qu'il a aussi une configuration dans host_vars, la configuration dans host_vars a la priorité.

Ansible Facts

Les facts sont des données dynamiques collectées via le module setup. Par exemple :

bash
1ansible web1 -m setup
2

ça retourne des informations sur la machine cible, comme l'adresse IP, la mémoire, etc. Ces facts peuvent être utilisés dans vos playbooks :

yaml
1ansible_default_ipv4.address
2

Variables passées via la ligne de commande

Les variables définies avec l'option -e (extra-vars) ont la priorité maximale. Je ne les utilise quasi jamais car ne rentrent pas dans l'idéal d'un modèle GitOps.


Quelques conseils pour vos variables

  1. Visualisez l'ordre :

    • Placez les valeurs génériques dans defaults/main.yml.
    • Utilisez group_vars pour des configurations partagées par plusieurs hôtes.
    • Spécifiez les détails propres à un hôte dans host_vars.
  2. Privilégiez la lisibilité :

    • Documentez chaque variable pour qu'on comprenne son objectif.
  3. Testez vos configurations :

    • Exécutez des tests avec le module debug pour valider les valeurs des variables.
  4. Réduisez les surcharges inutiles :

    • Essayez de ne pas définir la variable à plusieurs endroits, ou supprimez les anciennes références.

Commentaires