Passer au contenu principal

Production (Ansible)

Stratégies d'exécution

Par défaut, Ansible exécute chaque tâche sur tous les hôtes en parallèle avant de passer à la suivante. C'est la stratégie linear. En production, cette approche naïve peut mettre à terre un service si tous les nœuds redémarrent simultanément. Les stratégies d'exécution permettent de contrôler finement ce comportement.

forks : parallélisme

Le paramètre forks contrôle combien d'hôtes sont traités simultanément. Défaut : 5.

# ansible.cfg
[defaults]
forks = 20
# Override en ligne de commande
ansible-playbook site.yml -f 20

Augmenter les forks accélère l'exécution mais consomme plus de ressources sur le nœud de contrôle (connexions SSH concurrentes, processus Python). Une bonne règle : forks = nombre de CPU du nœud de contrôle * 2.

serial : déploiement progressif

serial contrôle combien d'hôtes sont traités par "batch" avant de passer au suivant. Indispensable pour les rolling updates :

- name: Déploiement progressif
  hosts: web
  serial: 1          # un hôte à la fois

  tasks:
    - name: Déployer l'application
      # ...
# Par pourcentage
serial: "25%"   # 25% des hôtes à la fois

# Progression variable : 1 hôte, puis 5, puis le reste
serial:
  - 1
  - 5
  - "100%"

Combiné avec un handler qui vérifie la santé du service, c'est le pattern de base pour un déploiement sans coupure.

delegate_to : déléguer une tâche à un autre hôte

Exécuter une tâche sur un hôte différent de celui ciblé par le play. Cas d'usage classique : désinscrire un nœud d'un load balancer avant de le mettre à jour.

- name: Retirer du load balancer
  community.general.haproxy:
    state: disabled
    host: "{{ inventory_hostname }}"
    backend: web_backend
  delegate_to: lb01.example.com

- name: Mettre à jour l'application
  ansible.builtin.apt:
    name: myapp
    state: latest

- name: Remettre dans le load balancer
  community.general.haproxy:
    state: enabled
    host: "{{ inventory_hostname }}"
    backend: web_backend
  delegate_to: lb01.example.com

delegate_to: localhost est très utilisé pour exécuter des commandes localement (appels API, interactions avec des CLIs cloud).

run_once : exécution unique

Exécute une tâche sur un seul hôte du groupe, même si le play cible plusieurs hôtes. Utile pour les migrations de base de données ou les initialisation de cluster :

- name: Appliquer les migrations de BDD
  ansible.builtin.command:
    cmd: /srv/myapp/manage.py migrate
  run_once: true
  delegate_to: "{{ groups['app'][0] }}"   # toujours sur le premier hôte du groupe

async et poll : tâches longues

Certaines opérations prennent du temps (compilation, sauvegarde, redémarrage de cluster). async lance la tâche en arrière-plan sans bloquer le play :

- name: Lancer la sauvegarde en arrière-plan
  ansible.builtin.command:
    cmd: /usr/local/bin/backup.sh
  async: 3600    # timeout maximum : 1h
  poll: 0        # ne pas attendre (fire and forget)
  register: backup_job

- name: Faire d'autres choses pendant la sauvegarde
  # ...

- name: Attendre la fin de la sauvegarde
  ansible.builtin.async_status:
    jid: "{{ backup_job.ansible_job_id }}"
  register: job_result
  until: job_result.finished
  retries: 60
  delay: 30

Stratégies d'exécution

  • linear (défaut) : tâche par tâche sur tous les hôtes. Attend que tous les hôtes terminent une tâche avant de passer à la suivante.
  • free : chaque hôte avance à son rythme. Plus rapide, mais les logs sont moins lisibles et les dépendances entre hôtes sont délicates.
  • host_pinned : variante de free, un seul hôte à la fois. Utile pour le debugging.
- name: Déploiement rapide indépendant
  hosts: web
  strategy: free
  tasks:
    # ...