Aller au contenu principal

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ôlesAvec rôles
Code dupliquéCode réutilisable
Playbook monolithiqueModules indépendants
Difficile à testerTestable unitairement
Pas de versioningVersionnable

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 init pour 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

  1. Créez un rôle "common" pour la configuration de base
  2. Créez un rôle "nginx" avec templates
  3. Ajoutez des dépendances entre rôles
  4. Testez votre rôle avec un playbook

← Variables et Facts | Templates →