
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.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- 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/etvars/selon le rôle de la variable. - Utiliser
--extra-varspour override tout.
Prérequis
Section intitulée « Prérequis »- Avoir suivi Créer son premier rôle.
- Comprendre group_vars / host_vars.
Le rôle de chaque dossier — règle simple
Section intitulée « Le rôle de chaque dossier — règle simple »| Dossier | Priorité Ansible (sur 22) | Quand l’utiliser |
|---|---|---|
defaults/main.yml | 2 (basse) | L’utilisateur doit pouvoir override la valeur (config publique du rôle) |
vars/main.yml | 18 (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.
Étape 1 — defaults/main.yml étendu
Section intitulée « Étape 1 — defaults/main.yml étendu »# defaults/main.yml — variables OVERRIDE-ABLES (priorité faible)---webserver_package: nginxwebserver_state: presentwebserver_service_state: startedwebserver_service_enabled: true
# Configuration nginxwebserver_listen_port: 80webserver_worker_processes: autowebserver_worker_connections: 1024
# Page d'accueil personnaliséewebserver_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/.
Étape 2 — vars/main.yml pour les internes
Section intitulée « Étape 2 — vars/main.yml pour les internes »# 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.pidConvention 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.
Étape 3 — Brancher les variables aux tâches
Section intitulée « Étape 3 — Brancher les variables aux tâches »# 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.
Étape 4 — Template Jinja2 paramétré
Section intitulée « Étape 4 — Template Jinja2 paramétré »{# 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).
Étape 5 — Override depuis le playbook
Section intitulée « Étape 5 — Override depuis le playbook »- 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.
La précédence en 5 niveaux (extrait des 22)
Section intitulée « La précédence en 5 niveaux (extrait des 22) »Pour ce rôle :
| Niveau | Source | Priorité (sur 22) |
|---|---|---|
| 1 (faible) | defaults/main.yml du rôle | 2 |
| 2 | group_vars/all.yml, host_vars/<host>.yml | 4-7 |
| 3 | vars: dans le play / role include | 13 |
| 4 | vars/main.yml du rôle | 18 |
| 5 (forte) | --extra-vars en CLI | 22 |
Conséquences pratiques :
defaults/peut être override partout — c’est le but.vars/ne peut être override que par--extra-varsouset_fact.host_vars/web1.lab.ymlne peut pas override lesvars/d’un rôle.
--extra-vars — le top de la précédence
Section intitulée « --extra-vars — le top de la précédence »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).
# Même les variables internes de vars/ sont override-ables via --extra-varsansible-playbook playbook.yml \ --extra-vars "__webserver_html_dir=/tmp/extra"À utiliser avec précaution — vous bypassez les protections du rôle.
Pratiquer dans le lab
Section intitulée « Pratiquer dans le lab »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).
cd ~/Projets/ansible-training/labs/roles/variables-defaults-vars/
ansible-playbook playbook.yml # config par défautcat challenge/README.md # consigne challengepytest -v challenge/tests/ # valider overridePièges courants
Section intitulée « Pièges courants »| Symptôme | Cause | Fix |
|---|---|---|
| Variable d’override ignorée | Définie dans vars/ (priorité 18) | Bouger vers defaults/ (priorité 2) |
| Collision de noms entre rôles | Variables non préfixées | Toujours préfixer par le nom du rôle (webserver_*) |
Template plante avec undefined | Variable absente des defaults/ | Mettre une valeur par défaut, ou utiliser {{ var | default('valeur') }} |
Override --extra-vars ne marche pas | Faute de frappe sur le nom de variable | ansible-inventory --host <host> pour voir les variables résolues |
validate: nginx -t -c %s échoue | Conf invalide générée par le template | Vérifier les valeurs des variables, ajouter default() Jinja |
À retenir
Section intitulée « À retenir »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).