Leçon 4 / 6
Leçon 04 · Ansible

Les playbooks

C'est quoi un playbook ?

Un playbook est un fichier YAML qui décrit ce qu'Ansible doit faire sur tes serveurs. C'est le cœur d'Ansible : tu y définis une liste de tâches à exécuter sur un ou plusieurs groupes d'hôtes, dans l'ordre, de façon déclarative et idempotente.

Un playbook peut installer des paquets, copier des fichiers de configuration, démarrer des services, créer des utilisateurs — et tout ça en un seul fichier versionnable dans Git.

Structure d'un playbook

Un playbook est une liste de plays. Chaque play cible un groupe d'hôtes et contient une liste de tâches.

---  # le triple tiret marque le début d'un fichier YAML
# Un playbook est une liste de plays

- name: Mon premier play     # nom du play (documentation)
  hosts: webservers           # groupe d'hôtes ciblé (depuis l'inventaire)
  become: true               # élévation de privilèges (sudo)

  tasks:                      # liste des tâches à exécuter
    - name: Installer curl    # nom de la tâche
      ansible.builtin.apt:    # module utilisé
        name: curl
        state: present         # present = installé, absent = supprimé
💡

L'indentation YAML est critique : utilise toujours des espaces (jamais de tabulations). Deux espaces par niveau est la convention Ansible.

Les tasks — le cœur du playbook

Chaque tâche appelle un module Ansible avec des paramètres. Les modules les plus courants :

  • ansible.builtin.apt / ansible.builtin.yum — gestion des paquets
  • ansible.builtin.copy — copier un fichier depuis le contrôleur vers l'hôte
  • ansible.builtin.template — copier un fichier Jinja2 avec des variables
  • ansible.builtin.service — démarrer, arrêter, redémarrer un service
  • ansible.builtin.user — créer ou gérer des utilisateurs
  • ansible.builtin.file — créer des dossiers, gérer les permissions
  • ansible.builtin.command / ansible.builtin.shell — exécuter une commande

Playbook complet : installer Nginx sur Ubuntu

Voici un playbook réaliste qui installe Nginx, déploie une configuration personnalisée, et s'assure que le service est démarré et activé au boot.

---
- name: Déployer Nginx
  hosts: webservers
  become: true

  tasks:

    - name: Mettre à jour le cache apt
      ansible.builtin.apt:
        update_cache: true
        cache_valid_time: 3600   # ne rafraîchit que si > 1h

    - name: Installer Nginx
      ansible.builtin.apt:
        name: nginx
        state: present

    - name: Copier la configuration Nginx
      ansible.builtin.template:
        src: templates/nginx.conf.j2   # fichier Jinja2 sur le contrôleur
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: "0644"
      notify: Redémarrer Nginx         # déclenche le handler si le fichier change

    - name: S'assurer que Nginx est démarré et activé
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true              # activé au démarrage du système

  handlers:                          # exécutés une seule fois à la fin du play
    - name: Redémarrer Nginx
      ansible.builtin.service:
        name: nginx
        state: restarted

Les handlers — réagir aux changements

Un handler est une tâche spéciale déclenchée uniquement si une tâche l'a notifié via notify: et que la tâche a effectivement produit un changement (changed). Si la configuration Nginx n'a pas changé, le handler ne s'exécute pas.

Les handlers s'exécutent une seule fois, à la fin du play, même si plusieurs tâches ont notifié le même handler. C'est parfait pour éviter des redémarrages inutiles.

⚠️

Un handler n'est déclenché que si la tâche qui le notifie retourne changed. Si Nginx est déjà installé et que la config n'a pas bougé, le handler ne sera pas appelé. C'est l'idempotence en action.

Variables dans les playbooks

Tu peux définir des variables directement dans le playbook avec vars:, puis les utiliser avec la syntaxe Jinja2 .

---
- name: Installer un serveur web configurable
  hosts: webservers
  become: true

  vars:                               # déclaration des variables du play
    web_port: 8080
    app_user: www-data
    packages:
      - nginx
      - curl
      - git

  tasks:

    - name: Créer l'utilisateur applicatif
      ansible.builtin.user:
        name: ""         # utilisation de la variable
        system: true
        shell: /usr/sbin/nologin

    - name: Créer le répertoire de l'app
      ansible.builtin.file:
        path: /var/www/app
        state: directory
        owner: ""
        mode: "0755"

Conditions — when

La directive when: permet d'exécuter une tâche seulement si une condition est vraie. Tu peux utiliser les facts Ansible (variables collectées automatiquement sur chaque hôte) comme ansible_distribution, ansible_os_family, ansible_architecture.

  tasks:

    - name: Installer Nginx (Debian/Ubuntu)
      ansible.builtin.apt:
        name: nginx
        state: present
      when: ansible_distribution == "Ubuntu"   # seulement sur Ubuntu

    - name: Installer Nginx (CentOS/RHEL)
      ansible.builtin.yum:
        name: nginx
        state: present
      when: ansible_os_family == "RedHat"     # seulement sur RedHat/CentOS

    - name: Tâche multi-conditions
      ansible.builtin.debug:
        msg: "Serveur 64 bits sous Ubuntu"
      when:
        - ansible_distribution == "Ubuntu"    # liste = ET logique
        - ansible_architecture == "x86_64"

Les facts sont collectés automatiquement avant chaque play via le module gather_facts (activé par défaut). Pour accélérer un playbook, désactive-les avec gather_facts: false si tu n'en as pas besoin.

Boucles — loop et with_items

Plutôt que d'écrire une tâche par paquet à installer, utilise loop: pour itérer sur une liste. La valeur courante est disponible dans .

  tasks:

    - name: Installer les paquets nécessaires
      ansible.builtin.apt:
        name: ""          # item = valeur courante de la boucle
        state: present
      loop:                         # loop: remplace l'ancien with_items:
        - nginx
        - git
        - curl
        - htop

    - name: Créer plusieurs répertoires
      ansible.builtin.file:
        path: ""
        state: directory
        mode: "0755"
      loop:
        - /var/www/app
        - /var/log/app
        - /etc/app
💡

with_items: est l'ancienne syntaxe de boucle, toujours supportée. loop: est la syntaxe moderne recommandée depuis Ansible 2.5. Les deux font la même chose pour les cas simples.

Exécuter un playbook

La commande ansible-playbook est ton point d'entrée pour lancer un playbook.

# Lancer un playbook avec un inventaire spécifique
ansible-playbook -i inventory.ini playbook.yml

# Mode dry-run : simuler sans rien modifier (--check)
ansible-playbook -i inventory.ini playbook.yml --check

# Voir le détail de chaque changement (--diff)
ansible-playbook -i inventory.ini playbook.yml --diff

# Cibler seulement certains hôtes avec --limit
ansible-playbook -i inventory.ini playbook.yml --limit web01

# Passer des variables en ligne de commande
ansible-playbook -i inventory.ini playbook.yml -e "web_port=9000"

# Mode verbeux pour déboguer (-v, -vv, -vvv)
ansible-playbook -i inventory.ini playbook.yml -v

Pendant l'exécution, Ansible affiche l'état de chaque tâche : ok (rien changé), changed (modification effectuée), failed (erreur), skipped (condition when non remplie).

// à retenir
  • Un playbook = fichier YAML qui liste des plays, chaque play ciblant des hôtes et contenant des tasks.
  • become: true active l'élévation de privilèges (sudo) pour le play entier.
  • Chaque task appelle un module (apt, template, service…) avec des paramètres.
  • Les handlers s'exécutent une seule fois en fin de play, uniquement si une task les a notifiés et a changé quelque chose.
  • vars: déclare des variables, les utilise. when: conditionne, loop: itère.
  • ansible-playbook -i inventory playbook.yml lance le playbook. Ajoute --check pour simuler.