RousselTMLEARNING

Automatisation

Ansible : structurer son code avec les rôles

Créer, organiser et réutiliser des rôles Ansible : arborescence, defaults, tasks, handlers, templates, dépendances, ansible-galaxy et bonnes pratiques.

1. Pourquoi des rôles ? #

Réutiliser, tester et partager.

Du playbook monolithique au rôle #

Un playbook qui grossit devient illisible. Un rôle regroupe tout ce qui concerne un composant (installation, configuration, service) dans une structure normalisée : il est réutilisable entre projets, testable indépendamment et partageable via Ansible Galaxy.

Arborescence d'un rôle Ansible
Seul tasks/main.yml est obligatoire.

Créer l'arborescence #

mkdir -p roles && cd roles
ansible-galaxy role init nginx
tree nginx
nginx/
├── README.md
├── defaults/main.yml     # variables par défaut (priorité la plus basse)
├── files/                # fichiers copiés tels quels
├── handlers/main.yml     # actions déclenchées par notify
├── meta/main.yml         # métadonnées et dépendances
├── tasks/main.yml        # point d'entrée du rôle
├── templates/            # fichiers Jinja2 (.j2)
├── tests/                # inventaire et playbook de test
└── vars/main.yml         # variables internes (priorité élevée)

2. Écrire un rôle complet : nginx #

Tasks, defaults, templates et handlers.

defaults et tasks #

# roles/nginx/defaults/main.yml
nginx_port: 80
nginx_server_name: "{{ ansible_fqdn }}"
nginx_worker_processes: auto
nginx_enable_service: true
# roles/nginx/tasks/main.yml
- name: Installer nginx
  ansible.builtin.package:
    name: nginx
    state: present

- name: Déployer la configuration du site
  ansible.builtin.template:
    src: site.conf.j2
    dest: /etc/nginx/conf.d/site.conf
    owner: root
    mode: "0644"
    validate: nginx -t -c /etc/nginx/nginx.conf
  notify: Recharger nginx

- name: Démarrer et activer nginx
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: "{{ nginx_enable_service }}" 

Template et handler #

# roles/nginx/templates/site.conf.j2
server {
    listen {{ nginx_port }};
    server_name {{ nginx_server_name }};
    root /var/www/{{ nginx_server_name }};
    access_log /var/log/nginx/{{ nginx_server_name }}.access.log;
}
# roles/nginx/handlers/main.yml
- name: Recharger nginx
  ansible.builtin.service:
    name: nginx
    state: reloaded
À savoir : Un handler ne s'exécute qu'une fois, en fin de play, et seulement si une tâche qui le notifie a réellement changé quelque chose. Forcez son exécution immédiate avec - meta: flush_handlers.

3. Utiliser un rôle #

Dans un playbook, avec ses variables.

Appeler le rôle #

# site.yml
- hosts: webservers
  become: true
  roles:
    - role: nginx
      vars:
        nginx_port: 8080
    - role: monitoring_agent
      tags: [monitoring]
ansible-playbook -i inventories/lab/hosts.ini site.yml
ansible-playbook site.yml --tags monitoring
ansible-playbook site.yml --list-tasks

Vous pouvez aussi l'appeler dynamiquement au milieu d'une liste de tâches avec include_role (exécution conditionnelle ou en boucle) ou import_role (inclusion statique) :

tasks:
  - name: Installer le serveur web
    ansible.builtin.include_role:
      name: nginx
    when: ansible_os_family == "Debian" 

Dépendances entre rôles #

# roles/wordpress/meta/main.yml
dependencies:
  - role: nginx
    vars: { nginx_port: 80 }
  - role: mariadb

4. Partager avec Ansible Galaxy et les collections #

Ne pas réinventer la roue.

Installer des rôles et collections #

ansible-galaxy role search nginx --author geerlingguy
ansible-galaxy role install geerlingguy.docker
ansible-galaxy collection install community.general ansible.posix

# Versionner les dépendances du projet
cat requirements.yml
roles:
  - name: geerlingguy.docker
    version: 7.4.1
collections:
  - name: community.general
    version: ">=9.0.0"

ansible-galaxy install -r requirements.yml

Bonnes pratiques #

  • Un rôle = une responsabilité ; nommez-le d'après le composant (nginx, postgres).
  • Préfixez toutes les variables par le nom du rôle (nginx_port) pour éviter les collisions.
  • Mettez les valeurs modifiables dans defaults/ et réservez vars/ aux constantes internes.
  • Rendez chaque tâche idempotente et testez-la avec Molecule (voir « Aller plus loin »).
Erreur Courante : Éviter d'écrire un rôle monstre qui installe, configure et supervise dix composants : il devient impossible à tester et à réutiliser.

Pour aller plus loin