Aller au contenu

Utilisation des variables avec Ansible

Mise à jour :

Les variables Ansible sont indispensables pour rendre vos playbooks réutilisables, dynamiques et faciles à maintenir. Elles permettent de personnaliser l’exécution des tâches selon les hôtes, les environnements ou les rôles. Que ce soit pour définir un chemin d’installation, une adresse IP ou un mot de passe, les variables évitent de dupliquer du code en dur. Elles sont définissables à plusieurs endroits — dans un playbook, un fichier d’inventaire, un rôle ou même en ligne de commande — et Ansible gère leur priorité grâce à un système de précédence bien établi.

Définir des variables

Ansible permet de définir des variables à différents endroits dans un projet. Chaque emplacement a ses usages privilégiés, selon que l’on souhaite définir des variables globales, par hôte, par groupe, ou spécifiques à un rôle. Bien organiser ces variables est essentiel pour garder des playbooks lisibles, maintenables et réutilisables.

Rappel : Dans le guide sur l’écriture de playbooks, nous avons vu comment construire l’arborescence d’un projet Ansible. Voici les emplacements principaux où vous pouvez définir des variables :

  • Répertoireprojet_ansible
    • Répertoireinventory
      • hosts
    • Répertoiregroup_vars
      • all.yml
      • webservers.yml
    • Répertoirehost_vars
      • server1.yml
      • server2.yml
    • Répertoirefiles
      • sample_file.txt
    • Répertoiretemplates
      • service.j2
    • ansible.cfg
    • install_apache.yml
    • configure_apache.yml

Déclaration de base

Les variables simples s’écrivent en YAML, sous forme de paires clé: valeur. On les définit généralement dans les blocs vars du playbook.

- name: Exemple de playbook avec des variables simples
hosts: all
vars:
http_port: 80
package_name: nginx
tasks:

Utilisation de fichiers de variables

On peut séparer les variables dans un fichier YAML et les inclure dans un playbook :

- hosts: all
vars_files:
- vars/config.yml

Fichier vars/config.yml :

timezone: Europe/Paris

Avec les --extra-vars

Les variables passées avec -e sont utiles pour les surcharges dynamiques ou dans les scripts d’automatisation :

Terminal window
ansible-playbook site.yml -e "app_env=production debug=false"

Dans l’inventaire (fichiers host_vars et group_vars)

group_vars/

Utile pour appliquer des variables à tous les hôtes d’un groupe.

Fichier group_vars/webservers.yml :

http_port: 80
nginx_enabled: true

host_vars/

Spécifique à un hôte individuel.

Fichier host_vars/web1.yml :

hostname: web1.example.com
datacenter: paris

Ces fichiers sont automatiquement lus par Ansible si leur nom correspond à celui de l’hôte ou du groupe dans l’inventaire.

Précédence des variables

Lorsque des variables sont définies à plusieurs endroits, Ansible applique un ordre de priorité strict pour décider quelle valeur utiliser. C’est ce qu’on appelle la précédence des variables. Comprendre cette hiérarchie est essentiel pour éviter des comportements inattendus dans vos playbooks.

Quand une variable est définie plusieurs fois sous le même nom, Ansible garde la valeur avec la priorité la plus haute. Par exemple, une variable passée en ligne de commande via -e l’emportera sur celle définie dans un fichier defaults/main.yml d’un rôle.

Voici les principales sources de variables, classées de la plus haute à la plus basse priorité :

  1. Variables extra (--extra-vars ou -e)
  2. Variables définies dans un playbook
  3. Variables dans host_vars/ et group_vars/
  4. Facts collectés automatiquement

La précédence des variables permet à Ansible de rester flexible, mais elle nécessite une bonne organisation pour éviter les conflits et garder le contrôle sur les valeurs réellement utilisées pendant l’exécution.

Plus d’informations sur la précédence des variables

Les différents types de variables

Les variables simples

Les variables sont la base de la personnalisation dans Ansible. Elles stockent une seule valeur : une chaîne de caractères, un nombre, un booléen ou une valeur nulle. Ces variables facilitent la maintenance et évitent la duplication d’informations dans les playbooks.

Les variables simples peuvent être de différents types :

  1. Chaînes de caractères : Utilisées pour représenter du texte, elles peuvent être entourées de guillemets ou d’apostrophes.

    server_name: "example.com"
  2. Nombres : Représentent des valeurs numériques, sans guillemets.

    max_connections: 100
  3. Booléens : Représentent des valeurs vraies (true) ou fausses (false), sans guillemets.

    enable_ssl: true

Variables complexes

En plus des variables simples, Ansible permet d’utiliser des listes (arrays) et des dictionnaires (objets). Ces structures de données sont particulièrement utiles pour organiser des informations complexes, comme une liste de paquets à installer ou une configuration de service complète.

Les listes

Une liste est un ensemble de valeurs ordonnées. Elle se déclare avec un tiret (-) devant chaque élément :

packages:
- nginx
- php
- mysql-server

On peut aussi écrire la liste sur une seule ligne :

packages: ["nginx", "php", "mysql-server"]

Les dictionnaires

Un dictionnaire (ou objet YAML) regroupe des paires clé/valeur. Il permet de structurer des données hiérarchiques :

mysql_config:
user: root
password: secret
host: localhost
port: 3306

Pour accéder à une valeur :

- name: Afficher le nom d’utilisateur
ansible.builtin.debug:
msg: "Utilisateur MySQL : {{ mysql_config.user }}"

Dictionnaires imbriqués

On peut combiner plusieurs niveaux pour décrire des services, des utilisateurs, ou des configurations complètes :

services:
nginx:
enabled: true
port: 80
php:
enabled: true
version: "8.1"
mysql:
enabled: false
databases:
- nom: app_db
user: app_user

Accès à un élément de dictionnaire imbriqué :

{{ services.nginx.port }}

Quand utiliser listes et dictionnaires ?

  • Listes : plusieurs éléments similaires à traiter en boucle (paquets, services, chemins).
  • Dictionnaires : structurer des configurations liées à une entité (base de données, utilisateur, application).
- hosts: all
vars:
users:
- name: alice
uid: 1001
- name: bob
uid: 1002
tasks:
- name: Créer les utilisateurs
ansible.builtin.user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
state: present
loop: "{{ users }}"

Grâce aux listes et dictionnaires, vous pouvez décrire des systèmes complexes de manière lisible, modulaire et réutilisable. Ces structures sont fondamentales pour tirer pleinement parti d’Ansible dans vos playbooks.

Utilisation des variables

Une fois déclarées, les variables Ansible s’utilisent à travers la syntaxe Jinja2, avec des doubles accolades : {{ variable }}. Cette syntaxe permet de référencer dynamiquement n’importe quelle variable dans un module, une condition, un chemin de fichier ou même un nom de tâche. Leur usage dans les tâches Ansible est central pour rendre les playbooks génériques, dynamiques et réutilisables.

Utilisation dans les modules

C’est l’usage le plus courant : insérer une variable comme argument d’un module Ansible. Voici un exemple avec ansible.builtin.apt :

- name: Installer un paquet
ansible.builtin.apt:
name: "{{ package_name }}"
state: present

Le nom du paquet sera injecté dynamiquement selon la valeur de package_name.

Utilisation dans les noms de tâches

On peut rendre les noms de tâches plus lisibles en utilisant des variables :

- name: Redémarrer le service {{ service_name }}
ansible.builtin.service:
name: "{{ service_name }}"
state: restarted

Cela permet de mieux suivre l’exécution du playbook selon les contextes. Attention les variables ne sont autorisées qu’à la fin du nom de la tâche.

Utilisation dans les chemins de fichiers

Ansible utilise des chemins souvent variables selon l’environnement. Vous pouvez injecter une variable dans un chemin :

- name: Créer un répertoire spécifique
ansible.builtin.file:
path: "/opt/{{ app_name }}/logs"
state: directory

Variables spéciales : Les facts et variables magiques

Ansible propose des variables spéciales appelées facts et variables magiques. Ces informations sont automatiquement disponibles durant l’exécution d’un playbook. Elles permettent d’adapter les tâches à l’environnement cible sans avoir à tout définir manuellement.

Les facts Ansible : ansible_facts

Les facts sont des données collectées automatiquement sur un hôte distant : version du système, interfaces réseau, mémoire, architecture, etc. Ansible les collecte en début de playbook via le module setup.

Terminal window
ansible all -m setup
...
"ansible_virtualization_tech_host": [],
"ansible_virtualization_type": "lxc",
"discovered_interpreter_python": "/usr/bin/python3.11",
"gather_subset": [
"all"
],
"module_setup": true
},
"changed": false
}

Vous pouvez aussi utiliser la syntaxe courte :

{{ ansible_distribution }}

Exemples courants de facts disponibles

  • ansible_hostname : nom d’hôte
  • ansible_distribution : type de distribution Linux
  • ansible_memory_mb : mémoire RAM en Mo
  • ansible_processor : architecture processeur
  • ansible_interfaces : interfaces réseau
  • ansible_default_ipv4.address : adresse IP principale

Contrôle de la collecte des facts

La collecte des facts se fait automatiquement, sauf si on la désactive :

- hosts: all
gather_facts: false

Pour la récupérer manuellement, on peut appeler le module setup :

- name: Récupérer les facts
ansible.builtin.setup:

Par défaut, Ansible collecte tous les facts, mais vous pouvez restreindre cette collecte pour améliorer les performances, surtout sur de nombreux hôtes.

- name: Collecter uniquement les facts de base
ansible.builtin.setup:
gather_subset:
- network

Enregistrer la sortie de tâches (register)

Ansible permet de capturer le résultat d’une tâche dans une variable à l’aide de l’instruction register. Cela permet de réutiliser la sortie dans une autre tâche, de faire des vérifications, ou de prendre des décisions conditionnelles.

- name: Lister les fichiers
ansible.builtin.command: ls /etc
register: liste_etc

Structure de la variable enregistrée

La variable enregistrée contient plusieurs champs : stdout, stderr, rc, changed, failed, etc.

Voici les principales clés accessibles :

  • stdout : sortie standard
  • stderr : sortie d’erreur
  • rc : code retour (0 = succès)
  • changed : booléen indiquant si une modification a eu lieu
  • failed : booléen indiquant l’échec

On peut ensuite afficher ou utiliser le contenu :

- name: Afficher le résultat
ansible.builtin.debug:
msg: "Contenu : {{ liste_etc.stdout }}"

Bonnes pratiques d’utilisation des variables

L’usage des variables dans Ansible est puissant, mais sans discipline, il peut rapidement rendre un projet difficile à maintenir, voire exposer des données sensibles. Voici une série de bonnes pratiques pour organiser, sécuriser et utiliser efficacement vos variables dans vos playbooks.

Séparer les variables sensibles avec Ansible Vault

Les mots de passe, tokens API ou clés SSH ne doivent jamais être stockés en clair dans vos fichiers YAML. Utilisez Ansible Vault pour chiffrer les fichiers contenant des informations confidentielles.

Masquer les sorties sensibles avec no_log

Quand vous utilisez une variable contenant une donnée confidentielle dans une tâche, masquez sa sortie dans les logs grâce à l’option no_log :

- name: Envoyer un mot de passe
ansible.builtin.debug:
msg: "Mot de passe : {{ password }}"
no_log: true

Cela empêche Ansible d’écrire cette information dans la sortie standard et dans les fichiers de log.

Nommer les variables de façon explicite

Un bon nom de variable doit être compréhensible et explicite. Utilisez le format snake_case, et évitez les abréviations ambiguës :

  • Préférer : db_root_password, webserver_port, enable_tls
  • Éviter : pw, x, var1, port1

Utiliser des fichiers séparés pour les environnements

Organisez vos variables par environnement : dev, staging, prod, en créant des fichiers distincts :

group_vars/
all.yml
dev.yml
prod.yml

Puis sélectionnez le bon fichier depuis la ligne de commande.

Limiter l’usage de set_fact

set_fact est utile pour définir dynamiquement une variable pendant l’exécution, mais son usage excessif peut brouiller la lisibilité du playbook. Préférez l’usage des vars et des conditions déclaratives.

Documenter les variables importantes

Ajoutez des commentaires dans vos fichiers de variables pour expliquer leur rôle :

db_port: 5432 # Port de la base PostgreSQL
api_timeout: 30 # Timeout en secondes pour les appels API

Vérifier les variables manquantes

Pour éviter les erreurs silencieuses, vous pouvez forcer l’échec si une variable est absente :

- name: Échouer si une variable n’est pas définie
ansible.builtin.assert:
that:
- db_user is defined
- db_password is defined

Conclusion

L’application rigoureuse de ces bonnes pratiques garantit la clarté, la sécurité et la robustesse de vos automatisations Ansible. En particulier dans les environnements professionnels, elles sont indispensables pour travailler en équipe et déployer en toute confiance.

Conclusion

Les variables Ansible sont un outil puissant pour rendre vos playbooks dynamiques, réutilisables et faciles à maintenir. En comprenant comment les définir, les organiser et les utiliser efficacement, vous pouvez automatiser des tâches complexes tout en gardant une structure claire et lisible.