Aller au contenu
Infrastructure as Code medium

Variables d'un rôle Ansible : defaults/ vs vars/ et précédence

10 min de lecture

Logo Ansible

defaults/main.yml et vars/main.yml sont les deux sources de variables d’un rôle, mais avec une différence fondamentale : defaults/ est override-able par l’utilisateur, vars/ ne l’est pas. Cette distinction est objectif RHCE explicite et conditionne la qualité de votre rôle — un mauvais choix entre les deux casse la réutilisabilité ou expose des chemins critiques.

Cette page vous fait brancher les variables aux tâches et au template Jinja du rôle webserver, démontre la précédence à 5 niveaux (defaults, vars du play, vars/, —extra-vars), et explique quel critère choisir entre les deux dossiers.

  • Brancher des variables aux tâches ({{ webserver_listen_port }}).
  • Utiliser des variables dans un template Jinja2 (nginx.conf.j2).
  • Override une variable depuis un playbook avec vars:.
  • Comprendre la précédence : defaults/ < vars: du play < vars/ du rôle.
  • Choisir entre defaults/ et vars/ selon le rôle de la variable.
  • Utiliser --extra-vars pour override tout.
DossierPriorité Ansible (sur 22)Quand l’utiliser
defaults/main.yml2 (basse)L’utilisateur doit pouvoir override la valeur (config publique du rôle)
vars/main.yml18 (haute)Constantes internes au rôle (chemins système, mappings OS)

Règle pratique : si vous hésitez, mettez en defaults/. Le RHCE EX294 teste explicitement cette distinction.

# defaults/main.yml — variables OVERRIDE-ABLES (priorité faible)
---
webserver_package: nginx
webserver_state: present
webserver_service_state: started
webserver_service_enabled: true
# Configuration nginx
webserver_listen_port: 80
webserver_worker_processes: auto
webserver_worker_connections: 1024
# Page d'accueil personnalisée
webserver_index_content: "<h1>Hello from {{ inventory_hostname }}</h1>"

8 variables, toutes préfixées par webserver_ (convention nom du rôle pour éviter les collisions). L’utilisateur peut redéfinir n’importe laquelle dans son playbook ou ses group_vars/.

# vars/main.yml — variables INTERNES (priorité haute, NE PAS modifier)
---
__webserver_config_dir: /etc/nginx
__webserver_log_dir: /var/log/nginx
__webserver_html_dir: /usr/share/nginx/html
__webserver_pid_file: /run/nginx.pid

Convention double underscore (__) pour signaler « usage interne, ne pas modifier ». Ces 4 chemins sont des détails d’implémentation : les changer casse le rôle. Les protéger dans vars/ (priorité 18) empêche un utilisateur de les redéfinir accidentellement.

# tasks/main.yml — utilise les variables defaults/ et vars/
---
- name: Installer le paquet nginx
ansible.builtin.dnf:
name: "{{ webserver_package }}"
state: "{{ webserver_state }}"
- name: Déployer nginx.conf depuis le template
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: "0644"
backup: true
validate: nginx -t -c %s
notify: Restart nginx
- name: Déployer la page d'accueil personnalisée
ansible.builtin.copy:
dest: "{{ __webserver_html_dir }}/index.html" # ← variable de vars/
content: "{{ webserver_index_content }}\n" # ← variable de defaults/
mode: "0644"
- name: Ouvrir le port HTTP custom dans firewalld
ansible.posix.firewalld:
port: "{{ webserver_listen_port }}/tcp"
permanent: true
immediate: true
state: enabled
- name: Démarrer et activer nginx
ansible.builtin.systemd_service:
name: "{{ webserver_package }}"
state: "{{ webserver_service_state }}"
enabled: "{{ webserver_service_enabled }}"

Chaque variable est référencée avec {{ var_name }}. Pour Jinja, defaults/ et vars/ sont indistinguables — la précédence est résolue en amont par Ansible.

{# templates/nginx.conf.j2 — utilise les variables du rôle #}
user nginx;
worker_processes {{ webserver_worker_processes }};
pid {{ __webserver_pid_file }};
events {
worker_connections {{ webserver_worker_connections }};
}
http {
include /etc/nginx/mime.types;
sendfile on;
server {
listen {{ webserver_listen_port }};
server_name _;
location / {
root {{ __webserver_html_dir }};
index index.html;
}
}
}

5 variables consommées dans un seul template — les 3 publiques (worker_processes, worker_connections, listen_port) et 2 internes (pid_file, html_dir).

- name: Webserver avec port custom
hosts: web1.lab
become: true
roles:
- role: webserver
vars:
webserver_listen_port: 9090
webserver_index_content: "Custom message override"

Le vars: du play gagne sur defaults/main.yml du rôle. nginx écoute maintenant sur 9090 au lieu de 80.

Étape 6 — Tester d’override vars/ (et observer l’échec)

Section intitulée « Étape 6 — Tester d’override vars/ (et observer l’échec) »
- name: Tenter override d'une vars/ interne
hosts: web1.lab
become: true
roles:
- role: webserver
vars:
__webserver_html_dir: /tmp/test # ← variable interne de vars/

Lancement → la valeur d’override n’est PAS appliquée. Pourquoi ? vars/main.yml du rôle a priorité 18, le vars: du play a priorité 13. Donc vars/ du rôle gagne.

C’est exactement pourquoi on protège les constantes internes dans vars/ — pour éviter qu’un utilisateur casse le rôle accidentellement.

Pour ce rôle :

NiveauSourcePriorité (sur 22)
1 (faible)defaults/main.yml du rôle2
2group_vars/all.yml, host_vars/<host>.yml4-7
3vars: dans le play / role include13
4vars/main.yml du rôle18
5 (forte)--extra-vars en CLI22

Conséquences pratiques :

  • defaults/ peut être override partout — c’est le but.
  • vars/ ne peut être override que par --extra-vars ou set_fact.
  • host_vars/web1.lab.yml ne peut pas override les vars/ d’un rôle.
Fenêtre de terminal
ansible-playbook playbook.yml \
--extra-vars "webserver_listen_port=12345"

Priorité 22 : écrase TOUT, y compris vars/main.yml du rôle. À utiliser pour des overrides ponctuels (debug, test rapide, parameter d’un job CI).

Fenêtre de terminal
# Même les variables internes de vars/ sont override-ables via --extra-vars
ansible-playbook playbook.yml \
--extra-vars "__webserver_html_dir=/tmp/extra"

À utiliser avec précaution — vous bypassez les protections du rôle.

Cette page a un lab d’accompagnement : labs/roles/variables-defaults-vars/ dans stephrobert/ansible-training.

Le lab étend le rôle webserver du lab roles/creer-premier-role avec 8 variables defaults/ + 4 variables vars/ + un template nginx.conf.j2 qui les consomme. Le challenge override 3 variables et prouve l’effet par testinfra (5 tests).

Fenêtre de terminal
cd ~/Projets/ansible-training/labs/roles/variables-defaults-vars/
ansible-playbook playbook.yml # config par défaut
cat challenge/README.md # consigne challenge
pytest -v challenge/tests/ # valider override
SymptômeCauseFix
Variable d’override ignoréeDéfinie dans vars/ (priorité 18)Bouger vers defaults/ (priorité 2)
Collision de noms entre rôlesVariables non préfixéesToujours préfixer par le nom du rôle (webserver_*)
Template plante avec undefinedVariable absente des defaults/Mettre une valeur par défaut, ou utiliser &#123;&#123; var | default('valeur') &#125;&#125;
Override --extra-vars ne marche pasFaute de frappe sur le nom de variableansible-inventory --host <host> pour voir les variables résolues
validate: nginx -t -c %s échoueConf invalide générée par le templateVérifier les valeurs des variables, ajouter default() Jinja
  • defaults/main.yml = override-able (priorité 2). Variables publiques du rôle.
  • vars/main.yml = interne (priorité 18). Chemins système, constantes.
  • Convention : préfixer par nom_du_role_ les variables publiques, par __nom_du_role_ les internes.
  • Précédence simplifiée : defaults/ < vars: du play < vars/ du rôle < --extra-vars.
  • --extra-vars = priorité 22, override tout.
  • validate: sur les templates de services critiques (nginx -t -c %s).

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn