
Un rôle Ansible est l'équivalent d'un module Terraform ou d'un chart Helm : une brique réutilisable qui packagde tâches, variables, templates, handlers et tests autour d'un objectif unique. Vous écrivez un rôle nginx une fois, vous le réutilisez dans 5 projets, vous le maintenez à un seul endroit.
Cette page explique pourquoi un rôle est supérieur à un long playbook, quand basculer du playbook au rôle, et ce que vous gagnez réellement (avec un exemple concret de refactoring).
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Le problème que les rôles résolvent : duplication, drift, code monolithique.
- La comparaison avec les modules Terraform et les charts Helm.
- Le ROI réel d'un refactoring playbook → rôle (avant/après).
- Quand basculer : critères pratiques pour décider.
- Anti-patterns : ce qu'il ne faut PAS mettre dans un rôle.
Le problème, un long playbook qui grossit
Section intitulée « Le problème, un long playbook qui grossit »Vous démarrez un projet pour automatiser un déploiement web. Première version : 50 lignes pour installer nginx. Trois mois plus tard, votre playbook.yml ressemble à ça :
---- name: Déployer toute l'infra web hosts: webservers become: true vars: nginx_version: "1.26.1" nginx_workers: 4 nginx_port: 80 php_version: "8.3" php_modules: - mysql - mbstring - curl db_host: db1.lab db_port: 5432 # ... 30 autres variables ...
tasks: # 50 tâches nginx - name: Installer nginx ansible.builtin.dnf: name: nginx state: present - name: Configurer nginx.conf ansible.builtin.template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf # ... 48 autres tâches nginx ...
# 30 tâches php-fpm - name: Installer PHP ...
# 40 tâches application métier ...
handlers: # 10 handlers ...500 lignes, 120 tâches, 30 variables, 10 handlers, 7 templates. Ce playbook fonctionne sur votre serveur de dev. Mais il pose 5 problèmes structurels.
Problème 1, Pas réutilisable
Section intitulée « Problème 1, Pas réutilisable »Demain, nouveau projet qui a aussi besoin de nginx. Vous copiez-collez les 50 tâches nginx dans le nouveau playbook. Drift garanti : à la première mise à jour de la config nginx, les deux versions divergent silencieusement.
Problème 2, Pas testable isolément
Section intitulée « Problème 2, Pas testable isolément »Vous voulez tester que nginx démarre correctement, indépendamment de PHP et de la base. Impossible avec ce playbook : pour tester nginx, vous devez rejouer toute la stack, attendre 5 minutes, et chercher dans le log si nginx a marché.
Problème 3, Mélange des responsabilités
Section intitulée « Problème 3, Mélange des responsabilités »Une modification urgente sur PHP nécessite de comprendre tout le contexte (nginx, base, app). Risque d'erreur élevé. Le diff Git est illisible : un changement sur la version PHP touche un fichier de 500 lignes que personne ne lit en entier.
Problème 4, Variables disséminées
Section intitulée « Problème 4, Variables disséminées »Les 30 variables sont au top du playbook. Trois mois plus tard, vous ne savez plus laquelle est vraie (par défaut), laquelle est forcée, laquelle vient d'un group_vars/. Le vars: du play écrase silencieusement vos group_vars/all.yml.
Problème 5, Pas distribuable
Section intitulée « Problème 5, Pas distribuable »Votre collègue veut nginx dans son projet. Comment lui donner ? Copier-coller 50 tâches ? Lui pousser un repo ? Aucun de ces deux flux n'est satisfaisant pour un partage à grande échelle.
La solution, un rôle par responsabilité
Section intitulée « La solution, un rôle par responsabilité »Refactorer en 3 rôles :
roles/├── nginx/ ← 50 tâches + 5 templates + 10 variables├── php-fpm/ ← 30 tâches + 3 templates + 8 variables└── app/ ← 40 tâches + 4 templates + 12 variablesLe playbook devient :
---- name: Déployer toute l'infra web hosts: webservers become: true
roles: - role: nginx vars: nginx_version: "1.26.1" nginx_workers: 4 - role: php-fpm vars: php_version: "8.3" - role: app vars: db_host: db1.lab20 lignes au lieu de 500. Lisible. Modulaire. Chaque rôle est :
- Réutilisable :
roles: - nginxdans un autre projet. - Testable isolément : Molecule sur le rôle nginx sans toucher PHP ni l'app.
- Versionnable indépendamment :
nginx@1.2.0,php-fpm@2.0.1dansrequirements.yml. - Documentable par un README clair (paramètres, exemples).
- Distribuable sur Galaxy ou un Automation Hub privé.
Comparaison avec d'autres outils IaC
Section intitulée « Comparaison avec d'autres outils IaC »Les rôles Ansible occupent dans l'écosystème la même niche que :
| Outil | Unité de réutilisation | Source |
|---|---|---|
| Ansible | Rôle | Galaxy, Automation Hub, GitHub |
| Terraform | Module | Terraform Registry, Git |
| Kubernetes | Helm chart | Artifact Hub, OCI registry |
| Pulumi | Component | Pulumi Registry, NPM/PyPI |
| Salt | Formula | Salt Formulas (GitHub) |
| Chef | Cookbook | Chef Supermarket |
| Puppet | Module | Puppet Forge |
Le concept est identique partout : un dossier structuré avec des conventions, une API d'entrée (variables/inputs), et un comportement encapsulé. Si vous avez utilisé un module Terraform, vous comprenez déjà 80 % d'un rôle Ansible, la syntaxe diffère mais la philosophie est identique.
ROI réel du refactoring, chiffres
Section intitulée « ROI réel du refactoring, chiffres »Voici le résultat concret d'un refactoring de production sur 5 projets utilisant nginx :
| Métrique | Avant (playbooks) | Après (rôle nginx + 5 projets) |
|---|---|---|
| Lignes de code totales (nginx) | 5 × 50 = 250 | 1 × 50 + 5 × 5 = 75 |
| Temps de mise à jour de la config nginx | 5 fichiers à éditer | 1 fichier à éditer |
| Risque de drift | Élevé | Nul (source unique) |
| Testabilité | 0 | Molecule isolé |
| Onboarding nouveau dev | Lit 500 lignes | Lit README.md du rôle |
Gain factuel : 60 % de code en moins, 100 % de drift en moins, testabilité de 0 à 100 %.
Quand basculer du playbook au rôle ?
Section intitulée « Quand basculer du playbook au rôle ? »Critères de décision simples :
- Le code va être réutilisé ailleurs (autre projet, autre environnement). → Rôle dès le départ.
- Le playbook dépasse 100 lignes et grossit. → Refactor en plusieurs rôles.
- Plusieurs équipes doivent collaborer. → Rôles (ownership clair).
- Vous voulez tester avec Molecule. → Rôle (Molecule fonctionne sur les rôles, pas les playbooks).
- Le code touche un service identifiable (nginx, postgres, vault). → Rôle par service.
À l'inverse, ne créez pas de rôle pour :
- Un playbook one-shot de migration unique (purge + import).
- Une glue très spécifique à un projet (reportez dans
tasks/du playbook). - Du code expérimental que vous n'êtes pas sûr de garder.
Anti-patterns à éviter
Section intitulée « Anti-patterns à éviter »Anti-pattern 1, Le rôle « base »/« common »
Section intitulée « Anti-pattern 1, Le rôle « base »/« common » »Tentation : un rôle common qui contient « tout ce que toutes les machines doivent avoir » (sshd, ntp, monitoring, users...). Problème : devient un fourre-tout ingérable. Préférer un rôle par responsabilité : sshd, ntp, monitoring, users. Plus long à écrire, infiniment plus maintenable.
Anti-pattern 2, Les rôles imbriqués profondément
Section intitulée « Anti-pattern 2, Les rôles imbriqués profondément »Un rôle webapp qui dépend du rôle nginx qui dépend du rôle tls qui dépend du rôle dns... 4 niveaux de profondeur. Debug = horreur. Préférer 2 niveaux maximum ou utiliser un playbook orchestrateur qui appelle les rôles à plat.
Anti-pattern 3, Variables hardcodées dans les tasks
Section intitulée « Anti-pattern 3, Variables hardcodées dans les tasks »# ❌ Mauvais- name: Configurer nginx ansible.builtin.template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf vars: nginx_version: "1.26.1" # ← hardcodé dans la taskLe rôle n'est plus paramétrable. Préférer defaults/main.yml :
# ✅ Bonnginx_version: "1.26.1"
# tasks/main.yml- name: Configurer nginx ansible.builtin.template: src: nginx.conf.j2 dest: /etc/nginx/nginx.confAnti-pattern 4, Tâches non idempotentes
Section intitulée « Anti-pattern 4, Tâches non idempotentes »# ❌ Mauvais- name: Vider le cache ansible.builtin.command: rm -rf /var/cache/nginx/*À chaque exécution, changed=true. Préférer un module dédié avec idempotence :
# ✅ Bon- name: Vider le cache ansible.builtin.file: path: /var/cache/nginx state: absent- name: Recréer le cache ansible.builtin.file: path: /var/cache/nginx state: directory mode: "0755"Anti-pattern 5, Pas de README ni d'argument_specs.yml
Section intitulée « Anti-pattern 5, Pas de README ni d'argument_specs.yml »Un rôle sans documentation est inutilisable par autrui, voire par vous-même 6 mois plus tard. Mandatory : README.md + meta/argument_specs.yml (validation des variables).
À retenir
Section intitulée « À retenir »- Un rôle = brique réutilisable testable distribuable. Équivalent d'un module Terraform.
- Refactor playbook → rôle dès que le code dépasse 100 lignes ou doit être réutilisé.
- ROI mesurable : 60 % de code en moins, 100 % de drift en moins, testabilité native.
- Un rôle = une responsabilité. Pas de rôle « base »/« common » fourre-tout.
- Anti-patterns : variables hardcodées, tâches non-idempotentes, pas de README.
- Imbrication max 2 niveaux, préférer un playbook orchestrateur.