
Une tâche Ansible standard bloque la connexion SSH jusqu’à ce qu’elle finisse. Pour une compilation de 30 minutes, un dnf upgrade complet ou un reboot, ce comportement pose deux problèmes : timeout SSH (la connexion lâche) et monopolisation du worker (les autres hôtes attendent). Le mode async détache la tâche du worker — elle tourne en arrière-plan côté managed node, et Ansible la surveille par polling.
Cette page couvre les trois patterns : async + poll > 0 (surveillance synchrone), async + poll: 0 (fire-and-forget), et la combinaison async_status (suivre une tâche async lancée plus tôt).
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »async:: durée maximale d’une tâche en arrière-plan (timeout) ;poll:: intervalle de surveillance (en secondes) ;poll: 0= fire-and-forget ;async_status: module qui vérifie l’état d’une tâche async à un moment donné ;- Le pattern fire-and-forget suivi d’une vérification ultérieure ;
- Les modules incompatibles avec async (
raw,meta).
Le problème : timeout SSH sur tâches longues
Section intitulée « Le problème : timeout SSH sur tâches longues »Imaginez :
- name: Mettre à jour tous les paquets (peut prendre 20 minutes) ansible.builtin.dnf: name: "*" state: latestSur un serveur avec 200 paquets à mettre à jour, cette tâche prend 20-30 minutes. SSH coupe la connexion après le ssh_args de default 60s (avec ControlPersist=60s), et le timeout du module fait planter l’opération.
Mode async :
- name: Mettre à jour tous les paquets (async) ansible.builtin.dnf: name: "*" state: latest async: 1800 # max 30 min côté managed node poll: 30 # vérifier toutes les 30sLa tâche fork côté managed node, Ansible se déconnecte après le démarrage et revient toutes les 30 secondes pour vérifier l’avancement. La connexion SSH ne reste jamais ouverte plus de quelques secondes.
Les trois patterns
Section intitulée « Les trois patterns »Pattern 1 — async + poll > 0 : surveillance synchrone
Section intitulée « Pattern 1 — async + poll > 0 : surveillance synchrone »- name: Build long avec surveillance ansible.builtin.shell: make -j4 args: chdir: /srv/build async: 3600 # max 1 heure poll: 60 # vérifier toutes les 60sLe play attend la fin (mais sans monopoliser SSH). C’est le pattern par défaut quand vous ne savez pas si la tâche peut échouer et que vous voulez bloquer si oui.
Pattern 2 — async + poll: 0 : fire-and-forget
Section intitulée « Pattern 2 — async + poll: 0 : fire-and-forget »- name: Lancer un backup en arrière-plan ansible.builtin.shell: /usr/local/bin/backup.sh async: 7200 # max 2 heures poll: 0 # fire-and-forget register: backup_jobAvec poll: 0, Ansible lance la tâche, récupère un ID de job, et passe immédiatement à la suite. La tâche tourne indépendamment côté managed node. Cas typique : un backup qui doit s’exécuter sans bloquer le déploiement.
Pattern 3 — async_status : suivre une tâche fire-and-forget
Section intitulée « Pattern 3 — async_status : suivre une tâche fire-and-forget »Pour récupérer le statut d’une tâche fire-and-forget plus tard :
- name: Lancer le backup ansible.builtin.shell: /usr/local/bin/backup.sh async: 7200 poll: 0 register: backup_job
# ... d'autres tâches ...
- name: Attendre la fin du backup ansible.builtin.async_status: jid: "{{ backup_job.ansible_job_id }}" register: backup_result until: backup_result.finished retries: 60 delay: 60 # 60 retries x 60s = 1h max d'attenteuntil: backup_result.finished répète la vérification jusqu’à ce que le job soit fini. retries: 60 + delay: 60 autorisent jusqu’à 1 heure d’attente.
Cas pratique — reboot avec retour
Section intitulée « Cas pratique — reboot avec retour »Un reboot coupe SSH en plein milieu et ne peut pas être géré comme une tâche normale. Le pattern :
- name: Reboot du système ansible.builtin.reboot: msg: "Reboot pour appliquer le nouveau kernel" reboot_timeout: 300 # attendre max 5 min que SSH revienne test_command: uptimeLe module ansible.builtin.reboot gère automatiquement :
- La déconnexion attendue après le
shutdown -r; - L’attente que SSH revienne (
reboot_timeout) ; - La vérification que le système est opérationnel (
test_command).
Pas besoin d’async — reboot est conçu pour ça. Mais le pattern async est utile quand vous voulez lancer un reboot et ne pas attendre (par exemple en mode rolling où chaque hôte reboote indépendamment) :
- name: Reboot fire-and-forget ansible.builtin.shell: sleep 5 && shutdown -r now async: 60 poll: 0Limites et incompatibilités
Section intitulée « Limites et incompatibilités »Modules incompatibles
Section intitulée « Modules incompatibles »Certains modules ne peuvent pas tourner en async :
raw: trop bas niveau (pas de Python pour gérer le job)meta: méta-actions internes (flush_handlers)- Les modules interactifs (rares)
Ansible vous le signale avec un message clair en cas d’usage incorrect.
Timeout vs retries
Section intitulée « Timeout vs retries »| Paramètre | Rôle |
|---|---|
async: 3600 | Côté managed node : tue la tâche si pas finie en 1h |
until + retries + delay | Côté control node : attend N retries x delay secondes |
Les deux limites s’appliquent simultanément — la plus stricte gagne.
Async ne contourne pas le check_mode
Section intitulée « Async ne contourne pas le check_mode »Un async en --check se comporte comme une tâche normale en check : il simule sans rien lancer en arrière-plan. Pas de surprise.
Pièges fréquents
Section intitulée « Pièges fréquents »| Symptôme | Cause | Fix |
|---|---|---|
async_status retourne finished: 0 indéfiniment | Le job a été tué par le timeout async: | Augmenter async: ou paralléliser le travail |
| Job fire-and-forget perdu (pas de jid pour le suivre) | register: oublié sur la tâche async | Toujours register: var quand poll: 0 |
Module async qui plante avec module not supported | Module non compatible (raw, meta) | Bascule en mode synchrone, ou wrap dans un shell: |
until: result.finished plante avec 'NoneType' has no attribute | La première vérif async_status n’a pas encore le job | Ajouter register: result à la tâche async_status: (pas la tâche d’origine) |
async: 0 (zéro) au lieu de fire-and-forget | async: 0 = synchrone (ignore async) ; pour fire-and-forget c’est poll: 0 | Bien mettre async: <timeout> + poll: 0 |
À retenir
Section intitulée « À retenir »async: <secondes>détache la tâche du worker SSH — Ansible vérifie périodiquement, pas de timeout SSH.poll: <secondes>= surveillance synchrone (le play attend la fin, sans bloquer SSH).poll: 0= fire-and-forget : Ansible lance la tâche, récupère un ID viaregister:, et continue.async_status:+until:+retries: + delay:suit une tâche fire-and-forget jusqu’à sa fin.ansible.builtin.rebootgère automatiquement le reboot + reconnexion SSH — pas besoin d’async pour ce cas.- Les modules
rawetmetane supportent pas async.
Pratiquer dans le lab
Section intitulée « Pratiquer dans le lab »Cette page a un lab d’accompagnement : labs/ecrire-code/async-poll/ dans
stephrobert/ansible-training. Il contient
un README.md guidé, un Makefile (make verify lance les tests), et un
challenge final auto-évalué : lancer un job async (sleep 5) en fire-and-forget puis attendre via async_status.
Une fois le lab provisionné :
cd ~/Projets/ansible-training/labs/ecrire-code/async-poll/
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).