Roles Ansible
Objectifs du chapitre
- Comprendre l'intérêt des rôles
- Créer la structure d'un rôle
- Utiliser les rôles dans les playbooks
- Partager et réutiliser les rôles
1 - Pourquoi les rôles ?
Problème sans rôles
Solution avec rôles
Avantages
| Sans rôles | Avec rôles |
|---|---|
| Code dupliqué | Code réutilisable |
| Playbook monolithique | Modules indépendants |
| Difficile à tester | Testable unitairement |
| Pas de versioning | Versionnable |
2 - Structure d'un rôle
Arborescence standard
roles/
└── nginx/
├── README.md # Documentation
├── defaults/ # Variables par défaut (priorité basse)
│ └── main.yml
├── vars/ # Variables du rôle (priorité haute)
│ └── main.yml
├── tasks/ # Tâches principales
│ └── main.yml
├── handlers/ # Handlers
│ └── main.yml
├── templates/ # Templates Jinja2
│ └── nginx.conf.j2
├── files/ # Fichiers statiques
│ └── index.html
├── meta/ # Métadonnées et dépendances
│ └── main.yml
└── tests/ # Tests du rôle
├── inventory
└── test.yml
3 - Créer un rôle
Commande ansible-galaxy
# Créer un squelette de rôle
ansible-galaxy init roles/nginx
# Structure créée
roles/nginx/
├── README.md
├── defaults/
│ └── main.yml
├── files/
├── handlers/
│ └── main.yml
├── meta/
│ └── main.yml
├── tasks/
│ └── main.yml
├── templates/
├── tests/
│ ├── inventory
│ └── test.yml
└── vars/
└── main.yml
Exemple complet : rôle nginx
defaults/main.yml - Variables par défaut
---
# defaults/main.yml
nginx_http_port: 80
nginx_https_port: 443
nginx_worker_processes: auto
nginx_worker_connections: 1024
nginx_server_names_hash_bucket_size: 64
nginx_vhosts: []
# Exemple:
# nginx_vhosts:
# - name: example.com
# root: /var/www/example.com
# port: 80
tasks/main.yml - Tâches
---
# tasks/main.yml
- name: Install nginx
apt:
name: nginx
state: present
update_cache: yes
tags: [nginx, packages]
- name: Configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
validate: nginx -t -c %s
notify: Reload nginx
tags: [nginx, configuration]
- name: Configure virtual hosts
template:
src: vhost.conf.j2
dest: "/etc/nginx/sites-available/{{ item.name }}"
loop: "{{ nginx_vhosts }}"
notify: Reload nginx
tags: [nginx, vhosts]
- name: Enable virtual hosts
file:
src: "/etc/nginx/sites-available/{{ item.name }}"
dest: "/etc/nginx/sites-enabled/{{ item.name }}"
state: link
loop: "{{ nginx_vhosts }}"
notify: Reload nginx
tags: [nginx, vhosts]
- name: Start and enable nginx
service:
name: nginx
state: started
enabled: yes
tags: [nginx, services]
handlers/main.yml - Handlers
---
# handlers/main.yml
- name: Reload nginx
service:
name: nginx
state: reloaded
- name: Restart nginx
service:
name: nginx
state: restarted
templates/nginx.conf.j2 - Template
# {{ ansible_managed }}
user www-data;
worker_processes {{ nginx_worker_processes }};
pid /run/nginx.pid;
events {
worker_connections {{ nginx_worker_connections }};
}
http {
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
server_names_hash_bucket_size {{ nginx_server_names_hash_bucket_size }};
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
meta/main.yml - Métadonnées
---
# meta/main.yml
galaxy_info:
author: DevOps Team
description: Install and configure Nginx
license: MIT
min_ansible_version: "2.10"
platforms:
- name: Ubuntu
versions:
- focal
- jammy
- name: Debian
versions:
- bullseye
- bookworm
galaxy_tags:
- nginx
- webserver
- web
dependencies: []
# dependencies:
# - role: common
# - role: firewall
4 - Utiliser un rôle
Dans un playbook
---
# site.yml
- name: Configure web servers
hosts: webservers
become: yes
roles:
- nginx
- php-fpm
- app
Avec des variables
---
- name: Configure web servers
hosts: webservers
become: yes
roles:
- role: nginx
nginx_http_port: 8080
nginx_vhosts:
- name: myapp.example.com
root: /var/www/myapp
Import vs Include
---
- name: Différentes façons d'inclure
hosts: webservers
become: yes
tasks:
# Statique - résolu au parsing
- import_role:
name: nginx
tags: [nginx]
# Dynamique - résolu à l'exécution
- include_role:
name: "{{ role_name }}"
vars:
role_name: nginx
when: install_nginx | bool
5 - Dépendances de rôles
Définir des dépendances
# roles/app/meta/main.yml
---
dependencies:
- role: common
- role: nginx
nginx_vhosts:
- name: "{{ app_domain }}"
root: "{{ app_root }}"
- role: postgresql
when: app_db_type == 'postgresql'
Ordre d'exécution
6 - Organisation des tâches
Séparer les tâches
# tasks/main.yml
---
- name: Include installation tasks
include_tasks: install.yml
tags: [install]
- name: Include configuration tasks
include_tasks: configure.yml
tags: [configure]
- name: Include OS-specific tasks
include_tasks: "{{ ansible_os_family }}.yml"
# tasks/install.yml
---
- name: Install nginx
apt:
name: nginx
state: present
# tasks/configure.yml
---
- name: Configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
# tasks/Debian.yml
---
- name: Debian-specific configuration
copy:
src: debian-default
dest: /etc/default/nginx
7 - Tests de rôles
Structure de test
roles/nginx/
└── molecule/
└── default/
├── converge.yml
├── molecule.yml
└── verify.yml
Test simple avec Molecule
# molecule/default/molecule.yml
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: instance
image: ubuntu:22.04
pre_build_image: true
provisioner:
name: ansible
verifier:
name: ansible
# molecule/default/converge.yml
---
- name: Converge
hosts: all
become: yes
roles:
- role: nginx
# molecule/default/verify.yml
---
- name: Verify
hosts: all
tasks:
- name: Check nginx is installed
command: nginx -v
changed_when: false
- name: Check nginx is running
service:
name: nginx
state: started
check_mode: yes
# Exécuter les tests
molecule test
8 - Bonnes pratiques
Structure recommandée
# defaults/main.yml - Documenter les variables
---
# nginx_http_port: Port HTTP (default: 80)
nginx_http_port: 80
# nginx_worker_processes: Nombre de workers (default: auto)
nginx_worker_processes: auto
Nommage
# ✅ Préfixer avec le nom du rôle
nginx_http_port: 80
nginx_worker_connections: 1024
# ❌ Noms génériques
http_port: 80
worker_connections: 1024
Idempotence
# ✅ Toujours idempotent
- name: Ensure nginx is installed
apt:
name: nginx
state: present
# ❌ Non idempotent
- name: Install nginx
command: apt-get install nginx
Documentation
<!-- README.md -->
# Role: nginx
Installs and configures Nginx web server.
## Requirements
- Ubuntu 20.04+ or Debian 11+
## Role Variables
| Variable | Default | Description |
|----------|---------|-------------|
| nginx_http_port | 80 | HTTP port |
| nginx_worker_processes | auto | Worker processes |
## Example Playbook
```yaml
- hosts: webservers
roles:
- role: nginx
nginx_http_port: 8080
---
## 9 - Structure de projet complète
```mermaid
graph TB
A[ansible-project/] --> B[ansible.cfg]
A --> C[inventory/]
A --> D[playbooks/]
A --> E[roles/]
A --> F[group_vars/]
E --> E1[common/]
E --> E2[nginx/]
E --> E3[postgresql/]
E --> E4[app/]
D --> D1[site.yml]
D --> D2[deploy.yml]
Playbook principal
# playbooks/site.yml
---
- name: Apply common configuration
hosts: all
become: yes
roles:
- common
- name: Configure web servers
hosts: webservers
become: yes
roles:
- nginx
- php-fpm
- name: Configure database servers
hosts: databases
become: yes
roles:
- postgresql
- name: Deploy application
hosts: webservers
become: yes
roles:
- app
Résumé
Points clés
- Les rôles permettent la réutilisation du code
- Utilisez
ansible-galaxy initpour créer un squelette - Préfixez les variables avec le nom du rôle
- Testez vos r ôles avec Molecule
- Documentez dans README.md
Exercices pratiques
- Créez un rôle "common" pour la configuration de base
- Créez un rôle "nginx" avec templates
- Ajoutez des dépendances entre rôles
- Testez votre rôle avec un playbook