Aller au contenu
Infrastructure as Code medium

Plays et tasks Ansible : anatomie complète, ordre d'exécution, mots-clés

11 min de lecture

Logo Ansible

Un playbook est une liste ordonnée de plays, chaque play ciblant un groupe d’hôtes avec une séquence de tâches précise. Cette page décortique l’anatomie complète d’un play — au-delà du hosts: + tasks: minimal — et explique l’ordre d’exécution exact des sections (pre_tasksrolestaskspost_taskshandlers). Comprendre cet ordre est essentiel pour structurer correctement vos playbooks et éviter les surprises sur les handlers déclenchés trop tôt ou trop tard.

Cette page se concentre sur l’anatomie. Les mots-clés de parallélisme (serial:, strategy:, max_fail_percentage:) ont leur page dédiée — voir Parallélisme et stratégies.

  • L’anatomie complète d’un play et ses mots-clés principaux ;
  • L’ordre d’exécution strict : gather_factspre_tasksrolestaskspost_taskshandlers ;
  • Comment enchaîner plusieurs plays dans un même playbook ;
  • La différence entre environment: au niveau play, task et bloc ;
  • Le pattern meta: flush_handlers pour forcer les handlers entre deux sections.

Voici un play qui utilise la majorité des mots-clés disponibles :

---
- name: Déployer nginx avec rolling update
hosts: webservers
become: true
gather_facts: true
vars:
nginx_version: "1.26.1"
nginx_workers: 4
vars_files:
- vars/secrets.yml
environment:
PATH: "/usr/local/bin:{{ ansible_env.PATH }}"
TZ: Europe/Paris
pre_tasks:
- name: Drainer le load-balancer
ansible.builtin.debug:
msg: "Drainer {{ inventory_hostname }} du LB"
roles:
- role: nginx
vars:
nginx_port: 80
tasks:
- name: Vérifier que nginx répond
ansible.builtin.uri:
url: "http://{{ inventory_hostname }}/health"
status_code: 200
post_tasks:
- name: Réintégrer dans le load-balancer
ansible.builtin.debug:
msg: "Réintégrer {{ inventory_hostname }} dans le LB"
handlers:
- name: Recharger nginx
ansible.builtin.systemd:
name: nginx
state: reloaded

Chaque mot-clé a un rôle précis. Voyons-les un par un.

Description humaine du play, affichée dans le PLAY RECAP. Doit décrire l’objectif business, pas la liste des modules.

Pattern d’hôtes ciblé. Exemples : all, webservers, webservers:!web1, web*:&rhce_lab.

become: true élève en root via sudo. become_user: postgres exécute en tant qu’utilisateur dédié (utile pour pg_* commands). Peut être mis au niveau du play, du block, ou de la task.

gather_facts: true (défaut) lance le module setup au début et expose ansible_facts.*. Mettre false pour gagner quelques secondes si vous savez ne pas utiliser de facts. gather_subset: '!all,network' restreint à un sous-ensemble (gain de perf sur fleets très grandes).

vars: injecte des variables locales au play. vars_files: charge des fichiers YAML externes (utile pour les secrets vars_files: - vars/secrets.yml chiffrés Vault).

Injecte des variables d’environnement dans le shell qui exécute les modules. Utile pour http_proxy, PATH, LANG. Peut être posé au niveau play, block, ou task — la valeur la plus locale gagne.

environment:
HTTP_PROXY: http://proxy.example.com:3128
LANG: en_US.UTF-8

Les sections : pre_tasks, tasks, post_tasks, handlers, roles

Section intitulée « Les sections : pre_tasks, tasks, post_tasks, handlers, roles »

Un play exécute ses sections dans cet ordre strict :

1. gather_facts (si true)
2. pre_tasks ← tâches AVANT les rôles
3. handlers déclenchés par les pre_tasks
4. roles ← rôles importés
5. tasks ← tâches inline
6. handlers déclenchés par les tasks/roles
7. post_tasks ← tâches APRÈS le reste
8. handlers déclenchés par les post_tasks

Les handlers sont déclenchés à la fin de chaque section qui les a notifiés — pas à la toute fin du play. Conséquence : si vous redémarrez nginx via un handler dans tasks:, le post_tasks: voit déjà le service redémarré.

Tâches exécutées avant les rôles. Cas typiques :

  • Drainer un load-balancer avant de toucher aux serveurs ;
  • Snapshotter une base de données ;
  • Vérifier un prérequis externe (DNS, certificat, accès réseau).

Le cœur du play. Tâches inline qui s’exécutent après les rôles.

Tâches exécutées après tout le reste. Cas typiques :

  • Réintégrer dans le load-balancer ;
  • Notifier Slack/Teams/PagerDuty ;
  • Écrire un journal de déploiement dans une base.

Liste de rôles à importer. Voir la section dédiée Rôles (à venir).

Tâches réactives qui ne s’exécutent que si elles sont notifiées par une autre tâche via notify:. Voir la page dédiée Handlers.

Un playbook YAML peut contenir plusieurs plays — exécutés séquentiellement :

---
- name: Configurer la base de données
hosts: dbservers
become: true
tasks:
- name: Installer PostgreSQL
ansible.builtin.dnf:
name: postgresql-server
state: present
- name: Déployer l'application
hosts: webservers
become: true
tasks:
- name: Installer nginx
ansible.builtin.dnf:
name: nginx
state: present

Le second play ne démarre que si le premier réussit sur ses hôtes (sauf si le premier hôte a unreachable=true, le play continue par défaut sur les autres).

Par défaut, les handlers déclenchés dans pre_tasks: ou tasks: ne tournent qu’à la fin de leur section. Pour les forcer à s’exécuter immédiatement (par exemple avant un smoke test), utiliser :

tasks:
- name: Modifier la conf nginx
ansible.builtin.copy:
dest: /etc/nginx/conf.d/site.conf
content: "..."
notify: Recharger nginx
- name: Forcer le reload avant la suite
ansible.builtin.meta: flush_handlers
- name: Smoke test
ansible.builtin.uri:
url: http://localhost
status_code: 200

Sans meta: flush_handlers, le smoke test tournerait avant le reload — donc sur l’ancienne config. Le pattern est essentiel dès que vous avez besoin de tester l’effet d’un handler dans la même section.

SymptômeCauseFix
Handlers exécutés trop tardVous attendiez qu’ils tournent avant post_tasksForcer le déclenchement avec meta: flush_handlers à la fin de tasks:
pre_tasks lance des handlers… mais ils tournent à la finC’est le comportement standardAjouter - meta: flush_handlers après les pre_tasks:
environment: ne s’applique pasLa var est posée sur le play mais surchargée au niveau taskLa règle : la var la plus locale gagne. Vérifier les niveaux play/block/task
Plusieurs plays mais le second ne démarre pasLe premier a marqué tous les hôtes en failed ou unreachableVérifier le PLAY RECAP, ajouter ignore_errors: true si pertinent
  • Un play déclare hosts:, exécute pre_tasksrolestaskspost_tasks, avec handlers intercalés à chaque section qui les notifie.
  • gather_facts: false + gather_subset: sont les leviers de performance sur grandes fleets.
  • environment: injecte des variables d’environnement avec règle “le plus local gagne” (play < block < task).
  • meta: flush_handlers force les handlers à tourner immédiatement, sans attendre la fin de la section.
  • Pour le parallélisme (serial:, strategy:, max_fail_percentage:), voir Parallélisme et stratégies.

Cette page a un lab d’accompagnement : labs/ecrire-code/plays-et-tasks/ dans stephrobert/ansible-training. Il contient un README.md guidé, un Makefile (make verify lance les tests), et un challenge final auto-évalué : reproduire le pattern pre_tasks + tasks + post_tasks + handlers sur db1.lab avec httpd.

Une fois le lab provisionné :

Fenêtre de terminal
cd ~/Projets/ansible-training/labs/ecrire-code/plays-et-tasks/
cat README.md # tuto pas à pas
cat challenge/README.md # consigne du challenge final
pytest -v challenge/tests/ # lancer les tests testinfra

Si 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).

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