Polarys
Automatisation avec Ansible/Fiabiliser ses playbooks

Fiabiliser ses playbooks

Gérer les erreurs et les exécutions partielles

Le comportement par défaut, et ses limites

Par défaut, une tâche qui échoue sur un hôte retire cet hôte du reste du playbook. Les autres continuent.

Ce comportement est raisonnable, et il produit une situation inconfortable : un parc à moitié configuré, dont l'état exact n'est plus connu. C'est pire qu'un échec net, parce que personne ne sait où reprendre.

Les mécanismes qui suivent servent à choisir ce qui arrive, plutôt qu'à le subir.

Décider ce qui compte comme un échec

- name: Vérifier la présence du service
  ansible.builtin.command: systemctl is-active monservice
  register: etat
  failed_when: false
  changed_when: false

- name: Alerter si le service est arrêté
  ansible.builtin.debug:
    msg: "Service arrêté sur {{ inventory_hostname }}"
  when: etat.rc != 0

failed_when: false dit qu'un code de retour non nul n'est pas une erreur ici. changed_when: false dit que cette tâche ne modifie rien : sans elle, une simple vérification apparaît comme un changement, et le rapport devient illisible.

ignore_errors: true existe aussi, et c'est le plus mauvais des trois : il masque l'erreur sans la qualifier. Réservez-le au dépannage.

Arrêter tout le monde quand c'est nécessaire

- hosts: serveurs_web
  max_fail_percentage: 20
  serial: 5

serial: 5 traite les machines par lots de cinq. max_fail_percentage: 20 interrompt le playbook si plus d'un cinquième des machines du lot échoue.

L'intérêt est direct : une mise à jour qui casse s'arrête après cinq machines au lieu de cinquante. C'est la protection la plus rentable d'un playbook de production, et elle tient en deux lignes.

Pour un arrêt immédiat sur tout le parc dès la première défaillance : any_errors_fatal: true.

Nettoyer après un échec

- block:
    - name: Basculer en maintenance
      ansible.builtin.command: /opt/app/maintenance on
    - name: Déployer
      ansible.builtin.command: /opt/app/deploy.sh
  rescue:
    - name: Revenir à la version précédente
      ansible.builtin.command: /opt/app/rollback.sh
  always:
    - name: Sortir de maintenance
      ansible.builtin.command: /opt/app/maintenance off

rescue s'exécute en cas d'échec, always dans tous les cas. Le bloc always est ce qui évite de laisser un parc en mode maintenance parce qu'une tâche a échoué au milieu.

Reprendre après un échec partiel

Ansible écrit un fichier listant les hôtes en échec. Il permet de rejouer uniquement sur eux :

ansible-playbook site.yml --limit @/home/ops/site.retry

C'est utile, et cela suppose l'idempotence de la leçon précédente : sans elle, rejouer sur des machines partiellement traitées est risqué.

Les gestionnaires, un piège fréquent

Un gestionnaire déclenché par une tâche ne s'exécute qu'à la fin du playbook. Si une tâche ultérieure échoue, le redémarrage prévu n'a pas lieu : la configuration est en place, le service tourne encore avec l'ancienne.

force_handlers: true impose leur exécution même en cas d'échec. À poser sur tout playbook qui modifie une configuration de service.

À retenir

Qualifiez les erreurs avec failed_when plutôt que de les ignorer. serial et max_fail_percentage évitent de casser tout le parc. block/rescue/always garantit le nettoyage, et force_handlers évite le service laissé sur l'ancienne configuration.

Quiz de validation

Quiz - 3 questions

1. Quelle combinaison évite de casser tout un parc avec une mise à jour défectueuse ?

2. Pourquoi poser force_handlers sur un playbook qui modifie une configuration de service ?

3. Quelle option masque une erreur sans la qualifier, et devrait rester réservée au dépannage ?

Suis ta progression

Crée un compte gratuit pour suivre ta progression et accéder à toutes les leçons.