Aller au contenu
Infrastructure as Code medium

Précédence des variables Ansible : les 22 niveaux officiels (RHCE EX294)

14 min de lecture

Logo Ansible

Quand la même variable est définie à plusieurs endroits, Ansible applique une règle de précédence stricte sur 22 niveaux. Connaître cet ordre vous évite des heures de debug : non, votre group_vars/all.yml ne peut pas écraser un --extra-vars. Oui, vars/main.yml d'un rôle gagne sur vars: du play. Cette page liste les 22 niveaux officiels, du plus faible (role defaults) au plus fort (--extra-vars), avec des règles pratiques pour ne pas se tromper. Objectif explicite RHCE EX294.

C'est une page de référence, on n'apprend pas à coder en la lisant, on revient la consulter quand un comportement vous surprend.

  • L'ordre exact des 22 niveaux de précédence Ansible (du plus faible au plus fort)
  • Le regroupement par catégorie : defaults / group_vars / host_vars / play / role / task / extra
  • Les 3 règles simples qui couvrent 95 % des cas pratiques
  • --extra-vars est toujours prioritaire sur tout
  • Comment diagnostiquer quel niveau a gagné quand une variable a une valeur inattendue

Du plus faible (1) au plus fort (22) :

NiveauSourceNotes
1Command-line values (-u, -c...)Pas vraiment des variables
2roles/<role>/defaults/main.ymlDefaults d'un rôle (override naturel)
3inventory file group varsSection [group:vars] d'un inventaire INI
4inventory group_vars/allÀ côté de l'inventaire
5playbook group_vars/allÀ côté du playbook
6inventory group_vars/<group>À côté de l'inventaire, par groupe
7playbook group_vars/<group>À côté du playbook, par groupe
8inventory file host varsSection [host:vars] d'un inventaire INI
9inventory host_vars/<host>À côté de l'inventaire
10playbook host_vars/<host>À côté du playbook
11host facts / cached set_factsFacts gathered + set_fact avec cacheable: true
12play vars:Bloc vars: au niveau du play
13play vars_prompt:Variables saisies interactivement
14play vars_files:Fichiers YAML chargés par le play
15roles/<role>/vars/main.ymlVars du rôle (gagne sur le play !)
16block varsVars sur un block: (limité aux tâches du block)
17task varsVars sur une tâche (limitées à cette tâche)
18include_varsModule qui charge un fichier au runtime
19set_fact / registerVariables créées en cours d'exécution
20role (and include_role) paramsParams passés à un rôle via roles: - { role: x, var: y }
21include paramsParams passés via include_tasks/include_role
22--extra-varsLe plus fort, gagne sur tout
Fenêtre de terminal
ansible-playbook site.yml --extra-vars "service_name=production-api"

Aucun vars:, vars_files:, group_vars/, host_vars/, set_fact: ou vars/main.yml ne peut écraser ça. C'est le niveau 22.

Implication : --extra-vars est l'outil de prédilection en CI/CD pour pousser un tag de release ou un environnement au runtime, sans modifier le code.

Règle 2, Plus c'est local, plus c'est prioritaire

Section intitulée « Règle 2, Plus c'est local, plus c'est prioritaire »

L'intuition naturelle marche : une variable définie à proximité de la tâche gagne sur une variable définie plus loin :

host_vars/<host> > group_vars/<group> > group_vars/all > defaults
↑ très spécifique ↑ très générique
task vars > block vars > play vars > vars_files > group_vars
↑ ultra-local ↑ partagé

Règle 3, vars/main.yml d'un rôle gagne sur vars: du play

Section intitulée « Règle 3, vars/main.yml d'un rôle gagne sur vars: du play »

Piège classique : un rôle pose vars/main.yml (niveau 15) qui écrase vos vars: du play (niveau 12). Conséquence : si vous voulez paramétrer un rôle depuis l'extérieur, utilisez :

  • defaults/main.yml du rôle (niveau 2), peut être overridé naturellement par le caller
  • role params (niveau 20) : roles: - { role: nginx, nginx_port: 8080 }
  • --extra-vars (niveau 22)
# Pas ça : impossible à overrider naturellement depuis le play
# roles/nginx/vars/main.yml :
nginx_port: 80 # ← niveau 15, écrase vars: du play
# Préférer : defaults pour permettre l'override
# roles/nginx/defaults/main.yml :
nginx_port: 80 # ← niveau 2, le caller peut écraser facilement

Reprenons l'exemple validé sur le lab 15-ecrire-code-precedence-variables :

# group_vars/dbservers.yml ← niveau 6 ou 7
priority_test: "from_group_vars_dbservers"
# group_vars/all.yml ← niveau 4 ou 5
priority_test: "from_group_vars_all"
# playbook.yml
- name: Test precedence
hosts: db1.lab
vars:
priority_test: "from_play_vars" # ← niveau 12
tasks:
- debug:
msg: "priority_test = {{ priority_test }}"

Sans --extra-vars :

"msg": "priority_test = from_play_vars"

vars: du play (12) gagne sur group_vars/dbservers (6/7) qui gagne sur group_vars/all (4/5).

Avec --extra-vars "priority_test=from_extra_vars" (niveau 22) :

"msg": "priority_test = from_extra_vars"

--extra-vars écrase tout.

Quand une variable a une valeur inattendue, deux outils :

Affiche les variables résolues pour un hôte donné, en montrant l'origine (group_vars, host_vars) :

Fenêtre de terminal
ansible-inventory --host db1.lab

Ne montre pas les vars: du play ni les set_fact: (qui sont dynamiques), mais c'est suffisant pour vérifier group_vars/ et host_vars/.

- name: Debug - voir toutes les sources de la variable
ansible.builtin.debug:
var: priority_test
- name: Debug - voir la valeur réellement utilisée
ansible.builtin.debug:
msg: "priority_test = {{ priority_test }}"

Ajoutez ce duo en haut de votre play quand vous chassez un bug de précédence. Vous voyez immédiatement la valeur active.

Pattern 1, defaults/main.yml pour permettre l'override

Section intitulée « Pattern 1, defaults/main.yml pour permettre l'override »

Dans un rôle, toujours mettre les valeurs paramétrables dans defaults/main.yml (niveau 2) :

roles/nginx/defaults/main.yml
nginx_port: 80
nginx_workers: 4
nginx_user: nginx

Le caller peut alors les écraser via vars:, --extra-vars, ou role params.

Pattern 2, vars/main.yml pour les constantes du rôle

Section intitulée « Pattern 2, vars/main.yml pour les constantes du rôle »

Réservez vars/main.yml (niveau 15) aux constantes immuables que le caller ne doit pas pouvoir changer :

roles/nginx/vars/main.yml
# Constantes : pas paramétrables par le caller
nginx_pid_file: /var/run/nginx.pid
nginx_log_dir: /var/log/nginx

Pattern 3, group_vars/<env>.yml pour les overrides d'environnement

Section intitulée « Pattern 3, group_vars/<env>.yml pour les overrides d'environnement »

Structure type d'un projet multi-environnement :

inventory/
├── prod.yml
├── staging.yml
└── group_vars/
├── all.yml # variables partagées (niveau 4)
├── webservers.yml # variables groupe (niveau 6)
├── prod.yml # variables environnement prod (niveau 6)
└── staging.yml # variables environnement staging (niveau 6)

Lancement :

Fenêtre de terminal
ansible-playbook site.yml -i inventory/prod.yml

group_vars/prod.yml charge automatiquement les variables prod, qui peuvent écraser all.yml.

Un job de CI qui déploie une version :

.gitlab-ci.yml
deploy:
script:
- ansible-playbook site.yml
-i inventory/prod.yml
--extra-vars "release_tag=$CI_COMMIT_TAG"

Aucune variable du repo ne peut écraser release_tag, c'est garanti par le niveau 22.

SymptômeCauseFix
--extra-vars ignoréMauvais format CLIFormat correct : --extra-vars "k=v k2=v2"
group_vars/ introuvableDoit être à côté de l'inventaire OU du playbookVérifier les deux emplacements
Variable d'un rôle non-overridableC'est dans vars/main.yml (niveau 15)Déplacer dans defaults/main.yml (niveau 2)
set_fact perdu entre runsSans cacheable: true, set_fact est éphémèreAjouter cacheable: true (mais attention : devient persistent !)
host_vars/ ne gagne pas sur group_vars/Mauvais nom de fichier (host_vars/web1 vs host_vars/web1.lab)Le nom doit matcher exactement inventory_hostname
  • 22 niveaux officiels Ansible, du plus faible (role defaults) au plus fort (--extra-vars).
  • 3 règles pratiques couvrent 95 % des cas : --extra-vars gagne sur tout ; plus c'est local, plus c'est prioritaire ; vars/main.yml d'un rôle écrase vars: du play.
  • defaults/main.yml d'un rôle = paramétrable ; vars/main.yml = constante.
  • --extra-vars est l'outil CI/CD par excellence (niveau 22 inattaquable).
  • En cas de surprise, ansible-inventory --host <h> + debug: var=.

Cette page a un lab d'accompagnement : labs/ecrire-code/precedence-variables/ dans stephrobert/ansible-training. Il contient un README.md guidé, un Makefile (make verify lance les tests), et un challenge final auto-évalué : valider que --extra-vars (niveau 22) écrase vars: du play et vars_files:.

Une fois le lab provisionné :

Fenêtre de terminal
cd ~/Projets/ansible-training/labs/ecrire-code/precedence-variables/
cat README.md # tuto pas à pas
cat challenge/README.md # consigne du challenge final
pytest -v challenge/tests/ # lancer les tests testinfra

Si les tests passent, vous maîtrisez les concepts couverts dans ce guide. En cas de blocage, docs/troubleshooting.md à la racine du repo couvre les pièges fréquents (rate-limit SSH, clé absente, collection manquante).

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn