Skip to main content

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

ElementDescriptionRequired
nameDescription of the playNo (recommended)
hostsTarget hostsYes
becomePrivilege escalationNo
varsVariablesNo
tasksList of tasksYes
handlersTriggered tasksNo

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
  • when conditions enable conditional logic
  • Tags make partial execution easier

Practical exercises

  1. Create a playbook that installs and configures nginx
  2. Add handlers to reload the service
  3. Use conditions to handle different OSes
  4. Organize with tags and includes

← Ad-hoc commands | Variables and Facts →