Devops
Difficulte: Advanced
15 min de lecture

Ansible Avancé : Roles, Collections, AWX et pipelines CI/CD

Guide complet Ansible avancé : roles best practice, collections Galaxy, inventaires dynamiques AWS/GCP, AWX/Automation Controller, Molecule multi-distro et pipelines CI/CD GitHub Actions + GitLab CI.

Retour aux tutoriels
Prérequis
Ce guide suppose une bonne connaissance d'Ansible (playbooks, inventaires, modules). Si vous débutez, commencez par le guide d'introduction Ansible. Pour ce tutoriel : Ansible Core 2.15+, Python 3.10+, Docker installé localement.

Pourquoi Ansible basique ne suffit pas à grande échelle

Ansible est séduisant dans sa forme la plus simple : un fichier hosts, un playbook YAML, et le tour est joué. Cette simplicité cache cependant des limitations structurelles qui deviennent douloureuses à mesure que l'infrastructure grandit.

Les symptômes sont toujours identiques. Des playbooks de 1500 lignes impossibles à maintenir. Des variables copiées-collées entre dix projets. Impossible de savoir quelle version d'un rôle est déployée en production. Aucun moyen de tester un changement avant de le pousser en prod. Des secrets en clair dans le dépôt git. Et zéro visibilité sur qui a lancé quoi et quand.

Ce guide couvre les solutions à chacun de ces problèmes :

  • Roles avancés : structure professionnelle, variables, dépendances, tags
  • Collections : packaging, versioning, Galaxy vs Automation Hub
  • Inventaires dynamiques : AWS EC2, GCP, groupes construits
  • AWX : interface web, RBAC, workflows graphiques, schedules
  • CI/CD : lint, test Molecule, déploiement automatisé
  • Sécurité : Vault avancé, secrets CI/CD, no_log

1. Roles avancés

Structure best practice d'un rôle

Un rôle bien structuré est un composant autonome, testable et réutilisable. La commande ansible-galaxy role init crée le squelette standard, que vous pouvez enrichir selon vos besoins.

# Créer un role avec la structure complète
ansible-galaxy role init mon_role

# Structure générée
mon_role/
├── README.md              # Documentation obligatoire
├── meta/
│   └── main.yml           # Métadonnées et dépendances
├── defaults/
│   └── main.yml           # Variables par défaut (basse priorité)
├── vars/
│   └── main.yml           # Variables internes (haute priorité)
├── tasks/
│   ├── main.yml           # Point d'entrée des tâches
│   ├── install.yml        # Tâches d'installation
│   ├── configure.yml      # Tâches de configuration
│   └── debian.yml         # Tâches spécifiques Debian
├── handlers/
│   └── main.yml           # Handlers (restart service, reload config)
├── templates/
│   └── nginx.conf.j2      # Templates Jinja2
├── files/
│   └── logrotate.conf     # Fichiers statiques
├── tests/
│   ├── inventory          # Inventaire de test minimal
│   └── test.yml           # Playbook de test basique
└── molecule/              # Tests Molecule (voir section 7)
    └── default/

defaults/main.yml vs vars/main.yml

La distinction entre ces deux répertoires est fondamentale et souvent mal comprise. Elle détermine qui peut surcharger quelle variable et à quel niveau.

# defaults/main.yml — Variables configurables par l'utilisateur
# Priorité la plus BASSE → facilement surchargées
nginx_port: 80
nginx_ssl_port: 443
nginx_worker_processes: auto
nginx_user: www-data
nginx_log_path: /var/log/nginx
nginx_sites_available: /etc/nginx/sites-available
nginx_sites_enabled: /etc/nginx/sites-enabled

# Ces valeurs peuvent être surchargées depuis :
# - group_vars/, host_vars/
# - -e "nginx_port=8080" en ligne de commande
# - Le playbook appelant
# vars/main.yml — Constantes internes du role
# Priorité HAUTE → difficiles à surcharger (usage avancé uniquement)
_nginx_packages:
  Debian:
    - nginx
    - nginx-extras
  RedHat:
    - nginx
    - nginx-mod-http-geoip2

_nginx_service_name: nginx
_nginx_config_dir: /etc/nginx
_nginx_pid_file: /run/nginx.pid

# Règle : jamais de secrets ici, uniquement des constantes structurelles
# tasks/main.yml — Point d'entrée avec include conditionnel
---
- name: Inclure les variables selon l'OS
  ansible.builtin.include_vars: "{{ ansible_os_family }}.yml"
  tags: always

- name: Installation Nginx
  ansible.builtin.include_tasks: install.yml
  tags: [nginx, install]

- name: Configuration Nginx
  ansible.builtin.include_tasks: configure.yml
  tags: [nginx, configure]

- name: Activation et démarrage du service
  ansible.builtin.service:
    name: "{{ _nginx_service_name }}"
    state: started
    enabled: true
  tags: [nginx, service]

meta/main.yml : dépendances et métadonnées

Le fichier meta/main.yml est crucial pour deux raisons : il documente le rôle pour Galaxy et définit ses dépendances qui seront résolues automatiquement.

# meta/main.yml
galaxy_info:
  author: votre_pseudo
  description: Role Nginx production-ready avec SSL et hardening
  company: Mon Entreprise
  license: MIT
  min_ansible_version: "2.15"
  platforms:
    - name: Ubuntu
      versions:
        - "22.04"
        - "24.04"
    - name: Debian
      versions:
        - "12"
    - name: EL
      versions:
        - "9"
  galaxy_tags:
    - nginx
    - web
    - proxy
    - ssl

# Dépendances : ces roles seront exécutés AVANT celui-ci
dependencies:
  - role: geerlingguy.certbot
    vars:
      certbot_email: admin@example.com
    when: nginx_ssl_enabled | bool
  - role: common.firewall
    vars:
      firewall_allowed_tcp_ports:
        - "{{ nginx_port }}"
        - "{{ nginx_ssl_port }}"

handlers/main.yml

# handlers/main.yml
---
- name: Restart nginx
  ansible.builtin.service:
    name: "{{ _nginx_service_name }}"
    state: restarted
  listen: restart nginx

- name: Reload nginx
  ansible.builtin.service:
    name: "{{ _nginx_service_name }}"
    state: reloaded
  listen: reload nginx

- name: Test nginx config
  ansible.builtin.command: nginx -t
  changed_when: false
  listen: test nginx config

include_role dynamique et when conditionnel

La directive include_role permet d'inclure dynamiquement des roles à l'intérieur d'un play, avec des conditions et des variables calculées à l'exécution — impossible avec roles: statique.

# playbook avec include_role dynamique
---
- name: Configuration des serveurs web
  hosts: webservers
  become: true

  tasks:
    - name: Installer Nginx ou Apache selon le groupe
      ansible.builtin.include_role:
        name: "{{ 'nginx' if 'nginx_servers' in group_names else 'apache2' }}"
      vars:
        web_port: 80

    - name: Configurer SSL uniquement en production
      ansible.builtin.include_role:
        name: ssl_termination
      when: ansible_env.ENVIRONMENT | default('dev') == 'prod'

    - name: Appliquer les roles de monitoring pour chaque service
      ansible.builtin.include_role:
        name: "monitoring_{{ item }}"
      loop:
        - nginx
        - php_fpm
        - postgresql
      when: monitoring_enabled | default(true)

Contenu Premium

Ce tutoriel avancé est réservé aux membres premium.

9,90€ / mois
  • Tous les tutoriels avancés
  • Nouveaux contenus chaque semaine
  • Suivi de progression
  • Annulation à tout moment
Morgann Riu

Écrit par

Morgann Riu

Expert en cybersécurité et administration Linux. Je partage mes connaissances à travers des tutoriels gratuits et des formations pour aider les administrateurs systèmes et développeurs à sécuriser leurs infrastructures.

Partager ce tutoriel

Cet article vous a plu ?

Commentaires

Checklist Sécurité Linux

30 points essentiels pour sécuriser un serveur Linux. Recevez aussi les nouveaux tutoriels par email.

Pas de spam. Désabonnement en 1 clic.