
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.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Générer la structure d'un rôle avec
ansible-galaxy role init. - Écrire
tasks/main.ymlavec 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).
Prérequis
Section intitulée « Prérequis »- Avoir lu Structure standard d'un rôle.
- Lab fonctionnel avec
web1.labqui répond àansible web1.lab -m ping. - Collection
ansible.posixinstallée (ansible-galaxy collection install ansible.posix).
Étape 1, Générer la structure
Section intitulée « Étape 1, Générer la structure »À la racine du projet, créer un dossier roles/ puis générer le rôle :
mkdir -p rolesansible-galaxy role init roles/webserverSortie :
- Role roles/webserver was created successfullyArborescence 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.
Étape 2, Écrire les tâches dans tasks/main.yml
Section intitulée « Étape 2, Écrire les tâches dans tasks/main.yml »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: enabled3 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.
Étape 3, Définir les variables par défaut
Section intitulée « Étape 3, Définir les variables par défaut »defaults/main.yml contient les variables que l'utilisateur du rôle peut override. Convention : préfixer par le nom du rôle (webserver_).
---webserver_state: presentwebserver_service_state: startedwebserver_service_enabled: trueÉtape 4, Documenter le rôle (meta/main.yml)
Section intitulée « Étape 4, Documenter le rôle (meta/main.yml) »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).
Étape 5, Ajouter des handlers
Section intitulée « Étape 5, Ajouter des handlers »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.
---- name: Restart nginx ansible.builtin.systemd_service: name: nginx state: restarted
- name: Reload nginx ansible.builtin.systemd_service: name: nginx state: reloadedLes 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: webserverPas de tasks: dans le playbook, toutes les tâches viennent du rôle. Pattern recommandé : playbooks fins, rôles épais.
Étape 7, Exécuter le playbook
Section intitulée « Étape 7, Exécuter le playbook »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.
ansible-playbook playbook.ymlSortie 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=0Notez 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.
Étape 8, Vérifier l'idempotence
Section intitulée « Étape 8, Vérifier l'idempotence »Re-lancer immédiatement le playbook :
ansible-playbook playbook.ymlSortie 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.
Étape 9, Tester nginx
Section intitulée « Étape 9, Tester nginx »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.
Mettre en pratique
Section intitulée « Mettre en pratique »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.
Pièges courants
Section intitulée « Pièges courants »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ôme | Cause | Fix |
|---|---|---|
couldn't resolve module/action 'firewalld' | Collection ansible.posix non installée | ansible-galaxy collection install ansible.posix |
Cannot find role 'webserver' | Rôle pas dans roles_path | Vérifier ansible.cfg ou utiliser un path relatif explicite |
firewalld is not running | Service firewalld arrêté sur la cible | sudo systemctl enable --now firewalld puis relancer |
changed=true à chaque run | Une tâche n'est pas idempotente | Vérifier que tous les modules ont un state: ou creates: |
| Curl renvoie « Connection refused » | Port 80 pas ouvert | Vérifier firewall-cmd --list-services sur la cible |
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »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
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
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »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=0si l'état est déjà conforme. - Pattern recommandé :
playbooks/fins +roles/épais.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Handlers et meta : brancher un redémarrage de service sur un changement de configuration.
- argument_specs.yml : donner un contrat d'entrée à votre rôle plutôt qu'espérer les bonnes variables.
- Introduction au TDD avec Molecule : la suite logique une fois qu'un rôle existe, le tester automatiquement.