Ansible Playbooks
Chapter objectives
- Understand the structure of a playbook
- Write YAML playbooks
- Use handlers and conditions
- Organize complex playbooks
1 - What is a playbook?
Definition
A playbook is a YAML file describing a series of tasks to run on hosts.
Basic structure
---
# 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 - Anatomy of a playbook
Components
Elements of a play
| Element | Description | Required |
|---|---|---|
name | Description of the play | No (recommended) |
hosts | Target hosts | Yes |
become | Privilege escalation | No |
vars | Variables | No |
tasks | List of tasks | Yes |
handlers | Triggered tasks | No |
Elements of a task
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 - Complete example
Web server playbook
---
# 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
Handlers are tasks triggered only if a task notifies them.
Syntax
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
Force handler execution
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)
Basic syntax
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"
Operators
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 with 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 - Loops (loop)
Simple loop
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 with dictionaries
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 with 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 in playbooks
Define 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 from files
---
- 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
Interactive prompt
---
- 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 and debug
Capture results
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 of a result
9 - Tags
Add 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
Run with 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 - Organizing playbooks
Include other playbooks
# site.yml - Playbook principal
---
- import_playbook: playbooks/webservers.yml
- import_playbook: playbooks/databases.yml
- import_playbook: playbooks/loadbalancers.yml
Include tasks
# 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"
Summary
Key points
- Playbooks are YAML files
- Each task should have a descriptive name
- Use handlers for post-change actions
whenconditions enable conditional logic- Tags make partial execution easier
Practical exercises
- Create a playbook that installs and configures nginx
- Add handlers to reload the service
- Use conditions to handle different OSes
- Organize with tags and includes