Maîtriser les Playbooks Ansible
Le concept fondamental : la Gestion de Configuration
Avant de plonger dans les playbooks, il est essentiel de comprendre le problème qu’ils résolvent.
Historiquement, pour configurer un serveur, un administrateur se connectait en SSH et tapait des commandes manuellement. Cette approche pose plusieurs problèmes :
- Non reproductible : On ne sait plus exactement ce qui a été fait 6 mois plus tard.
- Non scalable : Configurer 1 serveur manuellement, c’est faisable. 50, c’est un calvaire.
- Sujette aux erreurs : Une faute de frappe peut casser un environnement de production.
La gestion de configuration (Configuration Management) résout tout cela en décrivant l’état désiré de l’infrastructure dans des fichiers versionnés. C’est le paradigme Infrastructure as Code (IaC).
Il existe deux grandes approches :
| Approche | Principe | Outils |
|---|---|---|
| Impérative | On décrit les étapes à exécuter (“installe ce paquet, copie ce fichier”) | Scripts Bash, Fabric |
| Déclarative | On décrit l’état final désiré (“ce paquet doit être installé, ce fichier doit avoir ce contenu”) | Ansible, Puppet, Chef, Salt |
Ansible se situe dans une position hybride : ses playbooks sont déclaratifs (on décrit un état) mais les tâches s’exécutent de manière séquentielle comme un script.
Qu’est-ce qu’un Playbook ?
Un Playbook est un fichier écrit en YAML (Yet Another Markup Language) qui décrit une liste de tâches à exécuter sur un ou plusieurs groupes de machines (hosts). C’est votre “recette de cuisine” pour l’état désiré de votre infrastructure.
Principes Clés
- Idempotence : Un playbook peut être exécuté plusieurs fois sans casser le système. Si l’état désiré est déjà atteint (ex: “le fichier doit exister”), Ansible ne fait rien. C’est le principe le plus important.
- Lisibilité : Le format YAML est conçu pour être lisible par les humains, même sans connaissances techniques profondes.
- Ordre : Les tâches sont exécutées séquentiellement, de haut en bas.
- Agentless (sans agent) : Ansible ne nécessite aucun logiciel installé sur les machines cibles. Il utilise uniquement SSH.
- Push-based : C’est la machine de contrôle qui pousse la configuration vers les cibles.
Architecture d’Ansible
Pour bien comprendre les playbooks, il faut saisir comment Ansible fonctionne globalement.
graph LR
subgraph "Machine de contrôle"
PB["📄 Playbook.yml"]
INV["📋 Inventory"]
ROLES["📁 Roles/"]
end
subgraph "Serveurs cibles"
A["🖥️ Serveur A<br/>Debian 12"]
B["🖥️ Serveur B<br/>Ubuntu 24.04"]
C["🖥️ Serveur C<br/>Rocky Linux 9"]
end
PB -->|SSH| A
PB -->|SSH| B
PB -->|SSH| C
INV -.-> PB
ROLES -.-> PBLes composants clés :
- Inventory : Le fichier qui liste les machines cibles et les regroupe.
- Playbook : Le fichier YAML qui décrit les tâches.
- Modules : Les briques unitaires (installer un paquet, copier un fichier, démarrer un service…). Ansible en fournit des milliers.
- Roles : Un mécanisme de structuration pour réutiliser et partager des playbooks.
- Facts : Des informations collectées automatiquement sur les machines cibles (OS, IP, RAM…).
- Vault : Système de chiffrement intégré pour stocker des secrets (mots de passe, clés API).
L’Inventaire (Inventory)
L’inventaire est la première pièce du puzzle. Il définit où vos playbooks vont s’exécuter.
Format INI (basique)
[webservers]web1.example.comweb2.example.com
[dbservers]db1.example.com ansible_user=postgres
[production:children]webserversdbservers
[all:vars]ansible_python_interpreter=/usr/bin/python3Format YAML (plus flexible)
all: children: webservers: hosts: web1.example.com: web2.example.com: http_port: 8080 dbservers: hosts: db1.example.com: ansible_user: postgresStructure d’un Playbook
Un playbook est composé d’une ou plusieurs “plays”. Chaque “play” mappe un groupe d’hôtes à des tâches.
Exemple basique
Voici un playbook simple qui installe et démarre Nginx sur des serveurs web :
---- name: Installer et configurer Nginx hosts: webservers become: yes # Exécuter en tant que root (sudo)
tasks: - name: S'assurer que Nginx est installé apt: name: nginx state: present update_cache: yes
- name: S'assurer que Nginx est démarré service: name: nginx state: started enabled: yesAnalyse des composants
hosts: Définit sur quelles machines ce play va s’exécuter (défini dans votre fichier d’inventaire).become: Indique si les tâches doivent être exécutées avec élévation de privilèges (sudo).tasks: La liste des actions à effectuer.modules:aptetservicesont des modules Ansible. Ce sont les outils qui font le travail réel.
Exemple complet : Déployer une stack LEMP
Voici un playbook réaliste qui illustre plusieurs fonctionnalités simultanément :
---- name: Déployer une stack LEMP complète hosts: webservers become: yes gather_facts: yes
vars: mysql_root_password: '{{ vault_mysql_root_password }}' php_version: '8.2' app_domain: 'monsite.example.com'
pre_tasks: - name: Mettre à jour le cache APT apt: update_cache: yes cache_valid_time: 3600
tasks: - name: Installer les paquets nécessaires apt: name: - nginx - 'php{{ php_version }}-fpm' - 'php{{ php_version }}-mysql' - mariadb-server - python3-pymysql state: present
- name: Déployer la config Nginx depuis un template Jinja2 template: src: templates/nginx-vhost.conf.j2 dest: '/etc/nginx/sites-available/{{ app_domain }}' owner: root group: root mode: '0644' notify: Recharger Nginx
- name: Activer le vhost file: src: '/etc/nginx/sites-available/{{ app_domain }}' dest: '/etc/nginx/sites-enabled/{{ app_domain }}' state: link notify: Recharger Nginx
- name: Configurer le mot de passe root MySQL mysql_user: name: root password: '{{ mysql_root_password }}' login_unix_socket: /var/run/mysqld/mysqld.sock no_log: true
handlers: - name: Recharger Nginx service: name: nginx state: reloadedComment utiliser les Playbooks ?
Prérequis
- Ansible installé sur votre machine de contrôle.
- Un fichier d’inventaire (
hosts.iniouinventory) listant vos serveurs. - Accès SSH configuré vers les machines cibles (clés SSH recommandées).
Exécution
La commande principale est ansible-playbook.
# Syntaxe basiqueansible-playbook -i inventory.ini mon_playbook.ymlOptions utiles
- Vérifier la syntaxe sans exécuter :
Fenêtre de terminal ansible-playbook mon_playbook.yml --syntax-check - Mode “Dry Run” (simulation) pour voir ce qui changerait sans rien modifier :
Fenêtre de terminal ansible-playbook mon_playbook.yml --check - Voir les différences détaillées (utile avec
--check) :Fenêtre de terminal ansible-playbook mon_playbook.yml --diff - Limiter l’exécution à un hôte spécifique :
Fenêtre de terminal ansible-playbook mon_playbook.yml --limit web1.example.com - Commencer à une tâche spécifique (utile pour reprendre après un échec) :
Fenêtre de terminal ansible-playbook mon_playbook.yml --start-at-task="Activer le vhost" - Exécuter avec un tag spécifique :
Fenêtre de terminal ansible-playbook mon_playbook.yml --tags "deploy" - Augmenter la verbosité pour le debug :
Fenêtre de terminal ansible-playbook mon_playbook.yml -vvv
Fonctionnalités Avancées
1. Variables et précédence
Les variables permettent de rendre vos playbooks dynamiques. Elles peuvent être définies à de nombreux endroits avec un ordre de priorité :
- Ligne de commande (
-e "var=value") — la plus haute priorité - Variables de rôle (
roles/x/vars/main.yml) - Variables de play (
vars:dans le playbook) - Variables d’inventaire (
host_vars/,group_vars/) - Valeurs par défaut du rôle (
roles/x/defaults/main.yml) — la plus basse
vars: http_port: 80 max_clients: 200
tasks: - name: Copier le fichier de config template: src: templates/nginx.conf.j2 dest: /etc/nginx/nginx.conf2. Templates Jinja2
Le module template utilise le moteur Jinja2 pour générer des fichiers de configuration dynamiques.
Fichier templates/nginx.conf.j2 :
server { listen {{ http_port }}; server_name {{ app_domain }};
{% for backend in backends %} location /{{ backend.name }} { proxy_pass http://{{ backend.host }}:{{ backend.port }}; } {% endfor %}}3. Handlers (Gestionnaires)
Les handlers sont des tâches spéciales qui ne s’exécutent que si elles sont notifiées par une autre tâche. Très utile pour redémarrer des services uniquement quand la config change.
tasks: - name: Modifier la config Apache template: src: httpd.conf dest: /etc/httpd/conf/httpd.conf notify: - Redémarrer Apache
handlers: - name: Redémarrer Apache service: name: httpd state: restarted4. Conditionnels
Exécuter des tâches selon des conditions.
tasks: - name: Installer Apache sur RedHat yum: name: httpd state: present when: ansible_os_family == "RedHat"
- name: Installer Apache sur Debian apt: name: apache2 state: present when: ansible_os_family == "Debian"5. Loops (Boucles)
Pour répéter une tâche sur plusieurs éléments.
- name: Créer plusieurs utilisateurs user: name: '{{ item.name }}' groups: '{{ item.groups }}' state: present loop: - { name: alice, groups: 'sudo,docker' } - { name: bob, groups: 'docker' } - { name: charlie, groups: 'www-data' }6. Vault (Gestion des secrets)
Ansible Vault permet de chiffrer des données sensibles directement dans vos fichiers YAML.
# Créer un fichier chiffréansible-vault create secrets.yml
# Chiffrer un fichier existantansible-vault encrypt secrets.yml
# Éditer un fichier chiffréansible-vault edit secrets.yml
# Exécuter un playbook qui utilise des secretsansible-playbook site.yml --ask-vault-pass7. Tags
Les tags permettent d’exécuter seulement une partie du playbook.
tasks: - name: Installer les paquets apt: name: nginx state: present tags: - install - packages
- name: Déployer la configuration template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf tags: - config - deployLes Rôles : structurer pour scaler
Pour les projets sérieux, un seul fichier playbook devient ingérable. Les Rôles imposent une structure de répertoire standard qui permet de réutiliser et partager du code.
Structure d’un Rôle
graph TD
ROOT["📁 roles/nginx/"] --> TASKS["📁 tasks/<br/>main.yml"]
ROOT --> HANDLERS["📁 handlers/<br/>main.yml"]
ROOT --> TEMPLATES["📁 templates/<br/>nginx.conf.j2"]
ROOT --> FILES["📁 files/<br/>index.html"]
ROOT --> VARS["📁 vars/<br/>main.yml<br/><i>haute priorité</i>"]
ROOT --> DEFAULTS["📁 defaults/<br/>main.yml<br/><i>basse priorité</i>"]
ROOT --> META["📁 meta/<br/>main.yml"]
style TASKS fill:#4CAF50,color:#fff
style HANDLERS fill:#FF9800,color:#fff
style TEMPLATES fill:#2196F3,color:#fff
style VARS fill:#9C27B0,color:#fff
style DEFAULTS fill:#607D8B,color:#fffUtiliser un Rôle dans un Playbook
---- name: Configurer les serveurs web hosts: webservers become: yes
roles: - common # Rôle de base (sécurité, NTP, etc.) - nginx - { role: app, tags: ['deploy'] }Ansible Galaxy
Ansible Galaxy est un hub communautaire de rôles prêts à l’emploi.
# Installer un rôle depuis Galaxyansible-galaxy install geerlingguy.docker
# Installer les rôles listés dans un fichier requirementsansible-galaxy install -r requirements.ymlBonnes Pratiques
- Nommez toujours vos tâches (
name: ...) : Cela rend la sortie de la commande compréhensible. - Utilisez le contrôle de version (Git) : Vos playbooks sont du code (“Infrastructure as Code”).
- Séparez les rôles : Pour les projets complexes, ne mettez pas tout dans un seul fichier. Utilisez la structure de Rôles d’Ansible (
ansible-galaxy init mon_role). - Testez avec
--checkavant d’appliquer sur la prod. - Utilisez
ansible-lint: Un linter dédié qui vérifie les bonnes pratiques dans vos playbooks.Fenêtre de terminal pip install ansible-lintansible-lint mon_playbook.yml - Structurez vos projets avec un layout standard :
graph TD
PROJECT["📁 project/"] --> CFG["⚙️ ansible.cfg"]
PROJECT --> INVENTORY["📁 inventory/"]
PROJECT --> GROUPVARS["📁 group_vars/"]
PROJECT --> HOSTVARS["📁 host_vars/"]
PROJECT --> ROLES["📁 roles/"]
PROJECT --> PLAYBOOKS["📁 playbooks/"]
INVENTORY --> PROD["production"]
INVENTORY --> STAGING["staging"]
GROUPVARS --> ALL["all.yml"]
GROUPVARS --> WEB["webservers.yml"]
HOSTVARS --> HOST1["web1.example.com.yml"]
PLAYBOOKS --> SITE["site.yml"]
PLAYBOOKS --> WEBPB["webservers.yml"]
PLAYBOOKS --> DBPB["dbservers.yml"]
style PROJECT fill:#1565C0,color:#fff
style INVENTORY fill:#2E7D32,color:#fff
style GROUPVARS fill:#6A1B9A,color:#fff
style PLAYBOOKS fill:#E65100,color:#fff- Ne stockez jamais de secrets en clair : Utilisez Ansible Vault ou un gestionnaire de secrets externe (HashiCorp Vault, AWS Secrets Manager).
- Testez vos playbooks avec Molecule, un framework de test pour les rôles Ansible.
Fenêtre de terminal pip install molecule molecule-dockermolecule init role mon_rolemolecule test
Conclusion
Les Playbooks sont au cœur de la puissance d’Ansible. Contrairement aux commandes qui permettent d’exécuter une tâche unique, les playbooks permettent d’orchestrer des configurations complexes, des déploiements d’applications et bien plus encore, de manière répétable et documentée.
C’est un outil indispensable pour l’administrateur système moderne et l’ingénieur DevOps. Il transforme des procédures manuelles sujettes aux erreurs en processus automatisés, fiables et partageables. Leur principal avantage face aux alternatives : la simplicité de démarrage (pas d’agent, YAML lisible) combinée à une puissance suffisante pour la majorité des cas. Pour le provisionnement d’infrastructure cloud, combinez Ansible avec Terraform.
Le workflow idéal en production :
- Terraform provisionne les serveurs et le réseau.
- Ansible configure les machines et déploie les applications.
- Git versionne le tout.
- CI/CD (GitLab CI, GitHub Actions) exécute les playbooks automatiquement à chaque commit.