Aller au contenu
English
English
Infrastructure as Code medium

Créer son premier rôle Ansible : ansible-galaxy role init pas à pas

80 min de lecture

Logo Ansible

Ce guide vous fait écrire votre premier rôle Ansible from scratch avec le rôle fil rouge webserver qui sera enrichi au fil des prochains guides. Vous générez la structure avec ansible-galaxy role init, vous écrivez les tâches dans tasks/main.yml, vous appelez le rôle depuis un playbook, et vous validez avec un test pytest+testinfra.

À la fin, vous aurez un rôle fonctionnel et idempotent qui installe nginx, le démarre, et ouvre le firewall, tout ça en respectant la structure conventionnelle des rôles Ansible.

  • Générer la structure d'un rôle avec ansible-galaxy role init.
  • Écrire tasks/main.yml avec 3 tâches FQCN idempotentes (dnf, systemd, firewalld).
  • Définir des variables par défaut dans defaults/main.yml.
  • Documenter le rôle via meta/main.yml + README.md.
  • Appeler le rôle depuis un playbook avec roles:.
  • Valider l'idempotence en relançant le playbook (résultat : changed=0).
  • Avoir lu Structure standard d'un rôle.
  • Lab fonctionnel avec web1.lab qui répond à ansible web1.lab -m ping.
  • Collection ansible.posix installée (ansible-galaxy collection install ansible.posix).

À la racine du projet, créer un dossier roles/ puis générer le rôle :

Fenêtre de terminal
mkdir -p roles
ansible-galaxy role init roles/webserver

Sortie :

- Role roles/webserver was created successfully

Arborescence générée :

  • Répertoireroles/
    • Répertoirewebserver/
      • Répertoiredefaults/
        • main.yml
      • Répertoirefiles/
        • …
      • Répertoirehandlers/
        • main.yml
      • Répertoiremeta/
        • main.yml
      • Répertoiretasks/
        • main.yml
      • Répertoiretemplates/
        • …
      • Répertoiretests/
        • …
      • Répertoirevars/
        • main.yml
      • README.md

8 dossiers + 2 fichiers racine. Les fichiers main.yml sont créés avec un squelette commenté, à vous de les remplir.

Trois tâches simples : installer nginx, démarrer le service, ouvrir le firewall.

---
# tasks/main.yml : rôle webserver
- name: Installer nginx
ansible.builtin.dnf:
name: nginx
state: present
- name: Démarrer et activer nginx
ansible.builtin.systemd_service:
name: nginx
state: started
enabled: true
- name: Ouvrir le service HTTP dans firewalld
ansible.posix.firewalld:
service: http
permanent: true
immediate: true
state: enabled

3 modules, 3 FQCN distincts : ansible.builtin.dnf, ansible.builtin.systemd_service, ansible.posix.firewalld. Chacun est idempotent, re-exécuter le rôle ne change rien si l'état est déjà conforme.

defaults/main.yml contient les variables que l'utilisateur du rôle peut override. Convention : préfixer par le nom du rôle (webserver_).

defaults/main.yml
---
webserver_state: present
webserver_service_state: started
webserver_service_enabled: true

Le fichier meta/main.yml est la carte d'identité du rôle pour Galaxy.

Rien de ce fichier n'est exécuté : il décrit le rôle pour qui va l'installer. La licence et l'auteur comptent pour la publication, les plateformes disent sur quels systèmes le rôle a été éprouvé, et les étiquettes le rendent trouvable dans un catalogue. Un seul champ agit à l'exécution, dependencies:, qui fait charger d'autres rôles avant celui-ci.

---
galaxy_info:
author: Stéphane Robert
namespace: stephrobert
role_name: webserver
description: Installer et configurer nginx
license: MIT
min_ansible_version: "2.16"
platforms:
- name: EL
versions:
- "9"
- "10"
galaxy_tags:
- nginx
- webserver
dependencies: []

Champs essentiels :

  • role_name + namespace : identifiant Galaxy (stephrobert.webserver).
  • min_ansible_version : version minimum d'Ansible.
  • platforms : OS supportés, Galaxy filtre les recherches selon ces tags.
  • dependencies : autres rôles à pré-installer (vide ici).

handlers/main.yml contient les actions réactives déclenchées par notify:.

Un handler ne s'exécute jamais de lui-même : il attend qu'une tâche se termine en changed et le nomme dans son notify:. Le gain est double sur un rôle qui écrit plusieurs fichiers de configuration : le service n'est rechargé qu'une fois, en fin de section, et pas du tout si rien n'a bougé. C'est ce qui permet à un rôle de rester idempotent tout en réagissant aux changements réels.

handlers/main.yml
---
- name: Restart nginx
ansible.builtin.systemd_service:
name: nginx
state: restarted
- name: Reload nginx
ansible.builtin.systemd_service:
name: nginx
state: reloaded

Les handlers ne s'exécutent pas tout seuls, il faut une tâche qui les notifie via notify: "Restart nginx". C'est le sujet du guide handlers-meta.

Étape 6, Écrire le playbook qui consomme le rôle

Section intitulée « Étape 6, Écrire le playbook qui consomme le rôle »

À la racine du projet (au-dessus de roles/), créer playbook.yml :

---
- name: Déployer le rôle webserver
hosts: web1.lab
become: true
roles:
- role: webserver

Pas de tasks: dans le playbook, toutes les tâches viennent du rôle. Pattern recommandé : playbooks fins, rôles épais.

Le playbook se lance sans option particulière : l'inventaire et le compte de connexion viennent de la configuration du projet, et le rôle a déjà toutes ses valeurs par défaut. La sortie mérite d'être lue en entier la première fois, car elle montre ce qu'Ansible fait vraiment, une collecte des faits, puis les trois tâches du rôle dans l'ordre où elles sont écrites.

Fenêtre de terminal
ansible-playbook playbook.yml

Sortie attendue :

PLAY [Déployer le rôle webserver] *********************************
TASK [Gathering Facts] *****************************************
ok: [web1.lab]
TASK [webserver : Installer nginx] *****************************
changed: [web1.lab]
TASK [webserver : Démarrer et activer nginx] *******************
changed: [web1.lab]
TASK [webserver : Ouvrir le service HTTP dans firewalld] *******
changed: [web1.lab]
PLAY RECAP *****************************************************
web1.lab : ok=4 changed=3 unreachable=0 failed=0

Notez le préfixe webserver : sur chaque tâche, Ansible identifie clairement le rôle exécutant. Très utile pour debugger un play multi-rôles.

Re-lancer immédiatement le playbook :

Fenêtre de terminal
ansible-playbook playbook.yml

Sortie attendue : changed=0. Tous les modules sont idempotents, l'état désiré est déjà atteint, rien à faire. C'est la propriété fondamentale d'un bon rôle Ansible : convergence vers un état, pas exécution aveugle.

Fenêtre de terminal
curl http://web1.lab/

Vous devriez voir la page d'accueil par défaut de nginx (« Welcome to nginx »).

Ce dernier contrôle vaut d'être fait depuis le poste de contrôle, et non depuis la machine elle-même : il prouve à la fois que le service écoute, que le pare-feu laisse passer le port 80 et que le réseau du lab route correctement. Un test lancé en local sur la machine réussirait même avec un pare-feu fermé, et laisserait passer la seule erreur que ce rôle peut réellement commettre.

Lire la structure d'un rôle ne suffit pas à la retenir, il faut l'avoir générée soi-même. Le lab repart du rôle webserver de cette page, puis vous demande d'en produire un second avec ansible-galaxy role init pour servir Apache sur db1.lab. Les tests inspectent l'état réel du managed node, paquet installé, service actif et port ouvert, avant d'exiger un second passage à changed=0.

Les deux premières lignes bloquent le rôle avant sa première tâche, collection absente ou rôle introuvable dans le chemin de recherche. Les trois suivantes le laissent tourner en produisant un résultat incomplet : un pare-feu arrêté, une tâche non idempotente qui rapporte un changement à chaque passage, ou un port resté fermé malgré la tâche prévue pour l'ouvrir.

SymptômeCauseFix
couldn't resolve module/action 'firewalld'Collection ansible.posix non installéeansible-galaxy collection install ansible.posix
Cannot find role 'webserver'Rôle pas dans roles_pathVérifier ansible.cfg ou utiliser un path relatif explicite
firewalld is not runningService firewalld arrêté sur la ciblesudo systemctl enable --now firewalld puis relancer
changed=true à chaque runUne tâche n'est pas idempotenteVérifier que tous les modules ont un state: ou creates:
Curl renvoie « Connection refused »Port 80 pas ouvertVérifier firewall-cmd --list-services sur la cible

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  • ansible-galaxy role init <nom> = générer la structure standard automatiquement.
  • tasks/main.yml = point d'entrée, exécuté quand le rôle est appelé.
  • FQCN partout : ansible.builtin.dnf, ansible.posix.firewalld. Mandatory en 2026.
  • Préfixer les variables avec le nom du rôle (webserver_state).
  • meta/main.yml = carte d'identité Galaxy. dependencies: = autres rôles requis.
  • Idempotence : re-jouer le playbook = changed=0 si l'état est déjà conforme.
  • Pattern recommandé : playbooks/ fins + roles/ épais.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens ce site gratuitement, sans publicité, sans profilage et sans compte à créer. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn