
Au début de chaque play, Ansible peut collecter automatiquement des centaines de variables sur chaque managed node : distribution, version, IP, mémoire, CPU, montages, packages, services, utilisateurs. Ce sont les facts — exposés sous la racine ansible_facts.* (et historiquement aussi en ansible_* directement). Cette page explique comment les utiliser, comment limiter leur collecte pour gagner en performance (gather_subset:), et comment lire les magic vars d’Ansible : inventory_hostname, groups, hostvars, play_hosts.
Maîtriser cette couche, c’est passer du playbook qui cible 1 hôte au playbook qui s’adapte automatiquement à la distribution, à la mémoire disponible, à la composition du groupe — sans aucune config manuelle.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Activer / désactiver
gather_facts:au niveau du play - Limiter la collecte avec
gather_subset:pour gagner du temps sur grandes fleets - Lire les facts les plus utiles :
ansible_distribution,ansible_default_ipv4,ansible_memtotal_mb,ansible_memory_mb - Utiliser les magic vars :
inventory_hostname,groups,hostvars,play_hosts,ansible_play_batch - Accéder aux facts d’un autre hôte via
hostvars['<host>'].ansible_*
Prérequis
Section intitulée « Prérequis »- Avoir lu Variables — déclaration et Types collections ;
- Avoir un lab opérationnel (
ansible all -m pingrépondpong).
La phase gather_facts
Section intitulée « La phase gather_facts »Au démarrage de chaque play (par défaut), Ansible exécute le module setup sur chaque hôte cible. Ce module remonte des centaines de variables :
ansible web1.lab -m setup | head -40Sortie (extrait) :
web1.lab | SUCCESS => { "ansible_facts": { "ansible_distribution": "AlmaLinux", "ansible_distribution_version": "10.1", "ansible_distribution_major_version": "10", "ansible_default_ipv4": { "address": "10.10.20.21", "interface": "eth0", "netmask": "255.255.255.0" }, "ansible_memtotal_mb": 1740, "ansible_processor_cores": 1, ... }}Ces facts sont disponibles dans toutes les tâches qui suivent — directement par leur nom ({{ ansible_distribution }}) ou via ansible_facts.*.
Les facts les plus utiles
Section intitulée « Les facts les plus utiles »| Fact | Type | Exemple |
|---|---|---|
ansible_distribution | string | AlmaLinux, Ubuntu, Debian |
ansible_distribution_version | string | 10.1 |
ansible_distribution_major_version | string | 10 |
ansible_os_family | string | RedHat, Debian |
ansible_default_ipv4.address | string | 10.10.20.21 |
ansible_all_ipv4_addresses | list | ["10.10.20.21"] |
ansible_memtotal_mb | int | 1740 |
ansible_processor_cores | int | 1 |
ansible_processor_count | int | 1 |
ansible_kernel | string | 5.14.0-...el10.x86_64 |
ansible_hostname | string | web1 (court) |
ansible_fqdn | string | web1.lab (FQDN) |
ansible_python_version | string | 3.12.x |
ansible_pkg_mgr | string | dnf, apt |
Désactiver les facts pour la performance
Section intitulée « Désactiver les facts pour la performance »La phase gather_facts: true prend 2-5 secondes par hôte. Sur 100 hôtes, c’est 5 minutes perdues si vous n’utilisez aucun fact :
- name: Tâche simple sans facts hosts: webservers gather_facts: false # désactive la collecte tasks: - name: Install nginx ansible.builtin.dnf: name: nginx state: presentbecome_method: sudo et les modules courants (dnf, systemd) n’ont pas besoin des facts. Les variables comme ansible_distribution ne sont en revanche plus disponibles.
Limiter la collecte avec gather_subset:
Section intitulée « Limiter la collecte avec gather_subset: »Plutôt que tout collecter ou rien, filtrez :
- name: Collecter uniquement les facts réseau hosts: webservers gather_facts: true gather_subset: - "!all" # ne pas tout collecter - "!min" # même pas le minimum - network # mais inclure le réseauSubsets disponibles :
| Subset | Contient |
|---|---|
all | Tout (par défaut) |
min | Sous-ensemble minimal (distribution, kernel, hostname) |
network | Interfaces, IPs, MAC |
hardware | CPU, mémoire, disques |
virtual | Virtualisation détectée |
facter, ohai | External fact gatherers |
Préfixer avec ! = exclure. Combinaisons typiques :
['!all', '!min', 'network']: seulement le réseau (le plus rapide)['!all', 'min']: juste le minimum vital
Sur 100 hôtes, passer de all à min peut réduire le temps de gather de 50 %.
Les magic vars
Section intitulée « Les magic vars »Variables automatiquement injectées par Ansible, pas issues du gather :
inventory_hostname
Section intitulée « inventory_hostname »Le nom de l’hôte courant tel que défini dans l’inventaire (web1.lab, pas web1).
- name: Saluer ansible.builtin.debug: msg: "Bonjour depuis {{ inventory_hostname }}"Dict des groupes de l’inventaire. groups['webservers'] retourne la liste des hôtes du groupe :
- name: Lister les webservers ansible.builtin.debug: msg: "{{ groups['webservers'] }}"# → ['web1.lab', 'web2.lab']
- name: Compter les webservers ansible.builtin.debug: msg: "{{ groups['webservers'] | length }} webservers"# → "2 webservers"hostvars
Section intitulée « hostvars »Dict indexé par hostname qui contient toutes les variables et facts de chaque hôte. Pour lire un fact d’un autre hôte :
- name: Afficher l'IP de web2 depuis web1 ansible.builtin.debug: msg: "{{ hostvars['web2.lab'].ansible_default_ipv4.address }}"play_hosts et ansible_play_batch
Section intitulée « play_hosts et ansible_play_batch »play_hosts: liste des hôtes ciblés par le play avant filtrage parserial:.ansible_play_batch: liste des hôtes du batch courant (pertinent quandserial: N).
- name: Liste du batch courant ansible.builtin.debug: msg: "Batch : {{ ansible_play_batch }}"Cas pratique — synthèse cross-host (lab ecrire-code/facts-magic-vars)
Section intitulée « Cas pratique — synthèse cross-host (lab ecrire-code/facts-magic-vars) »Voici l’exemple validé sur le lab 14-ecrire-code-facts-magic-vars :
---- name: Pre-gather facts sur web1 (rend hostvars web1 disponibles) hosts: web1.lab gather_facts: true tasks: []
- name: Synthese facts sur db1 hosts: db1.lab become: true gather_facts: true tasks: - name: Poser le fichier de synthese ansible.builtin.copy: dest: /tmp/facts-summary.txt content: | db1_hostname={{ inventory_hostname }} db1_os={{ ansible_distribution }} db1_memory={{ ansible_memtotal_mb }} webservers_count={{ groups['webservers'] | length }} web1_ip={{ hostvars['web1.lab'].ansible_default_ipv4.address }} mode: "0644"Contenu du fichier sur db1.lab :
db1_hostname=db1.labdb1_os=AlmaLinuxdb1_memory=1740webservers_count=2web1_ip=10.10.20.21Le pre-gather sur web1.lab est nécessaire pour que hostvars['web1.lab'] soit peuplé au moment du second play.
Quand utiliser quoi
Section intitulée « Quand utiliser quoi »| Situation | Mécanisme |
|---|---|
| Adapter une commande à la distribution | when: ansible_distribution == 'AlmaLinux' |
| Calculer une mémoire dépendante de la machine | nginx_workers: "{{ ansible_processor_cores * 2 }}" |
| Connaître l’IP d’un hôte voisin | hostvars['<host>'].ansible_default_ipv4.address |
| Itérer sur tous les membres d’un groupe | loop: "{{ groups['webservers'] }}" |
| Identifier l’hôte courant dans un template | {{ inventory_hostname }} |
| Connaître quels hôtes sont dans le batch courant | {{ ansible_play_batch }} |
Pièges fréquents
Section intitulée « Pièges fréquents »| Symptôme | Cause | Fix |
|---|---|---|
'NoneType' object has no attribute 'ansible_default_ipv4' | hostvars de l’hôte n’a pas été gather | Ajouter un pre-gather play sur le groupe |
gather_facts: false mais le playbook utilise ansible_distribution | Désactivation accidentelle | Réactiver gather_facts: true ou utiliser le module setup ad-hoc |
groups vide ou incorrect | Mauvais nom de groupe ou inventaire pas chargé | Vérifier avec ansible-inventory --graph |
gather_subset ignore mes choix | Mauvaise syntaxe de l’expression | Vérifier l’ordre ['!all', 'network'] (l’ordre compte) |
ansible_* direct (sans ansible_facts.) | INJECT_FACTS_AS_VARS désactivé (futur Ansible) | Toujours préférer ansible_facts.distribution à ansible_distribution |
À retenir
Section intitulée « À retenir »gather_facts: true(défaut) collecte les facts via le modulesetupau début de chaque play.gather_subset:filtre la collecte — passer deallàminpeut diviser par 2 le temps de gather.- Les magic vars essentielles :
inventory_hostname,groups,hostvars,play_hosts,ansible_play_batch. hostvars['<host>'].ansible_*lit les facts d’un autre hôte — nécessite que cet hôte ait été gather au préalable.- À l’avenir,
ansible_facts.distributionsera la forme canonique —ansible_distributiondeprecated.
Pratiquer dans le lab
Section intitulée « Pratiquer dans le lab »Cette page a un lab d’accompagnement : labs/ecrire-code/facts-magic-vars/ dans
stephrobert/ansible-training. Il contient
un README.md guidé, un Makefile (make verify lance les tests), et un
challenge final auto-évalué : synthèse cross-host : facts db1 + IP web1 via hostvars (pre-gather sur web1).
Une fois le lab provisionné :
cd ~/Projets/ansible-training/labs/ecrire-code/facts-magic-vars/
cat README.md # tuto pas à pascat challenge/README.md # consigne du challenge finalpytest -v challenge/tests/ # lancer les tests testinfraSi 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).