Aller au contenu
Infrastructure as Code medium

any_errors_fatal Ansible : arrêter le play sur 1ère erreur cluster

10 min de lecture

Logo Ansible

Par défaut, si une tâche échoue sur un hôte mais réussit sur les autres, Ansible continue le play sur les hôtes restants. Avec any_errors_fatal: true au niveau du play, dès qu’une tâche échoue sur n’importe quel hôte, le play s’arrête net pour tous les hôtes. C’est l’inverse philosophique d’ignore_errors: — ici on veut une opération atomique sur le cluster : soit toutes les machines sont OK, soit on arrête tout.

C’est l’outil pour les rolling updates stricts ou les migrations cluster où une moitié-réussite est pire qu’un échec total.

  • L’effet de any_errors_fatal: true au niveau du play
  • La différence avec max_fail_percentage: 0
  • Cas d’usage : rolling update strict, migration de schéma, opération all-or-nothing
  • Combinaison avec serial:
- name: Migration cluster atomique
hosts: webservers
any_errors_fatal: true
tasks:
- name: Tâche critique
ansible.builtin.command: /usr/local/bin/migrate.sh

Si migrate.sh échoue sur n’importe quel webserver, le play s’arrête immédiatement — même les hôtes qui ont réussi voient leurs tâches suivantes non exécutées.

Les deux directives sont liées mais subtilement différentes :

DirectiveEffet
any_errors_fatal: trueArrête le play dès la 1ère erreur sur n’importe quel hôte
max_fail_percentage: 0Arrête le play si plus de 0% des hôtes du batch courant ont échoué (= dès la 1ère erreur du batch, pour le batch courant)
max_fail_percentage: 30Arrête si plus de 30% du batch a échoué

Avec serial:, la nuance compte : max_fail_percentage: 0 arrête seulement le batch courant, any_errors_fatal: true arrête tout immédiatement.

# Rolling update : arrêter dès qu'un hôte échoue, pas continuer sur les autres
- name: Déploiement cluster strict
hosts: webservers
serial: 1
any_errors_fatal: true
tasks: [...]

Sur 5 webservers en serial: 1, si web2 échoue, web3, web4, web5 ne sont pas déployés (au lieu de l’être avec un comportement par défaut).

- name: Migrer le schéma sur tous les replica
hosts: dbservers
any_errors_fatal: true
tasks:
- name: Lancer la migration
ansible.builtin.command: /usr/local/bin/migrate-schema.sh

Si la migration échoue sur un seul replica, vous voulez arrêter immédiatement plutôt que continuer et créer des replica désynchronisés.

- name: Renouveler les certificats sur tout le cluster
hosts: all
any_errors_fatal: true
tasks:
- name: Lancer certbot
ansible.builtin.command: /usr/bin/certbot renew --no-self-upgrade

Si un nœud échoue, on arrête plutôt que de partager des certificats expirant à des moments différents.

- name: Arrêter un service partout en même temps (maintenance)
hosts: webservers
any_errors_fatal: true
tasks:
- name: Stopper le service
ansible.builtin.systemd:
name: app
state: stopped

Avant une maintenance globale, vous voulez soit tout arrêter, soit rien — un état partiel laisse des hôtes inutilisables tandis que d’autres tournent.

Cas pratique — validation syntaxe (lab ecrire-code/any-errors-fatal)

Section intitulée « Cas pratique — validation syntaxe (lab ecrire-code/any-errors-fatal) »

Voici l’exemple validé sur le lab 25-ecrire-code-any-errors-fatal :

- name: Challenge any errors fatal
hosts: webservers
become: true
any_errors_fatal: true
tasks:
- name: Marqueur sans erreur
ansible.builtin.copy:
dest: "/tmp/anyfatal-{{ inventory_hostname }}.txt"
content: "any_errors_fatal OK\n"

Sans erreur réelle, le play tourne normalement et pose 2 fichiers (web1 + web2). Pour prouver que any_errors_fatal: true arrête tout, il faudrait injecter une erreur — ce qui casserait le test (le play s’arrête en failed).

Le comportement réel se vérifie en injectant volontairement un échec : on observe alors que tous les webservers ont leurs tâches suivantes non exécutées.

any_errors_fatal: est une directive de play par défaut. Depuis Ansible 2.7, on peut aussi la poser au niveau block :

- block:
- name: Tâche critique 1
...
- name: Tâche critique 2
...
any_errors_fatal: true

Effet : l’échec d’une tâche du block sur n’importe quel hôte arrête le play. Hors du block, le comportement par défaut reprend.

SymptômeCauseFix
any_errors_fatal: true au niveau taskPas supportéLe mettre au niveau play ou block
Play s’arrête trop vite avec une erreur “secondaire”C’est le comportement attenduConsidérer max_fail_percentage: plus permissif si la tolérance est OK
Combiné avec ignore_errors: trueignore_errors: neutralise l’effetChoisir l’un ou l’autre
Combiné avec block/rescueLe rescue peut “capturer” et neutraliser any_errors_fatalBien réfléchir à l’interaction
serial: 1 + any_errors_fatal: true mais le play continue après échecVérifier qu’il n’y a pas un block/rescue qui captureLogiquement, any_errors_fatal doit gagner sauf rescue
  • any_errors_fatal: true au niveau play : arrête le play dès la 1ère erreur sur n’importe quel hôte.
  • Différent de max_fail_percentage: 0 qui agit sur le batch courant (avec serial:).
  • Cas d’usage : migration cluster atomique, renouvellement de certificats, arrêt synchrone de service.
  • Combiné avec serial: strict : un seul échec arrête tout le rolling update.
  • Disponible aussi au niveau block depuis Ansible 2.7.

Cette page a un lab d’accompagnement : labs/ecrire-code/any-errors-fatal/ dans stephrobert/ansible-training. Il contient un README.md guidé, un Makefile (make verify lance les tests), et un challenge final auto-évalué : play avec any_errors_fatal: true sur webservers (validation de la syntaxe sans erreur).

Une fois le lab provisionné :

Fenêtre de terminal
cd ~/Projets/ansible-training/labs/ecrire-code/any-errors-fatal/
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