Tester vos rôles Ansible avec Molécule + GitHub Actions (CI Automatisée)
Introduction
Dans un environnement DevOps, chaque modification de code doit pouvoir être testée rapidement et de manière fiable. Avec Ansible, le risque est simple : un rôle mal testé peut faire tomber une partie ou la totalité d’une infrastructure.
Molecule permet déjà de tester vos rôles localement. Mais en l’associant à GitHub Actions, vous pouvez exécuter ces tests automatiquement à chaque commit ou pull request. Résultat : vous atteignez en moyenne 80 à 90 % de couverture de scénarios critiques et vous pouvez détecter plus de 85 % des erreurs potentielles avant même qu’elles n’arrivent en production. Plus de confiance, moins de mauvaises surprises.
Si vous débutez avec Ansible, notre cours Ansible vous aide à poser des bases solides. Pour aller plus loin (tests role avec molecule, CI/CD, retours d’expérience), découvrez Ansible Expert.
Durée de mise en place : 30 à 45 min
Rappel : Molecule en quelques mots
Molecule est un framework open-source qui aide à tester des rôles Ansible dans des environnements isolés, souvent via Docker. Il suit un scénario simple :
- Créer l’environnement de test. ;
- Appliquer le rôle Ansible. ;
- Vérifier le résultat avec Testinfra ou Ansible.
- Nettoyer l’environnement.
Résultat : des rôles plus fiables, moins de surprises, et une base saine pour l’intégration continue.
Pourquoi utiliser GitHub Actions avec Molecule ?
Dans de nombreuses équipes, les rôles Ansible évoluent vite… et les régressions se voient trop tard. Molecule apporte un filet de sécurité : un environnement éphémère (Docker), un playbook “converge”, des vérifications, et un nettoyage propre. Adossé à GitHub Actions, chaque modification est testée automatiquement, et sur plusieurs distributions Linux pour éviter les surprises.
- Automatisation totale : plus besoin de lancer les tests à la main.
- Détection rapide : si un rôle casse, vous le savez immédiatement.
- Qualité constante : chaque commit est validé avant d’être fusionné.
- Travail d’équipe facilité : tout le monde voit l’état des tests dans GitHub.
Mise en place locale (exemple avec le rôle ansible-role-traefik)
Qu’est-ce que Traefik ?
Traefik est un reverse-proxy et load balancer open source (écrit en Go) pensé pour les environnements cloud-native (Docker, Kubernetes, Consul, etc.). Il découvre automatiquement les services, expose des routes HTTP(S) dynamiques via des règles, gère TLS/Let’s Encrypt, HTTP/2/3, des middlewares (auth, redirections, rate-limit…), l’observabilité (logs, metrics), et propose un dashboard/API.
En résumé: C’est une façon simple et moderne de publier et router des applications conteneurisées.
Molecule et GitHub Actions, un duo gagnant pour Ansible
Vue d’ensemble (système & architecture)
- Local : hôte Ubuntu 22.04 LTS, Docker Engine, Python 3 (venv), outils Ansible/Molecule/Testinfra.
- CI : runner GitHub Actions ubuntu-latest, workflow avec matrix (Ubuntu, Debian) ; chaque job installe la toolchain et lance molecule test.
- Cycle Molecule : create → converge → verify → destroy
Cas d’usage : installation de Traefik, démarrage du service systemd, vérification que l’API et le dashboard
Prérequis système (Ubuntu 22.04)
Ressources conseillées (dev local) : 2 vCPU, 4–8 Go RAM, 3–6 Go de disque libre, accès Internet.
Paquets :
sudo apt update
sudo apt install -y python3 python3-pip python3-venv python3-dev build-essential libffi-dev libssl-dev
sudo apt install -y python-is-python3 # optionnel (alias 'python' → python3)
sudo apt install -y docker.io
sudo usermod -aG docker $USER
newgrp docker
Dépôt cible & structure Molecule
Créez (ou utilisez) un dépôt de rôle Ansible — ici le rôle https://github.com/simoncaron/ansible-role-traefik sert de support pour intégrer Molecule (l’objectif est de tester ce role).
Forkez et cloner le repo: https://github.com/simoncaron/ansible-role-traefik
cd ansible-role-traefik /
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip setuptools wheel
# Pile outils (driver docker via plugins)
pip install "molecule" "molecule-plugins[docker]" ansible ansible-lint testinfra docker
Ajouter un scénario Molecule
Si le dépôt ne contient pas encore de scénario comme ici :
Tapez:
molecule init scenario default --driver-name docker
Après l’initialisation le dossier molécule va se creer dans le repos du rôle:
Toujours
dans le repertoire molecule/default/ rajouter les fichiers requirements.yml et verify.yml pour avoir ceci:
molecule/default/
├── converge.yml
├── molecule.yml
├── requirements.yml
└── verify.yml
Fichier : molecule/default/molecule.yml
Remplace le contenu /default/molecule.yml par :
---
driver:
name: docker
platforms:
- name: instance
image: ${MOLECULE_IMAGE:-geerlingguy/docker-ubuntu2204-ansible}
pre_build_image: true
privileged: true
command: /sbin/init
cgroupns_mode: host
user: root
environment:
HOME: /root
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
tmpfs:
- /run
- /tmp:rw,mode=1777 # <— essentiel : /tmp en écriture avec bons perms
# Optionnel: pour voir le dashboard depuis ton host pendant les tests locaux
published_ports:
- "8080:8080" # http://localhost:8080/dashboard/
- "80:80"
provisioner:
name: ansible
config_options:
defaults:
host_key_checking: false
remote_tmp: /tmp/.ansible/tmp
inventory:
host_vars:
instance:
ansible_connection: docker
ansible_user: root
ansible_python_interpreter: /usr/bin/python3
playbooks:
converge: converge.yml
verify: verify.yml
dependency:
name: galaxy
options:
role-file: requirements.yml
roles-path: "${MOLECULE_EPHEMERAL_DIRECTORY}/roles"
force: true
scenario:
test_sequence:
- dependency
- cleanup
- destroy
- syntax
- create
- prepare
- converge
- verify
- cleanup
- destroy
Fichier : molecule/default/converge.yml
Ton playbook télécharge le binaire Traefik sur le contrôleur, l’extrait en local, applique le rôle local (chemin projet), puis démarre le service. Enfin, il vérifie l’API /api/rawdata et le dashboard /dashboard/.
- name: Converge (Traefik dashboard insecure)
hosts: all
become: true
gather_facts: true
pre_tasks:
# 1) Télécharger l’archive sur le CONTROLEUR au chemin attendu par le rôle
- name: Pre-download Traefik archive on controller
ansible.builtin.get_url:
url: "https://github.com/traefik/traefik/releases/download/v{{ traefik_version }}/traefik_v{{ traefik_version }}_linux_amd64.tar.gz"
dest: "/tmp/traefik-{{ traefik_version }}.linux-amd64.tar.gz"
mode: "0644"
delegate_to: localhost
run_once: true
become: false
# 2) Décompresser en local vers /tmp pour obtenir /tmp/traefik
- name: Unarchive traefik locally to /tmp
ansible.builtin.unarchive:
src: "/tmp/traefik-{{ traefik_version }}.linux-amd64.tar.gz"
dest: "/tmp"
remote_src: false
creates: "/tmp/traefik"
delegate_to: localhost
run_once: true
become: false
# 3) S’assurer que le binaire est exécutable
- name: Ensure /tmp/traefik is executable (controller)
ansible.builtin.file:
path: "/tmp/traefik"
mode: "0755"
state: file
delegate_to: localhost
run_once: true
become: false
roles:
# Appel du rôle local par chemin absolu pour éviter tout souci de FQCN
- role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}"
vars:
traefik_version: "2.6.1"
traefik_config:
api:
insecure: true
dashboard: true
entryPoints:
traefik:
address: ":8080"
http:
address: ":80"
handlers:
- name: bounce traefik
listen:
- restart traefik
- reload traefik
ansible.builtin.systemd:
name: traefik
state: restarted # 'restarted' marche même si le unit ne supporte pas 'reload'
daemon_reload: true
become: true
# Pas de handlers requis côté rôle -> on le (re)démarre explicitement ici
post_tasks:
- name: Reload systemd units
ansible.builtin.systemd:
daemon_reload: true
- name: Enable + start Traefik
ansible.builtin.systemd:
name: traefik
state: started
enabled: true
- name: Wait for Traefik API (8080)
ansible.builtin.wait_for:
host: 127.0.0.1
port: 8080
timeout: 60
- name: Check Traefik API returns JSON
ansible.builtin.uri:
url: http://127.0.0.1:8080/api/rawdata
method: GET
status_code: 200
return_content: true
register: traefik_api
retries: 5
delay: 2
until: traefik_api.status == 200
- name: Check dashboard HTML is served
ansible.builtin.uri:
url: http://127.0.0.1:8080/dashboard/
method: GET
status_code: 200
return_content: true
register: traefik_dash
- name: Assert dashboard content looks OK
ansible.builtin.assert:
that:
- "'Traefik' in traefik_dash.content"
fail_msg: "Le dashboard ne semble pas servi correctement."
Le playbook de vérification confirme que le service écoute sur :8080 puis exige un HTTP 200 sur /dashboard/.
- name: Verify (Traefik dashboard)
hosts: all
become: true
gather_facts: false
tasks:
- name: Attend que Traefik écoute sur 8080
ansible.builtin.wait_for:
host: 127.0.0.1
port: 8080
timeout: 120
state: started
- name: Vérifie que /dashboard/ répond 200
ansible.builtin.uri:
url: http://127.0.0.1:8080/dashboard/
follow_redirects: all
return_content: false
status_code: 200
Fichier : molecule/default/requirements.yml
---
roles:
- name: simoncaron.traefik
src: https://github.com/Aurelie-Kamgang/ansible-role-traefik.git
Exécution locale (Ubuntu 22.04)
- Lint et meta Galaxy propres
Dans meta/main.yml (utile pour ansible-lint) :
---
galaxy_info:
namespace: simoncaron
role_name: traefik
author: Simon Caron
description: Installing and configure Traefik Webserver
license: "MIT"
min_ansible_version: "2.5"
platforms:
- name: Ubuntu
versions:
- bionic
- focal
- groovy
- hirsute
galaxy_tags:
- system
- network
- linux
- monitoring
- traefik
dependencies: []
-
- Exécuter Molecule en local
# Création de l’environnement de test (Docker)
molecule create
- Après la création on a l’instance qui est disponible
# Application du rôle (convergence)
Molecule converge
- #Visualisation de l’application apres le converge
# Arrête et supprime le conteneur + ressources associées
molecule destroy
# test complet (par défaut sur Ubuntu 22.04)
molecule test orchestre automatiquement la séquence complète (dependency → cleanup/destroy → syntax → create → prepare → converge → verify → cleanup → destroy) telle que définie dans ton scenario.test_sequence.
- C’est la commande la plus utilisée en automatisation (GitHub Actions, GitLab CI, Jenkins…) car elle porte le pipeline de A à Z.
Intégration CI : GitHub Actions en matrix multi-OS
Créer .github/workflows/molecule-matrix.yml à la racine du repo :
name: Molecule Multi-OS Test
name: Molecule
on:
push:
branches: [ master, main ]
pull_request:
jobs:
molecule:
name: Molecule (${{ matrix.label }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- label: ubuntu2204
image: geerlingguy/docker-ubuntu2204-ansible
- label: debian12
image: geerlingguy/docker-debian12-ansible
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10" # pas de cache pip pour éviter l’erreur de fichier manquant
- name: Install Molecule toolchain
run: |
python -m pip install --upgrade pip
pip install molecule "molecule-plugins[docker]" ansible docker
- name: Docker info (debug)
run: docker info
- name: Run Molecule tests
env:
MOLECULE_IMAGE: ${{ matrix.image }}
run: molecule test
| Distribution | Image Docker (MOLECULE_IMAGE) |
| Ubuntu 22.04 | geerlingguy/docker-ubuntu2204-ansible |
| Debian 12 | geerlingguy/docker-debian12-ansible |
Après push/PR : Deux jobs parallèles, un par distribution.
Sécurité : ne laissez pas le dashboard en « insecure »
Dans ce tuto, api.insecure: true simplifie les tests. N’exposez jamais cela en production.
En prod, activez TLS (certresolver), auth, ou restreignez l’accès (middleware + IPAllowList, etc.).
FAQ
Pourquoi télécharger le binaire côté contrôleur ?
Pour éviter des restrictions réseau dans le conteneur et fiabiliser la répétabilité du test.
Puis-je ajouter des tests Testinfra ?
Oui — en complément de verify.yml : vérifiez le binaire, les sockets, l’unité systemd, la présence des fichiers de config/règles.
Conclusion
Ce tutoriel a montré, pas à pas, comment industrialiser la validation d’un rôle Ansible avec Molecule (Docker) et GitHub Actions, en utilisant Traefik comme exemple.
Ce qui est vérifié :
- Installation de Traefik, service systemd opérationnel et dashboard servi ;
- Fin voulue confirmée : binaire présent/exécutable, service enabled/running, :8080 à l’écoute, /dashboard/ → HTTP 200 (en local et en CI) ;
- Échecs explicites en cas de souci (timeout sur :8080, statut ≠ 200, service en échec) pour un diagnostic immédiat.
Avec Molecule + Docker, tu valides localement l’installation, le service et le serving du dashboard.
Avec GitHub Actions, ces validations s’exécutent automatiquement à chaque commit/PR sur plusieurs distributions.
En pratique, molecule test orchestre toute la séquence
(dependency → cleanup/destroy → syntax → create → prepare → converge → verify → cleanup → destroy)
et c’est la commande de référence — surtout en automatisation (CI/CD).
Résultat : une chaîne de confiance de bout en bout, des revues plus rapides et des déploiements plus sûrs — un patron de test que tu peux appliquer à n’importe quel rôle Ansible, bien au-delà de Traefik.
👉 Dépôt associé : https://github.com/Aurelie-Kamgang/ansible-role-traefik.git
Tags et Catégories
Tags : #Ansible #Semaphore #Automatisation #DevOps
Catégorie : Automatisation, Ansible
Aurelie Blondel Nguedajang Kamgang
Ingénieur DevOps
blondelle aurelie nguedjang kamgang | LinkedIn
