Aller au contenu principal

Playbooks Ansible


Objectifs du chapitre

  • Comprendre la structure d'un playbook
  • Écrire des playbooks YAML
  • Utiliser les handlers et les conditions
  • Organiser des playbooks complexes

1 - Qu'est-ce qu'un playbook ?

Définition

Un playbook est un fichier YAML décrivant une série de tâches à exécuter sur des hôtes.

Structure de base

---
# site.yml - Mon premier playbook
- name: Configurer les serveurs web
hosts: webservers
become: yes

tasks:
- name: Installer nginx
apt:
name: nginx
state: present

- name: Démarrer nginx
service:
name: nginx
state: started
enabled: yes

2 - Anatomie d'un playbook

Composants

Éléments d'un play

ÉlémentDescriptionObligatoire
nameDescription du playNon (recommandé)
hostsHôtes ciblesOui
becomeEscalade privilègesNon
varsVariablesNon
tasksListe des tâchesOui
handlersTâches déclenchéesNon

Éléments d'une tâche

tasks:
- name: Description de la tâche # Obligatoire (bonne pratique)
module_name: # Module à utiliser
param1: value1 # Arguments du module
param2: value2
become: yes # Options de la tâche
when: condition # Condition
notify: handler_name # Déclencher un handler
register: result # Capturer le résultat

3 - Exemple complet

Playbook serveur web

---
# webserver.yml
- name: Configuration complète serveur web
hosts: webservers
become: yes
vars:
http_port: 80
domain: example.com

tasks:
- name: Mettre à jour le cache apt
apt:
update_cache: yes
cache_valid_time: 3600

- name: Installer les packages requis
apt:
name:
- nginx
- certbot
- python3-certbot-nginx
state: present

- name: Créer le répertoire web
file:
path: /var/www/{{ domain }}
state: directory
owner: www-data
group: www-data
mode: '0755'

- name: Copier la configuration nginx
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/{{ domain }}
notify: Reload nginx

- name: Activer le site
file:
src: /etc/nginx/sites-available/{{ domain }}
dest: /etc/nginx/sites-enabled/{{ domain }}
state: link
notify: Reload nginx

- name: S'assurer que nginx est démarré
service:
name: nginx
state: started
enabled: yes

handlers:
- name: Reload nginx
service:
name: nginx
state: reloaded

4 - Handlers

Concept

Les handlers sont des tâches déclenchées uniquement si une tâche les notifie.

Syntaxe

tasks:
- name: Copier la configuration
copy:
src: app.conf
dest: /etc/app/app.conf
notify:
- Restart app
- Clear cache

handlers:
- name: Restart app
service:
name: myapp
state: restarted

- name: Clear cache
command: /usr/local/bin/clear-cache.sh

Forcer l'exécution des handlers

tasks:
- name: Copier la configuration
copy:
src: app.conf
dest: /etc/app/app.conf
notify: Restart app

- name: Forcer l'exécution des handlers maintenant
meta: flush_handlers

- name: Vérifier que l'app fonctionne
uri:
url: http://localhost:8080/health

5 - Conditions (when)

Syntaxe de base

tasks:
- name: Installer sur Debian
apt:
name: nginx
when: ansible_os_family == "Debian"

- name: Installer sur RedHat
yum:
name: nginx
when: ansible_os_family == "RedHat"

Opérateurs

tasks:
# Égalité
- name: Si Ubuntu
debug:
msg: "C'est Ubuntu"
when: ansible_distribution == "Ubuntu"

# Comparaison
- name: Si version >= 20.04
debug:
msg: "Version récente"
when: ansible_distribution_version is version('20.04', '>=')

# ET logique
- name: Ubuntu 22.04
debug:
msg: "Ubuntu 22.04"
when:
- ansible_distribution == "Ubuntu"
- ansible_distribution_version == "22.04"

# OU logique
- name: Debian ou Ubuntu
debug:
msg: "Famille Debian"
when: ansible_distribution == "Debian" or ansible_distribution == "Ubuntu"

# Négation
- name: Pas RedHat
debug:
msg: "Pas RedHat"
when: ansible_os_family != "RedHat"

# Variable définie
- name: Si variable existe
debug:
msg: "Variable définie"
when: my_variable is defined

# Dans une liste
- name: Si dans la liste
debug:
msg: "Package supporté"
when: package_name in ['nginx', 'apache2', 'lighttpd']

Conditions avec register

tasks:
- name: Vérifier si le fichier existe
stat:
path: /etc/myapp/config.yml
register: config_file

- name: Créer le fichier si absent
copy:
content: "# Configuration par défaut"
dest: /etc/myapp/config.yml
when: not config_file.stat.exists

6 - Boucles (loop)

loop simple

tasks:
- name: Créer plusieurs utilisateurs
user:
name: "{{ item }}"
state: present
loop:
- alice
- bob
- charlie

- name: Installer plusieurs packages
apt:
name: "{{ item }}"
state: present
loop:
- nginx
- postgresql
- redis

loop avec dictionnaires

tasks:
- name: Créer utilisateurs avec détails
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
shell: "{{ item.shell | default('/bin/bash') }}"
loop:
- { name: 'alice', groups: 'developers', shell: '/bin/zsh' }
- { name: 'bob', groups: 'admins' }
- { name: 'charlie', groups: 'developers' }

loop avec index

tasks:
- name: Créer des fichiers numérotés
copy:
content: "Fichier numéro {{ my_idx + 1 }}"
dest: "/tmp/file{{ my_idx + 1 }}.txt"
loop:
- first
- second
- third
loop_control:
index_var: my_idx

7 - Variables dans les playbooks

Définir des variables

---
- name: Exemple avec variables
hosts: webservers

vars:
http_port: 80
app_name: myapp
packages:
- nginx
- php-fpm
- php-mysql

tasks:
- name: Afficher les variables
debug:
msg: "App {{ app_name }} sur port {{ http_port }}"

- name: Installer les packages
apt:
name: "{{ packages }}"
state: present

Variables depuis fichiers

---
- name: Avec fichier de variables
hosts: webservers

vars_files:
- vars/common.yml
- vars/{{ ansible_os_family }}.yml

tasks:
- name: Utiliser les variables
debug:
var: some_variable

Prompt interactif

---
- name: Avec prompt
hosts: webservers

vars_prompt:
- name: admin_password
prompt: "Mot de passe admin?"
private: yes

tasks:
- name: Créer l'admin
user:
name: admin
password: "{{ admin_password | password_hash('sha512') }}"

8 - Register et debug

Capturer les résultats

tasks:
- name: Exécuter une commande
command: cat /etc/os-release
register: os_info

- name: Afficher le résultat
debug:
var: os_info.stdout_lines

- name: Afficher si succès
debug:
msg: "Commande réussie"
when: os_info.rc == 0

Structure d'un résultat


9 - Tags

Ajouter des tags

tasks:
- name: Installer nginx
apt:
name: nginx
tags:
- packages
- nginx

- name: Configurer nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
tags:
- configuration
- nginx

- name: Démarrer nginx
service:
name: nginx
state: started
tags:
- services
- nginx

Exécuter avec tags

# Exécuter seulement les tâches nginx
ansible-playbook site.yml --tags nginx

# Exécuter seulement les packages
ansible-playbook site.yml --tags packages

# Exclure des tags
ansible-playbook site.yml --skip-tags configuration

# Lister les tags disponibles
ansible-playbook site.yml --list-tags

10 - Organisation des playbooks

Inclure d'autres playbooks

# site.yml - Playbook principal
---
- import_playbook: playbooks/webservers.yml
- import_playbook: playbooks/databases.yml
- import_playbook: playbooks/loadbalancers.yml

Inclure des tâches

# main.yml
tasks:
- name: Tâches communes
include_tasks: tasks/common.yml

- name: Tâches spécifiques OS
include_tasks: "tasks/{{ ansible_os_family }}.yml"

Résumé

Points clés
  • Les playbooks sont des fichiers YAML
  • Chaque tâche doit avoir un nom descriptif
  • Utilisez les handlers pour les actions post-changement
  • Les conditions when permettent la logique conditionnelle
  • Les tags facilitent l'exécution partielle

Exercices pratiques

  1. Créez un playbook qui installe et configure nginx
  2. Ajoutez des handlers pour recharger le service
  3. Utilisez des conditions pour gérer différents OS
  4. Organisez avec des tags et des includes

← Commandes ad-hoc | Variables et Facts →