Aller au contenu
Infrastructure as Code medium

Modules add_host, group_by, meta refresh_inventory : inventaire dynamique au runtime

11 min de lecture

Logo Ansible

Les plugins d’inventaire sont géniaux pour gérer un parc évolutif, mais ils s’exécutent avant le playbook. Que faire quand un play provisionne une VM dont on ne connaît pas encore le nom ou l’IP, et que le play suivant doit l’utiliser ? add_host ajoute un hôte au runtime, group_by crée des groupes basés sur les facts, et meta: refresh_inventory recharge les plugins en cours de play.

Ces trois mécanismes complètent les plugins d’inventaire — ils sont indispensables pour orchestrer du provisioning + configuration en un seul playbook.

  • Ajouter un hôte à l’inventaire au runtime avec add_host.
  • Créer des groupes dynamiques basés sur les facts avec group_by.
  • Forcer le rechargement d’un plugin d’inventaire avec meta: refresh_inventory.
  • Combiner ces 3 mécanismes pour un workflow provision + configure en un seul playbook.
  • Persister un inventaire dynamique entre plays (limites et workarounds).

add_host ajoute un hôte à l’inventaire en mémoire pendant l’exécution. L’hôte devient utilisable par les plays suivants du même playbook.

---
- name: Provisionner une VM AWS
hosts: localhost
gather_facts: false
tasks:
- name: Lancer une instance EC2
amazon.aws.ec2_instance:
name: web-new-2026
instance_type: t3.micro
image_id: ami-0abcdef1234567890
wait: true
register: ec2_result
- name: Ajouter la nouvelle instance à l'inventaire
ansible.builtin.add_host:
name: "{{ ec2_result.instances[0].public_ip_address }}"
groups: webservers,new_instances
ansible_user: ec2-user
ansible_ssh_private_key_file: ~/.ssh/aws-key
- name: Configurer la nouvelle VM
hosts: new_instances
tasks:
- name: Installer nginx
ansible.builtin.dnf:
name: nginx
state: present

Le pattern : le premier play tourne sur localhost, provisionne la VM, récupère son IP, l’ajoute via add_host. Le second play cible le groupe new_instances qui vient d’être créé. Sans add_host, il faudrait deux playbooks séparés + un mécanisme de transmission de l’IP.

ParamètreEffet
name:Hostname ou IP de l’hôte à ajouter
groups:Groupes auxquels l’ajouter (séparés par virgule)
ansible_host:IP de connexion si différente du name:
ansible_user:User SSH pour cette VM
<var>: <valeur>Toute autre variable est attachée au host
  • Volatil : l’hôte n’existe que pour ce run. Le run suivant ne le voit pas.
  • Pas de host_vars/ : les variables sont définies inline dans le add_host:.
  • Pas dans --graph entre deux runs : même ansible-inventory --graph ne le voit pas (il n’a pas exécuté le play).

Pour persister, il faut écrire l’hôte dans un fichier d’inventaire via template: ou lineinfile:.

group_by crée un groupe à la volée basé sur les facts ou variables des hôtes. Idéal pour cibler par caractéristique runtime plutôt que par config statique.

---
- name: Grouper par famille d'OS
hosts: all
tasks:
- name: Créer un groupe par OS family
ansible.builtin.group_by:
key: "os_{{ ansible_facts.os_family | lower }}"
- name: Tâches spécifiques RHEL
hosts: os_redhat
tasks:
- name: Installer firewalld
ansible.builtin.dnf:
name: firewalld
state: present
- name: Tâches spécifiques Debian
hosts: os_debian
tasks:
- name: Installer ufw
ansible.builtin.apt:
name: ufw
state: present

Le pattern : le premier play gather_facts sur tous les hôtes et crée des groupes os_redhat, os_debian, os_archlinux selon ansible_os_family. Les plays suivants ciblent ces groupes générés au runtime.

Avantage sur when: ansible_os_family == 'RedHat' : code plus propre quand vous avez beaucoup de tâches par OS.

# Grouper par nombre de CPU
- ansible.builtin.group_by:
key: "cpu_{{ ansible_facts.processor_cores }}"
# Grouper par version de distribution
- ansible.builtin.group_by:
key: "rhel_{{ ansible_facts.distribution_major_version }}"
# Grouper par disponibilité d'un service (custom fact)
- ansible.builtin.group_by:
key: "has_docker"
when: ansible_facts.services['docker.service'] is defined
  • Comme add_host, volatil — n’existe que pour le run.
  • Les groupes créés par group_by ne sont vus que par les plays suivants, pas par le play courant.

Quand un plugin d’inventaire dynamique a un cache, meta: refresh_inventory force le rafraîchissement entre deux plays.

---
- name: Provisionner avec Terraform
hosts: localhost
tasks:
- name: Lancer terraform apply
ansible.builtin.command: terraform apply -auto-approve
args:
chdir: ./terraform/
- name: Rafraîchir l'inventaire pour voir les nouvelles VMs
ansible.builtin.meta: refresh_inventory
- name: Configurer les nouvelles VMs
hosts: webservers # ce groupe contient maintenant les VMs Terraform
tasks:
- name: Installer nginx
ansible.builtin.dnf:
name: nginx
state: present

Sans refresh_inventory, le second play utilise le cache de l’inventaire dynamique — qui ne contient pas encore les nouvelles VMs Terraform.

  • Après une commande qui modifie l’infrastructure (Terraform, virt-install, AWS CLI).
  • Avant un play qui doit voir les nouvelles ressources.
  • Sur un plugin avec cache: true configuré (sinon pas nécessaire).

Provisioning AWS + bootstrap Linux + déploiement application en un seul playbook :

---
- name: 1. Provisionner l'infra
hosts: localhost
gather_facts: false
tasks:
- name: Lancer Terraform
ansible.builtin.command: terraform apply -auto-approve
args:
chdir: ./terraform/
- name: Récupérer les IPs
ansible.builtin.command: terraform output -json instance_ips
register: ips_output
changed_when: false
- name: Ajouter les nouvelles VMs à l'inventaire
ansible.builtin.add_host:
name: "{{ item }}"
groups: new_vms
ansible_user: ec2-user
loop: "{{ ips_output.stdout | from_json }}"
- name: 2. Bootstrap Linux (gather_facts pour obtenir l'OS)
hosts: new_vms
tasks:
- name: Mettre à jour les paquets
ansible.builtin.dnf:
name: "*"
state: latest
- name: Grouper par OS family pour la suite
ansible.builtin.group_by:
key: "os_{{ ansible_facts.os_family | lower }}"
- name: 3. Configuration RHEL
hosts: os_redhat
tasks:
- name: Installer firewalld
ansible.builtin.dnf:
name: firewalld
state: present
- name: 4. Configuration Debian
hosts: os_debian
tasks:
- name: Installer ufw
ansible.builtin.apt:
name: ufw
state: present

Quatre plays, un seul fichier. Sans ces modules, il faudrait des scripts shell intermédiaires + plusieurs invocations d’Ansible.

Les modules add_host et group_by sont volatils. Pour persister un host découvert au runtime, écrire l’inventaire :

- name: Persister la liste des nouvelles VMs
ansible.builtin.template:
src: inventory.j2
dest: ./inventory/runtime-discovered.yml
mode: "0644"
delegate_to: localhost
vars:
discovered_hosts: "{{ groups['new_vms'] }}"

Avec inventory.j2 :

---
all:
children:
discovered:
hosts:
{% for h in discovered_hosts %}
{{ h }}:
ansible_host: {{ hostvars[h]['ansible_host'] | default(h) }}
{% endfor %}

Le fichier généré est utilisable par les commandes Ansible futures : ansible-playbook -i ./inventory/runtime-discovered.yml ....

BesoinOutil
Inventaire stable connu d’avanceStatique YAML (inventory/hosts.yml)
Source externe (cloud, NetBox, libvirt)Plugin d’inventaire (libvirt, AWS, Proxmox)
Ajouter un hôte juste-en-temps dans un playadd_host:
Cibler par caractéristique runtime (OS, capacité)group_by:
Voir des VMs créées par le play courantmeta: refresh_inventory
Persister une découverte runtimetemplate: + fichier d’inventaire
SymptômeCauseFix
add_host exécuté mais hôte absent au play suivantPlays définis dans des fichiers séparésMettre tous les plays dans le même playbook YAML
group_by ne crée pas le groupe attendugather_facts désactivéActiver gather_facts: true dans le play parent
Plugin dynamique ne voit pas la nouvelle VMCache du pluginmeta: refresh_inventory + --refresh-cache au besoin
Variables passées à add_host ignoréesRéservé : ne pas overrider ansible_host avec mauvaise valeurVérifier ansible-inventory --host <new> après le play
add_host plante en CITentative d’exécuter sur un host déjà existantadd_host est idempotent, mais le groups: ajouté peut poser problème
  • add_host: = ajouter un hôte au runtime, utilisable par les plays suivants. Volatil.
  • group_by: = créer un groupe basé sur les facts (ansible_os_family, etc.). Volatil.
  • meta: refresh_inventory = forcer le rechargement d’un plugin avec cache. À placer entre deux plays.
  • Combinaison des 3 = workflow provision + configure en un seul playbook.
  • Persister un inventaire runtime nécessite d’écrire un fichier YAML via template:.
  • Plays séparés : add_host et group_by ne sont visibles que dans les plays suivants du même playbook.

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