DevOpsFacile
AccueilParcours de formationCertificationsModulesCheat SheetÀ Propos
DevOpsFacile

Une plateforme d'apprentissage complète pour maîtriser les pratiques DevOps modernes, du débutant à l'expert.

contact@devopsfacile.fr

Formation

  • Parcours de formation
  • Modules

Informations

  • À Propos
  • Conditions d'utilisation
  • Confidentialité
  • Mentions légales

© 2026 DevOps Facile. Tous droits réservés.

Fait avec pour la communauté DevOps

ModulesAnsible Avancé : Vault, inventaires dynamiques et production

Module

Sécurisez vos secrets avec Ansible Vault, utilisez des inventaires dynamiques, maîtrisez les conditions et les boucles pour des playbooks de production.

  • 2h
  • Avancé
  • 6 exercices
Voir les exercices

Formation 100 % Linux

Tous les modules nécessitent un environnement Linux. Si vous êtes sur Windows, installez d'abord WSL (Windows Subsystem for Linux) avant de continuer.

Ansible Avancé : Vault, inventaires dynamiques et production

🎯 Objectifs

  • Chiffrer les secrets avec Ansible Vault
  • Utiliser des inventaires dynamiques (AWS, Docker, scripts)
  • Écrire des tâches conditionnelles et des boucles avancées
  • Optimiser l'exécution avec les tags et le parallélisme
  • Appliquer les bonnes pratiques pour un usage en production

📋 Prérequis

  • Ansible Intermédiaire - variables, templates, handlers, rôles
  • Ansible installé et fonctionnel
  • Bonne maîtrise des fichiers YAML

🔐 Ansible Vault : protéger les secrets

Le problème

Dans tes playbooks, tu as probablement des mots de passe, des clés API, des tokens. Les stocker en clair dans un fichier versionné avec Git est une très mauvaise pratique - n'importe qui ayant accès au dépôt peut les lire.

La solution : Ansible Vault chiffre tes fichiers de variables. Seule la personne qui connaît le mot de passe du vault peut les déchiffrer.

Chiffrer un fichier entier

bash
# Créer un nouveau fichier chiffré
ansible-vault create vars/secrets.yml

# Modifier un fichier chiffré existant
ansible-vault edit vars/secrets.yml

# Chiffrer un fichier existant en clair
ansible-vault encrypt vars/secrets.yml

# Déchiffrer un fichier (attention : le résultat sera en clair)
ansible-vault decrypt vars/secrets.yml

# Voir le contenu sans le déchiffrer définitivement
ansible-vault view vars/secrets.yml

# Changer le mot de passe du vault
ansible-vault rekey vars/secrets.yml

Chiffrer une seule valeur

Utile quand tu veux chiffrer uniquement un mot de passe dans un fichier autrement lisible :

bash
ansible-vault encrypt_string 'MonMotDePasse123' --name 'db_password'

Résultat à coller dans ton fichier YAML :

yaml
db_password: !vault |
  $ANSIBLE_VAULT;1.1;AES256
  61616265353733623264343264333063...
  (suite du chiffrement)

Utiliser les fichiers chiffrés dans un playbook

yaml
---
- name: Déployer la base de données
  hosts: databases
  become: true
  vars_files:
    - vars/all.yml
    - vars/secrets.yml    # Fichier chiffré avec Vault

  tasks:
    - name: Créer l'utilisateur PostgreSQL
      community.postgresql.postgresql_user:
        name: "{{ db_user }}"
        password: "{{ db_password }}"    # Vient du fichier chiffré
        state: present
bash
# Lancer le playbook en fournissant le mot de passe vault
ansible-playbook playbook.yml --ask-vault-pass

# Ou via un fichier contenant le mot de passe (à ne pas versionner !)
ansible-playbook playbook.yml --vault-password-file ~/.vault_pass

Fichier de mot de passe vault

bash
# Créer le fichier (ne jamais le committer dans Git !)
echo "MonMotDePasseVault" > ~/.vault_pass
chmod 600 ~/.vault_pass

# Ajouter dans .gitignore
echo ".vault_pass" >> .gitignore

🌐 Inventaires Dynamiques

Le problème des inventaires statiques

Dans un environnement cloud, les serveurs naissent et meurent constamment. Maintenir un fichier inventaire.ini à la main devient impossible quand tu as 50 instances EC2 qui changent d'IP à chaque redémarrage.

La solution : les inventaires dynamiques interrogent une source de vérité (AWS, Azure, Docker...) en temps réel pour construire la liste des hôtes.

Plugin d'inventaire AWS EC2

bash
# Installer la collection AWS
ansible-galaxy collection install amazon.aws
pip install boto3
yaml
# inventaire_aws.yml
plugin: amazon.aws.aws_ec2
regions:
  - eu-west-1
filters:
  instance-state-name: running
  "tag:Environment": production
keyed_groups:
  - key: tags.Role        # Créer des groupes basés sur le tag "Role"
    prefix: role
hostnames:
  - private-ip-address
bash
# Tester l'inventaire dynamique
ansible-inventory -i inventaire_aws.yml --list

# Lancer un playbook avec cet inventaire
ansible-playbook -i inventaire_aws.yml playbook.yml

Inventaire dynamique basé sur un script

Tu peux écrire un script Python ou Bash qui retourne du JSON :

python
#!/usr/bin/env python3
# inventaire.py
import json
import subprocess

def get_docker_containers():
    # Récupère les conteneurs Docker en cours d'exécution
    result = subprocess.run(
        ['docker', 'ps', '--format', '{{.Names}}\t{{.ID}}'],
        capture_output=True, text=True
    )
    hosts = {}
    for line in result.stdout.strip().split('\n'):
        if line:
            name, container_id = line.split('\t')
            hosts[name] = {'ansible_connection': 'docker'}
    return hosts

inventory = {
    'docker_containers': {
        'hosts': list(get_docker_containers().keys())
    },
    '_meta': {
        'hostvars': get_docker_containers()
    }
}

print(json.dumps(inventory))
bash
chmod +x inventaire.py
ansible-playbook -i inventaire.py playbook.yml

🔀 Conditions et Boucles Avancées

La directive when

yaml
tasks:
  - name: Installer les paquets sur Debian/Ubuntu
    ansible.builtin.apt:
      name: nginx
      state: present
    when: ansible_os_family == "Debian"

  - name: Installer les paquets sur Red Hat/CentOS
    ansible.builtin.dnf:
      name: nginx
      state: present
    when: ansible_os_family == "RedHat"

  - name: Tâche uniquement en production
    ansible.builtin.debug:
      msg: "Déploiement en production !"
    when:
      - env == "production"
      - ansible_hostname.startswith("prod-")

  - name: Passer si déjà fait
    ansible.builtin.command: /opt/init.sh
    when: not init_done.stat.exists

Boucles avec loop

yaml
- name: Créer plusieurs utilisateurs
  ansible.builtin.user:
    name: "{{ item.name }}"
    groups: "{{ item.groups }}"
    state: present
  loop:
    - { name: alice, groups: sudo }
    - { name: bob, groups: www-data }
    - { name: charlie, groups: docker }

- name: Installer une liste de paquets
  ansible.builtin.apt:
    name: "{{ item }}"
    state: present
  loop:
    - git
    - curl
    - htop
    - vim

- name: Déployer plusieurs fichiers de configuration
  ansible.builtin.template:
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"
  loop:
    - { src: nginx.conf.j2, dest: /etc/nginx/nginx.conf }
    - { src: app.conf.j2, dest: /etc/nginx/sites-available/app }

Boucles avec loop_control

yaml
- name: Créer des répertoires avec un label clair
  ansible.builtin.file:
    path: "{{ item }}"
    state: directory
  loop:
    - /var/www/app1
    - /var/www/app2
    - /var/log/app1
  loop_control:
    label: "Répertoire : {{ item }}"    # Personnalise l'affichage dans les logs

Récupérer et réutiliser un résultat (register)

yaml
- name: Vérifier si le fichier existe
  ansible.builtin.stat:
    path: /etc/app/config.yml
  register: config_file            # Stocker le résultat dans une variable

- name: Créer la config si elle n'existe pas
  ansible.builtin.copy:
    src: files/config.yml
    dest: /etc/app/config.yml
  when: not config_file.stat.exists  # Utiliser le résultat

- name: Afficher la version déployée
  ansible.builtin.command: cat /etc/app/version
  register: app_version
  changed_when: false              # Cette commande ne "change" rien

- name: Afficher la version
  ansible.builtin.debug:
    msg: "Version actuelle : {{ app_version.stdout }}"

🏷️ Les Tags

À quoi servent les tags ?

Sur un playbook complexe avec 30 tâches, tu ne veux pas toujours tout relancer. Les tags permettent d'exécuter uniquement certaines tâches.

yaml
---
- name: Déployer l'application
  hosts: webservers
  become: true

  tasks:
    - name: Installer les dépendances système
      ansible.builtin.apt:
        name: "{{ item }}"
        state: present
      loop: "{{ system_packages }}"
      tags:
        - install
        - setup

    - name: Déployer le code applicatif
      ansible.builtin.git:
        repo: "{{ app_repo }}"
        dest: "{{ app_dir }}"
        version: "{{ app_version }}"
      tags:
        - deploy
        - code

    - name: Recharger la configuration
      ansible.builtin.service:
        name: nginx
        state: reloaded
      tags:
        - reload
        - deploy
bash
# Exécuter uniquement les tâches taguées "deploy"
ansible-playbook playbook.yml --tags deploy

# Exécuter tout SAUF les tâches taguées "install"
ansible-playbook playbook.yml --skip-tags install

# Lister tous les tags disponibles
ansible-playbook playbook.yml --list-tags

⚡ Optimisation et Bonnes Pratiques

Parallélisme avec forks

Par défaut, Ansible exécute les tâches sur 5 hôtes en parallèle. Augmente ce nombre pour les grands inventaires :

bash
# En ligne de commande
ansible-playbook playbook.yml -f 20

# Dans ansible.cfg
[defaults]
forks = 20

Le fichier ansible.cfg

Crée un fichier ansible.cfg à la racine de ton projet pour éviter de répéter les options :

ini
[defaults]
inventory     = inventaire.ini
remote_user   = ubuntu
private_key_file = ~/.ssh/id_ed25519
forks         = 10
host_key_checking = False    # Utile en dev, à activer en prod
vault_password_file = ~/.vault_pass
retry_files_enabled = False

[privilege_escalation]
become        = True
become_method = sudo

Déléguer une tâche à un hôte différent

yaml
- name: Enregistrer l'hôte dans le load balancer
  ansible.builtin.uri:
    url: "http://lb.example.com/api/add"
    method: POST
    body_format: json
    body:
      host: "{{ ansible_hostname }}"
  delegate_to: localhost    # Cette tâche s'exécute sur ton control node

Tâches locales

yaml
- name: Générer un rapport en local
  ansible.builtin.template:
    src: rapport.j2
    dest: /tmp/rapport_{{ inventory_hostname }}.txt
  delegate_to: localhost

Bonnes pratiques de production

yaml
# 1. Toujours nommer tes tâches
- name: Installer Nginx version {{ nginx_version }}    # ✅
  ansible.builtin.apt:
    name: "nginx={{ nginx_version }}"

# 2. Utiliser changed_when pour les commandes
- name: Vérifier la configuration Nginx
  ansible.builtin.command: nginx -t
  changed_when: false    # Cette commande ne modifie rien

# 3. Utiliser failed_when pour contrôler les erreurs
- name: Vérifier si le service existe
  ansible.builtin.command: systemctl status monservice
  register: service_status
  failed_when: service_status.rc > 1   # rc=0 OK, rc=1 inactif (acceptable)

# 4. Préférer les modules aux commandes shell
- name: Créer un utilisateur          # ✅ Idempotent
  ansible.builtin.user:
    name: deploy
    state: present

- name: Créer un utilisateur          # ❌ Pas idempotent
  ansible.builtin.command: useradd deploy

🧪 Tester ses Playbooks avec Molecule

Molecule est l'outil standard pour tester les rôles Ansible.

bash
# Installation
pip install molecule molecule-docker

# Initialiser les tests pour un rôle
cd roles/nginx
molecule init scenario

# Lancer les tests
molecule test

# Tester uniquement le lint
molecule lint

# Converger (appliquer le rôle) sans détruire
molecule converge
yaml
# molecule/default/converge.yml
---
- name: Converge
  hosts: all
  tasks:
    - name: Inclure le rôle nginx
      ansible.builtin.include_role:
        name: nginx
      vars:
        nginx_port: 80

⚠️ Erreurs Courantes en Production

ErreurCauseSolution
Vault password requiredFichier chiffré sans mot de passe fourni--ask-vault-pass ou --vault-password-file
Inventaire dynamique videCredentials cloud manquants ou mauvais filtreVérifier les variables d'environnement AWS/Azure
changed_when oubliéFaux positifs de changementsToujours définir changed_when: false pour les commandes de lecture
Playbook trop lentforks trop bas ou pas de pipeliningAugmenter forks et activer pipelining = True dans ansible.cfg
Secrets en clair dans les logsno_log non définiAjouter no_log: true sur les tâches avec des secrets

Masquer les secrets dans les logs

yaml
- name: Créer l'utilisateur avec son mot de passe
  ansible.builtin.user:
    name: deploy
    password: "{{ user_password | password_hash('sha512') }}"
  no_log: true    # Masque les paramètres dans les logs

📊 Récapitulatif

FonctionnalitéUtilisationCommande / Directive
VaultChiffrer les secretsansible-vault encrypt
Inventaire dynamiqueHôtes depuis le cloudPlugin aws_ec2, script JSON
whenCondition sur une tâchewhen: variable == "valeur"
loopRépéter une tâcheloop: [item1, item2]
registerStocker un résultatregister: ma_variable
TagsExécution sélectivetags: [deploy], --tags deploy
delegate_toDéléguer à un autre hôtedelegate_to: localhost
no_logMasquer les secretsno_log: true

📚 Ressources

  • Ansible Vault
  • Inventaires dynamiques
  • Molecule (tests)
  • Ansible Best Practices
  • Collection amazon.aws

🚀 Prochaines étapes

Tu maîtrises maintenant Ansible en production. Les prochaines étapes naturelles :

  1. Intégrer Ansible dans un pipeline CI/CD avec GitHub Actions ou GitLab CI
  2. Explorer AWX / Ansible Automation Platform - l'interface web pour Ansible en entreprise
  3. Découvrir Terraform pour provisionner l'infrastructure avant de la configurer avec Ansible

Exercices Pratiques

6 exercices pour mettre en pratique

01

01 - Ansible Vault : chiffrer et gérer les secrets

40 minutesAvancé
02

02 - Inventaires dynamiques et collections Ansible

45 minutesAvancé
03

03 - Optimisation : tags, parallélisme et délégation

35 minutesAvancé
04

04 - Intégrer Ansible dans un pipeline CI/CD

45 minutesAvancé
05

05 - Bonnes pratiques et patterns de production

40 minutesAvancé
06

06 - Projet final : infrastructure complète avec Ansible

90 minutesAvancé
Retour aux modules

Sur cette page

  • 🎯 Objectifs
  • 📋 Prérequis
  • 🔐 Ansible Vault : protéger les secrets
  • Le problème
  • Chiffrer un fichier entier
  • Chiffrer une seule valeur
  • Utiliser les fichiers chiffrés dans un playbook
  • Fichier de mot de passe vault
  • 🌐 Inventaires Dynamiques
  • Le problème des inventaires statiques
  • Plugin d'inventaire AWS EC2
  • Inventaire dynamique basé sur un script
  • 🔀 Conditions et Boucles Avancées
  • La directive when
  • Boucles avec loop
  • Boucles avec loop_control
  • Récupérer et réutiliser un résultat (register)
  • 🏷️ Les Tags
  • À quoi servent les tags ?
  • ⚡ Optimisation et Bonnes Pratiques
  • Parallélisme avec forks
  • Le fichier ansible.cfg
  • Déléguer une tâche à un hôte différent
  • Tâches locales
  • Bonnes pratiques de production
  • 🧪 Tester ses Playbooks avec Molecule
  • ⚠️ Erreurs Courantes en Production
  • Masquer les secrets dans les logs
  • 📊 Récapitulatif
  • 📚 Ressources
  • 🚀 Prochaines étapes