Sommaire

  1. Introduction
  2. Installation
  3. Ansible - Concepts de base
  4. Commandes Ansible essentielles
  5. Playbooks
  6. Inventaire
  7. Variables et Facts
  8. Modules Ansible courants
  9. Roles
  10. Ansible Navigator
  11. Comparaison ansible vs ansible-navigator
  12. Bonnes pratiques

Introduction

Ansible est un outil d’automatisation open-source qui permet de gérer la configuration, le déploiement d’applications et l’orchestration d’infrastructures. Il utilise une approche déclarative via des fichiers YAML appelés playbooks.

Ansible Navigator est une interface en ligne de commande moderne pour Ansible qui fonctionne avec des execution environments (conteneurs). Il offre une expérience interactive et améliore la reproductibilité des exécutions.

Pourquoi Ansible ?

  • Agentless : pas besoin d’installer d’agent sur les machines cibles
  • Simple : syntaxe YAML lisible
  • Idempotent : peut être exécuté plusieurs fois sans effets secondaires
  • Extensible : bibliothèque riche de modules

Pourquoi Ansible Navigator ?

  • Isolation : exécution dans des conteneurs
  • Reproductibilité : environments standardisés
  • Interface améliorée : mode interactif avec navigation
  • Logs structurés : meilleure traçabilité

Installation

Installation d’Ansible (méthode classique)

Avec pip (recommandé pour avoir la dernière version) :

1
pip install ansible

Explication : Installe Ansible via le gestionnaire de paquets Python. C’est la méthode la plus flexible pour obtenir les versions récentes.

Avec apt (Debian/Ubuntu) :

1
2
sudo apt update
sudo apt install ansible

Explication : Installe Ansible depuis les dépôts officiels. La version peut être plus ancienne mais plus stable.

Avec yum/dnf (RHEL/CentOS/Fedora) :

1
sudo dnf install ansible

Vérification de l’installation :

1
ansible --version

Installation d’Ansible Navigator

Prérequis : Docker ou Podman doit être installé sur le système.

Avec pip :

1
pip install ansible-navigator

Explication : Ansible Navigator nécessite un runtime de conteneurs pour fonctionner avec les execution environments.

Vérification :

1
ansible-navigator --version

Configuration de base :

Créer un fichier ansible-navigator.yml à la racine de votre projet :

1
2
3
4
5
6
7
ansible-navigator:
  execution-environment:
    image: quay.io/ansible/creator-ee:latest
    pull-policy: missing
  mode: stdout
  playbook-artifact:
    enable: true

Explication :

  • execution-environment.image : spécifie l’image de conteneur à utiliser
  • pull-policy: missing : télécharge l’image seulement si elle n’existe pas localement
  • mode: stdout : affiche la sortie directement (mode interactive disponible aussi)
  • playbook-artifact.enable : sauvegarde les logs d’exécution

Ansible - Concepts de base

Architecture

1
2
3
4
5
6
┌─────────────┐
│   Control   │
│    Node     │ ──SSH/WinRM──> ┌──────────┐
│  (Ansible)  │                │  Managed │
└─────────────┘                │   Nodes  │
                               └──────────┘

Control Node : machine où Ansible est installé et d’où les commandes sont exécutées.

Managed Nodes : serveurs cibles gérés par Ansible. Pas besoin d’agent installé.

Inventory : liste des managed nodes organisés en groupes.

Playbook : fichier YAML contenant les tâches à exécuter.

Module : unité de code exécutée sur les managed nodes (ex: apt, copy, service).

Task : appel d’un module avec ses paramètres.

Role : ensemble organisé de tasks, variables, et fichiers réutilisables.

Facts : informations système collectées automatiquement sur les managed nodes.


Commandes Ansible essentielles

ansible (commandes ad-hoc)

Ping tous les hosts :

1
ansible all -m ping

Explication : Vérifie la connectivité avec tous les serveurs de l’inventaire. Le module ping teste la connexion SSH et la présence de Python.

Exécuter une commande sur tous les serveurs :

1
ansible all -a "uptime"

Explication : Le flag -a permet d’exécuter une commande shell directement. Par défaut, utilise le module command.

Exécuter sur un groupe spécifique :

1
ansible webservers -m apt -a "name=nginx state=present" --become

Explication :

  • webservers : groupe de l’inventaire
  • -m apt : utilise le module apt
  • -a : arguments du module
  • --become : exécute avec privilèges sudo

Copier un fichier :

1
ansible all -m copy -a "src=/local/file dest=/remote/file mode=0644"

Explication : Utilise le module copy pour transférer un fichier vers les serveurs distants avec les permissions spécifiées.

Redémarrer un service :

1
ansible webservers -m service -a "name=nginx state=restarted" --become

Explication : Gère les services systemd/init avec le module service. Les états possibles : started, stopped, restarted, reloaded.

Collecter les facts d’un serveur :

1
ansible hostname -m setup

Explication : Le module setup collecte toutes les informations système (OS, IP, CPU, mémoire, etc.).

Filtrer les facts :

1
ansible hostname -m setup -a "filter=ansible_distribution*"

Explication : Le filtre permet de cibler des facts spécifiques, ici ceux concernant la distribution Linux.

ansible-playbook

Exécuter un playbook :

1
ansible-playbook playbook.yml

Explication : Lance l’exécution du playbook sur les hosts définis dans le fichier.

Avec un inventaire spécifique :

1
ansible-playbook -i inventory.ini playbook.yml

Explication : Le flag -i spécifie le fichier d’inventaire à utiliser au lieu du défaut (/etc/ansible/hosts).

Mode check (dry-run) :

1
ansible-playbook playbook.yml --check

Explication : Simule l’exécution sans effectuer de changements réels. Utile pour tester avant déploiement.

Mode diff :

1
ansible-playbook playbook.yml --check --diff

Explication : Affiche les différences qui seraient appliquées sur les fichiers modifiés.

Verbose (debug) :

1
2
ansible-playbook playbook.yml -v
ansible-playbook playbook.yml -vvv

Explication : Augmente la verbosité des logs. -v basique, -vvv très détaillé (debug), -vvvv debug connexion.

Avec des variables en ligne :

1
ansible-playbook playbook.yml -e "version=1.2.3 env=production"

Explication : Le flag -e (ou --extra-vars) permet de passer des variables qui surchargent toutes les autres sources.

Limiter à certains hosts :

1
ansible-playbook playbook.yml --limit webserver01

Explication : Restreint l’exécution à un host ou un groupe spécifique, même si le playbook en cible plus.

Démarrer à une tâche spécifique :

1
ansible-playbook playbook.yml --start-at-task "Install packages"

Explication : Utile pour reprendre un playbook après un échec à une tâche particulière.

Avec des tags :

1
2
ansible-playbook playbook.yml --tags "configuration"
ansible-playbook playbook.yml --skip-tags "configuration"

Explication : Permet d’exécuter ou d’ignorer seulement les tâches marquées avec certains tags.

ansible-galaxy

Installer un role depuis Galaxy :

1
ansible-galaxy install geerlingguy.docker

Explication : Télécharge un role depuis Ansible Galaxy (dépôt public de roles) dans le répertoire par défaut.

Installer depuis un fichier requirements :

1
ansible-galaxy install -r requirements.yml

Explication : Installe tous les roles listés dans le fichier YAML requirements.

Lister les roles installés :

1
ansible-galaxy list

Créer un nouveau role :

1
ansible-galaxy init my-role

Explication : Génère la structure de dossiers standard d’un role Ansible.

ansible-vault

Créer un fichier chiffré :

1
ansible-vault create secrets.yml

Explication : Ouvre un éditeur pour créer un fichier chiffré. Demande un mot de passe pour le chiffrement.

Éditer un fichier chiffré :

1
ansible-vault edit secrets.yml

Explication : Déchiffre temporairement pour édition, puis re-chiffre automatiquement.

Chiffrer un fichier existant :

1
ansible-vault encrypt vars.yml

Déchiffrer un fichier :

1
ansible-vault decrypt secrets.yml

Explication : Attention, le fichier reste déchiffré sur le disque après cette commande.

Changer le mot de passe :

1
ansible-vault rekey secrets.yml

Utiliser un fichier de mot de passe :

1
ansible-playbook playbook.yml --vault-password-file .vault_pass

Explication : Lit le mot de passe depuis un fichier au lieu de le demander interactivement.


Playbooks

Structure de base d’un playbook

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
---
- name: Configuration des serveurs web
  hosts: webservers
  become: yes
  vars:
    http_port: 80
    max_clients: 200
  
  tasks:
    - name: Installer nginx
      apt:
        name: nginx
        state: present
        update_cache: yes
    
    - name: Copier la configuration
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        mode: '0644'
      notify: Redémarrer nginx
    
    - name: Démarrer nginx
      service:
        name: nginx
        state: started
        enabled: yes
  
  handlers:
    - name: Redémarrer nginx
      service:
        name: nginx
        state: restarted

Explication détaillée :

  • --- : marqueur de début de document YAML
  • name : description lisible du play
  • hosts : groupe ou host cible de l’inventaire
  • become: yes : exécute les tâches avec sudo
  • vars : variables locales au play
  • tasks : liste des tâches à exécuter séquentiellement
  • handlers : tâches spéciales exécutées seulement si notifiées (ex: redémarrage après modification de config)

Conditions et boucles

Condition simple :

1
2
3
4
5
- name: Installer Apache seulement sur Debian
  apt:
    name: apache2
    state: present
  when: ansible_os_family == "Debian"

Explication : La tâche s’exécute seulement si la condition when est vraie. Utilise les facts Ansible.

Boucle simple :

1
2
3
4
5
6
7
8
- name: Installer plusieurs paquets
  apt:
    name: "{{ item }}"
    state: present
  loop:
    - vim
    - git
    - curl

Explication : loop itère sur la liste. La variable {{ item }} représente l’élément courant.

Boucle avec dictionnaires :

1
2
3
4
5
6
7
8
- name: Créer des utilisateurs
  user:
    name: "{{ item.name }}"
    groups: "{{ item.groups }}"
    state: present
  loop:
    - { name: 'alice', groups: 'developers' }
    - { name: 'bob', groups: 'admins' }

Explication : On peut itérer sur des objets complexes et accéder à leurs propriétés avec la notation point.

Conditions multiples :

1
2
3
4
5
6
- name: Tâche complexe
  debug:
    msg: "Exécution"
  when:
    - ansible_distribution == "Ubuntu"
    - ansible_distribution_version >= "20.04"

Explication : Toutes les conditions doivent être vraies (AND logique). Pour un OR, utiliser or dans l’expression.

Blocks et gestion d’erreurs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
- name: Gestion d'erreurs avec blocks
  block:
    - name: Tentative d'installation
      apt:
        name: paquet-inexistant
        state: present
  
  rescue:
    - name: En cas d'erreur
      debug:
        msg: "L'installation a échoué, plan B"
    
    - name: Installer alternative
      apt:
        name: paquet-alternatif
        state: present
  
  always:
    - name: Toujours exécuté
      debug:
        msg: "Nettoyage effectué"

Explication :

  • block : groupe de tâches
  • rescue : exécuté si une tâche du block échoue
  • always : exécuté dans tous les cas (équivalent de finally)

Import vs Include

Import (statique, au parsing) :

1
2
- name: Import de tâches
  import_tasks: common-tasks.yml

Explication : Le fichier est inclus lors du parsing. Les conditions et tags s’appliquent à toutes les tâches importées.

Include (dynamique, à l’exécution) :

1
2
- name: Include conditionnel
  include_tasks: "{{ ansible_os_family }}.yml"

Explication : Le fichier est inclus dynamiquement. Permet des noms de fichiers basés sur des variables.


Inventaire

Inventaire INI

Fichier inventory.ini :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[webservers]
web01.example.com
web02.example.com

[databases]
db01.example.com ansible_host=192.168.1.10 ansible_port=2222

[production:children]
webservers
databases

[production:vars]
ansible_user=deploy
ansible_python_interpreter=/usr/bin/python3

Explication :

  • [groupname] : définit un groupe
  • Variables d’hôte : paramètres spécifiques après le hostname
  • [group:children] : groupe de groupes
  • [group:vars] : variables appliquées à tout le groupe
  • ansible_host : surcharge l’IP/hostname de connexion
  • ansible_port : port SSH personnalisé
  • ansible_user : utilisateur pour la connexion SSH

Inventaire YAML

Fichier inventory.yml :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
all:
  children:
    webservers:
      hosts:
        web01.example.com:
        web02.example.com:
          http_port: 8080
    
    databases:
      hosts:
        db01.example.com:
          ansible_host: 192.168.1.10
          ansible_port: 2222
    
    production:
      children:
        webservers:
        databases:
      vars:
        ansible_user: deploy
        env: production

Explication : Structure YAML équivalente au format INI. Plus flexible pour des structures complexes.

Inventaire dynamique

Script Python simple :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/usr/bin/env python3
import json

inventory = {
    "webservers": {
        "hosts": ["web01", "web02"]
    },
    "_meta": {
        "hostvars": {
            "web01": {"ansible_host": "192.168.1.11"},
            "web02": {"ansible_host": "192.168.1.12"}
        }
    }
}

print(json.dumps(inventory))

Utilisation :

1
ansible-playbook -i dynamic_inventory.py playbook.yml

Explication : Un inventaire dynamique est un script exécutable qui retourne du JSON. Utile pour interroger des APIs (AWS, Azure, etc.).

Patterns d’inventaire

1
ansible webservers -m ping

Cible le groupe webservers

1
ansible web* -m ping

Cible tous les hosts commençant par “web”

1
ansible webservers:databases -m ping

Union (webservers OU databases)

1
ansible webservers:!web01 -m ping

Exclusion (webservers SAUF web01)

1
ansible webservers:&production -m ping

Intersection (webservers ET production)


Variables et Facts

Sources de variables (par ordre de priorité)

  1. Extra vars (-e en ligne de commande)
  2. Task vars (dans la tâche)
  3. Block vars (dans un block)
  4. Role et include vars
  5. Play vars_files
  6. Play vars_prompt
  7. Play vars
  8. Host facts
  9. Playbook host_vars
  10. Playbook group_vars
  11. Inventory host_vars
  12. Inventory group_vars
  13. Inventory vars
  14. Role defaults

Définir des variables

Dans un playbook :

1
2
3
4
5
- name: Exemple de variables
  hosts: webservers
  vars:
    http_port: 80
    server_name: www.example.com

Dans vars_files :

1
2
3
4
5
- name: Avec fichier externe
  hosts: webservers
  vars_files:
    - vars/common.yml
    - vars/{{ env }}.yml

Dans group_vars :

Créer group_vars/webservers.yml :

1
2
http_port: 80
max_clients: 200

Explication : Ansible charge automatiquement group_vars/groupname.yml et host_vars/hostname.yml.

Variables enregistrées :

1
2
3
4
5
6
7
- name: Exécuter commande
  command: whoami
  register: login_user

- name: Afficher résultat
  debug:
    msg: "Utilisateur: {{ login_user.stdout }}"

Explication : register sauvegarde le résultat complet de la tâche dans une variable pour utilisation ultérieure.

Facts Ansible

Facts utiles :

  • ansible_hostname : nom d’hôte
  • ansible_fqdn : nom de domaine complet
  • ansible_default_ipv4.address : IP principale
  • ansible_distribution : distribution Linux (Ubuntu, CentOS, etc.)
  • ansible_distribution_version : version de la distribution
  • ansible_os_family : famille d’OS (Debian, RedHat, etc.)
  • ansible_processor_cores : nombre de cœurs CPU
  • ansible_memtotal_mb : RAM totale en MB
  • ansible_mounts : points de montage

Désactiver la collecte des facts :

1
2
3
- name: Playbook sans facts
  hosts: all
  gather_facts: no

Explication : Accélère l’exécution si les facts ne sont pas nécessaires.

Créer des facts personnalisés :

Sur le managed node, créer /etc/ansible/facts.d/custom.fact :

1
2
3
[general]
environment=production
datacenter=paris

Utilisation :

1
2
- debug:
    msg: "Environnement: {{ ansible_local.custom.general.environment }}"

Explication : Les facts locaux sont accessibles via ansible_local.<filename>.<section>.<key>.


Modules Ansible courants

Gestion de paquets

apt (Debian/Ubuntu) :

1
2
3
4
5
6
- name: Installer nginx
  apt:
    name: nginx
    state: present
    update_cache: yes
    cache_valid_time: 3600

Explication :

  • state: present : assure que le paquet est installé
  • update_cache : équivaut à apt-get update
  • cache_valid_time : ne met à jour le cache que s’il a plus de X secondes

yum/dnf (RHEL/CentOS) :

1
2
3
4
- name: Installer httpd
  yum:
    name: httpd
    state: latest

package (module générique) :

1
2
3
4
- name: Installation multi-distribution
  package:
    name: vim
    state: present

Explication : Détecte automatiquement le gestionnaire de paquets (apt, yum, etc.).

Gestion de fichiers

copy (copier des fichiers) :

1
2
3
4
5
6
7
8
- name: Copier fichier de configuration
  copy:
    src: files/config.conf
    dest: /etc/app/config.conf
    owner: root
    group: root
    mode: '0644'
    backup: yes

Explication :

  • src : fichier source sur le control node
  • dest : destination sur le managed node
  • backup: yes : crée une copie avant écrasement

template (Jinja2) :

1
2
3
4
5
- name: Générer config depuis template
  template:
    src: templates/nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    validate: 'nginx -t -c %s'

Fichier template nginx.conf.j2 :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
server {
    listen {{ http_port }};
    server_name {{ server_name }};
    
    {% for location in locations %}
    location {{ location.path }} {
        proxy_pass {{ location.backend }};
    }
    {% endfor %}
}

Explication :

  • Syntaxe Jinja2 avec {{ variable }} et {% contrôle %}
  • validate : commande de validation avant remplacement du fichier

file (gestion de fichiers/dossiers) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
- name: Créer un répertoire
  file:
    path: /var/www/app
    state: directory
    owner: www-data
    mode: '0755'

- name: Créer un lien symbolique
  file:
    src: /var/www/app/current
    dest: /var/www/app/releases/v1.2.3
    state: link

- name: Supprimer un fichier
  file:
    path: /tmp/old-file
    state: absent

lineinfile (modifier une ligne) :

1
2
3
4
5
- name: Configurer hostname dans /etc/hosts
  lineinfile:
    path: /etc/hosts
    regexp: '^127\.0\.1\.1'
    line: "127.0.1.1 {{ ansible_hostname }}"

Explication : Modifie ou ajoute une ligne dans un fichier. Utilise regex pour trouver la ligne.

blockinfile (insérer un bloc) :

1
2
3
4
5
6
7
8
- name: Ajouter configuration SSH
  blockinfile:
    path: /etc/ssh/sshd_config
    block: |
      PermitRootLogin no
      PasswordAuthentication no
      PubkeyAuthentication yes
    marker: "# {mark} ANSIBLE MANAGED BLOCK"

Gestion de services

service / systemd :

1
2
3
4
5
- name: Gérer nginx
  service:
    name: nginx
    state: started
    enabled: yes

Explication :

  • state: started : démarre le service
  • enabled: yes : active au démarrage du système
  • États possibles : started, stopped, restarted, reloaded

Exécution de commandes

command :

1
2
3
4
5
- name: Commande simple
  command: /usr/bin/create-backup.sh
  args:
    chdir: /var/backups
    creates: /var/backups/backup.tar.gz

Explication :

  • N’interprète pas les variables shell ($HOME, etc.)
  • creates : skip si le fichier existe déjà (idempotence)

shell :

1
2
3
- name: Commande avec pipe
  shell: cat /var/log/app.log | grep ERROR | wc -l
  register: error_count

Explication : Utilise un shell complet (/bin/sh). Permet pipes, redirections, variables d’environnement.

script :

1
2
- name: Exécuter script local sur remote
  script: scripts/deploy.sh --version 1.2.3

Gestion d’utilisateurs

user :

1
2
3
4
5
6
7
8
- name: Créer utilisateur
  user:
    name: deploy
    shell: /bin/bash
    groups: sudo,www-data
    append: yes
    create_home: yes
    password: "{{ 'SecretPassword123' | password_hash('sha512') }}"

Explication :

  • append: yes : ajoute aux groupes sans supprimer les autres
  • Mot de passe doit être hashé (filtre password_hash)

authorized_key :

1
2
3
4
5
- name: Ajouter clé SSH
  authorized_key:
    user: deploy
    key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
    state: present

Modules réseau et cloud

get_url :

1
2
3
4
5
- name: Télécharger fichier
  get_url:
    url: https://example.com/file.tar.gz
    dest: /tmp/file.tar.gz
    checksum: sha256:abc123...

uri (API REST) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
- name: Appel API
  uri:
    url: https://api.example.com/deploy
    method: POST
    body_format: json
    body:
      version: "1.2.3"
      environment: "production"
    headers:
      Authorization: "Bearer {{ api_token }}"
    status_code: 201
  register: api_response

docker_container :

1
2
3
4
5
6
7
8
9
- name: Lancer conteneur Docker
  docker_container:
    name: webapp
    image: nginx:alpine
    state: started
    ports:
      - "80:80"
    volumes:
      - /var/www:/usr/share/nginx/html

Roles

Structure d’un role

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
my-role/
├── defaults/
   └── main.yml       # Variables par défaut (priorité basse)
├── files/
   └── config.txt     # Fichiers statiques
├── handlers/
   └── main.yml       # Handlers
├── meta/
   └── main.yml       # Métadonnées et dépendances
├── tasks/
   └── main.yml       # Tâches principales
├── templates/
   └── app.conf.j2    # Templates Jinja2
├── tests/
   └── test.yml       # Tests du role
└── vars/
    └── main.yml       # Variables du role (priorité haute)

Exemple de role complet

tasks/main.yml :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
---
- name: Installer les paquets requis
  apt:
    name: "{{ item }}"
    state: present
  loop: "{{ nginx_packages }}"

- name: Copier la configuration
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: Redémarrer nginx

- name: S'assurer que nginx est démarré
  service:
    name: nginx
    state: started
    enabled: yes

defaults/main.yml :

1
2
3
4
5
6
7
---
nginx_packages:
  - nginx
  - nginx-extras

nginx_worker_processes: auto
nginx_worker_connections: 1024

handlers/main.yml :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
---
- name: Redémarrer nginx
  service:
    name: nginx
    state: restarted

- name: Recharger nginx
  service:
    name: nginx
    state: reloaded

meta/main.yml :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
---
dependencies:
  - role: common
    vars:
      some_parameter: value

galaxy_info:
  author: Your Name
  description: Nginx web server role
  license: MIT
  min_ansible_version: 2.9
  platforms:
    - name: Ubuntu
      versions:
        - focal
        - jammy

Utiliser un role

Dans un playbook :

1
2
3
4
5
6
7
---
- name: Configurer serveurs web
  hosts: webservers
  roles:
    - common
    - nginx
    - { role: monitoring, tags: ['monitoring'] }

Avec variables :

1
2
3
4
5
6
7
- name: Configurer avec paramètres
  hosts: webservers
  roles:
    - role: nginx
      vars:
        nginx_worker_processes: 4
        nginx_worker_connections: 2048

Avec include_role (dynamique) :

1
2
3
4
5
6
- name: Include conditionnel
  include_role:
    name: "{{ role_name }}"
  vars:
    role_name: nginx
  when: install_webserver

Ansible Navigator

Concepts clés

Execution Environment (EE) : conteneur contenant Ansible, Python, et toutes les dépendances nécessaires. Garantit la reproductibilité.

Artifact : fichier JSON généré après chaque exécution contenant tous les détails (logs, variables, tâches, etc.).

Mode interactif : interface TUI (Text User Interface) permettant de naviguer dans l’exécution d’un playbook.

Mode stdout : sortie classique comme ansible-playbook, mais avec les avantages des EE.

Configuration ansible-navigator.yml

Configuration complète :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
---
ansible-navigator:
  ansible:
    inventories:
      - inventory/
    playbook: playbooks/site.yml
  
  execution-environment:
    container-engine: podman
    enabled: true
    image: quay.io/ansible/creator-ee:latest
    pull-policy: missing
    volume-mounts:
      - src: /home/user/ansible/
        dest: /runner/project
        options: Z
  
  logging:
    level: info
    append: true
    file: ./ansible-navigator.log
  
  mode: interactive
  
  playbook-artifact:
    enable: true
    replay: ./artifacts/
    save-as: "{playbook_name}-{ts_utc}.json"
  
  color:
    enable: true
    osc4: true

Explication détaillée :

  • container-engine : docker ou podman
  • volume-mounts : montage de volumes dans le conteneur
  • options: Z : pour SELinux (nécessaire sur RHEL/Fedora)
  • pull-policy : always, missing, never, tag
  • mode : interactive ou stdout
  • playbook-artifact.save-as : pattern de nommage des artifacts
  • {ts_utc} : timestamp UTC, {playbook_name} : nom du playbook

Commandes Ansible Navigator

Exécuter un playbook (mode stdout) :

1
ansible-navigator run playbook.yml

Explication : Lance le playbook dans un execution environment. Équivalent moderne de ansible-playbook.

Mode interactif :

1
ansible-navigator run playbook.yml -m interactive

Explication : Ouvre l’interface TUI pour naviguer dans l’exécution. Permet d’explorer tâche par tâche.

Avec inventaire spécifique :

1
ansible-navigator run playbook.yml -i inventory/production.yml

Passer des variables :

1
ansible-navigator run playbook.yml -e "env=prod version=2.1.0"

Utiliser une image EE personnalisée :

1
ansible-navigator run playbook.yml --eei custom-ee:latest

Explication : --eei (execution environment image) surcharge l’image définie dans la config.

Mode check avec navigator :

1
ansible-navigator run playbook.yml --check --diff

Limiter à certains hosts :

1
ansible-navigator run playbook.yml --limit webservers

Lorsque vous êtes en mode interactif :

Touches de navigation :

  • ↑/↓ ou j/k : naviguer dans les listes
  • Enter : entrer dans un élément
  • Esc ou 0 : revenir en arrière
  • :q ou Ctrl+C : quitter
  • :help : afficher l’aide
  • / : rechercher

Numéros :

  • Taper un numéro directement pour aller à cet élément
  • Ex: 3 suivi de Enter pour aller au 3ème élément

Exploration :

  • :tasks : voir toutes les tâches
  • :hosts : voir tous les hosts
  • :plays : voir tous les plays
  • :json : voir la représentation JSON

Exemple de workflow interactif :

  1. Lancer : ansible-navigator run site.yml -m interactive
  2. Sélectionner un play (ex: taper 1)
  3. Sélectionner une tâche (ex: taper 5)
  4. Voir les détails de la tâche avec les variables utilisées
  5. Appuyer sur Esc pour revenir
  6. Taper :json pour voir le JSON complet

Explorer un artifact

Relire une exécution passée :

1
ansible-navigator replay artifacts/site-2025-10-01T14-30-00.json

Explication : Permet de naviguer dans une exécution précédente comme si elle venait de se produire. Utile pour le debug et l’audit.

Lister les artifacts :

1
ls -lh artifacts/

Extraire des informations d’un artifact :

1
jq '.plays[0].tasks' artifacts/site-2025-10-01T14-30-00.json

Explication : Les artifacts sont des fichiers JSON, donc utilisables avec jq pour extraction de données.

Collections avec Navigator

Lister les collections disponibles :

1
ansible-navigator collections

Explication : Affiche toutes les collections disponibles dans l’execution environment.

Explorer une collection :

1
ansible-navigator collections --eei quay.io/ansible/creator-ee:latest

Afficher les modules d’une collection :

1
ansible-navigator doc ansible.builtin.copy

Explication : Documentation interactive des modules avec exemples.

Inventaire avec Navigator

Explorer l’inventaire :

1
ansible-navigator inventory -i inventory.yml

Explication : Interface interactive pour visualiser l’inventaire complet.

Mode liste :

1
ansible-navigator inventory -i inventory.yml --list

Graph de l’inventaire :

1
ansible-navigator inventory -i inventory.yml --graph

Explication : Affiche l’arborescence des groupes et hosts.

Variables d’un host :

1
ansible-navigator inventory -i inventory.yml --host webserver01

Configuration avec Navigator

Afficher la configuration courante :

1
ansible-navigator settings

Explication : Montre toutes les configurations actives et leur source (fichier, env, défaut).

Dump de la config en YAML :

1
ansible-navigator settings --effective --format yaml

Afficher seulement certaines sections :

1
ansible-navigator settings --mode stdout | grep execution-environment

Images et Execution Environments

Lister les images disponibles :

1
ansible-navigator images

Explication : Affiche toutes les images EE disponibles localement ou configurées.

Détails d’une image :

1
ansible-navigator images --eei quay.io/ansible/creator-ee:latest

Builder une image EE personnalisée :

Créer execution-environment.yml :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
---
version: 3

build_arg_defaults:
  ANSIBLE_GALAXY_CLI_COLLECTION_OPTS: '--pre'

dependencies:
  galaxy: requirements.yml
  python: requirements.txt
  system: bindep.txt

images:
  base_image:
    name: quay.io/ansible/ansible-runner:latest

additional_build_steps:
  prepend_galaxy:
    - RUN pip3 install --upgrade pip setuptools
  
  append_final:
    - RUN echo "Custom EE built on $(date)" > /etc/custom-ee-info

Construire l’image :

1
ansible-builder build -t my-custom-ee:1.0 -v 3

Explication : ansible-builder crée une image de conteneur avec toutes les dépendances spécifiées.

Commandes adhoc avec Navigator

Ping avec navigator :

1
ansible-navigator exec -- ansible all -m ping

Explication : exec permet d’exécuter n’importe quelle commande ansible dans l’EE.

Commande shell :

1
ansible-navigator exec -- ansible webservers -a "uptime"

Collection de facts :

1
ansible-navigator exec -- ansible localhost -m setup

Débogage avec Navigator

Verbosité élevée :

1
ansible-navigator run playbook.yml -vvv

Logs détaillés :

1
ansible-navigator run playbook.yml --lf debug.log --ll debug

Explication :

  • --lf (log file) : fichier de log
  • --ll (log level) : debug, info, warning, error, critical

Debugger le conteneur EE :

1
ansible-navigator exec -- /bin/bash

Explication : Ouvre un shell interactif dans l’execution environment pour explorer l’environnement.

Passer des variables d’environnement :

1
ansible-navigator run playbook.yml --penv MY_VAR

Explication : --penv (pass environment) passe des variables d’environnement du host au conteneur.

Travailler avec des collections privées

Configuration avec token :

Dans ansible.cfg :

1
2
3
4
5
6
7
[galaxy]
server_list = automation_hub, galaxy

[galaxy_server.automation_hub]
url=https://cloud.redhat.com/api/automation-hub/
auth_url=https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token
token=my_token_here

Ou avec ansible-navigator.yml :

1
2
3
4
5
6
7
ansible-navigator:
  ansible:
    config: ./ansible.cfg
  execution-environment:
    environment-variables:
      set:
        ANSIBLE_GALAXY_SERVER_LIST: automation_hub

Comparaison ansible vs ansible-navigator

Aspectansible-playbookansible-navigator
EnvironnementSystème hôteConteneur (EE)
ReproductibilitéDépend du systèmeGarantie par l’image
DépendancesInstallation manuelleIncluses dans l’EE
InterfaceSortie texte linéaireTUI interactive
ArtifactsLogs basiquesJSON détaillé
DebugLimitéNavigation complète
IsolationAucuneComplète
PerformanceLégèrement plus rapideOverhead du conteneur (~5%)

Quand utiliser quoi ?

Utilisez ansible-playbook si :

  • Environnement simple et stable
  • Pas besoin de reproductibilité stricte
  • Scripts d’automatisation légers
  • Ressources limitées (pas de runtime de conteneurs)

Utilisez ansible-navigator si :

  • Environnements multiples (dev, staging, prod)
  • Équipes distribuées nécessitant la même configuration
  • Besoin d’audit et traçabilité détaillée
  • Collections avec dépendances Python complexes
  • CI/CD nécessitant isolation

Migration de ansible vers ansible-navigator

Étape 1 : Installer les prérequis :

1
2
pip install ansible-navigator
sudo dnf install podman

Étape 2 : Tester avec l’image par défaut :

1
ansible-navigator run playbook.yml --eei quay.io/ansible/creator-ee:latest

Étape 3 : Créer la configuration :

1
2
3
4
5
6
7
cat > ansible-navigator.yml <<EOF
---
ansible-navigator:
  execution-environment:
    image: quay.io/ansible/creator-ee:latest
  mode: stdout
EOF

Étape 4 : Adapter les playbooks :

Pas de changement nécessaire ! Les playbooks sont 100% compatibles.

Étape 5 : Gérer les collections :

Créer requirements.yml :

1
2
3
4
5
---
collections:
  - name: community.general
    version: ">=5.0.0"
  - name: ansible.posix

Installer dans l’EE :

1
ansible-navigator collections install -r requirements.yml

Ou builder une image personnalisée avec les collections pré-installées.


Bonnes pratiques

Organisation du projet

Structure recommandée :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
ansible-project/
├── ansible.cfg
├── ansible-navigator.yml
├── inventories/
   ├── production/
      ├── hosts.yml
      └── group_vars/
   └── staging/
       ├── hosts.yml
       └── group_vars/
├── playbooks/
   ├── site.yml
   ├── webservers.yml
   └── databases.yml
├── roles/
   ├── common/
   ├── nginx/
   └── postgresql/
├── group_vars/
   ├── all.yml
   └── webservers.yml
├── host_vars/
   └── special-host.yml
├── files/
├── templates/
├── vars/
   └── secrets.yml
├── requirements.yml
└── README.md

Sécurité

1. Toujours utiliser Ansible Vault pour les secrets :

1
ansible-vault create group_vars/all/vault.yml

Convention de nommage :

1
2
vault_db_password: SuperSecret123
vault_api_key: abc123def456

Utilisation dans les playbooks :

1
2
db_password: "{{ vault_db_password }}"
api_key: "{{ vault_api_key }}"

2. Ne jamais commiter de secrets non chiffrés :

Ajouter au .gitignore :

1
2
3
4
5
6
*.retry
*.log
.vault_pass
group_vars/*/vault.yml
host_vars/*/vault.yml
!**/*example*.yml

3. Utiliser become seulement quand nécessaire :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
- name: Tâche sans privilèges
  copy:
    src: file.txt
    dest: /home/user/file.txt

- name: Tâche avec privilèges
  apt:
    name: nginx
    state: present
  become: yes

4. Limiter les permissions sudo :

Sur les managed nodes, /etc/sudoers.d/ansible :

1
ansible ALL=(ALL) NOPASSWD: /usr/bin/systemctl, /usr/bin/apt-get

Performance

1. Activer le pipelining :

Dans ansible.cfg :

1
2
[defaults]
pipelining = True

Explication : Réduit le nombre de connexions SSH en envoyant plusieurs commandes par connexion.

2. Utiliser mitogen (stratégie alternative) :

1
pip install mitogen

Dans ansible.cfg :

1
2
3
[defaults]
strategy_plugins = /usr/local/lib/python3.9/site-packages/ansible_mitogen/plugins/strategy
strategy = mitogen_linear

Explication : Peut accélérer l’exécution de 1.5x à 7x selon les cas.

3. Parallélisme :

1
2
[defaults]
forks = 20

Explication : Nombre de hosts traités simultanément. Par défaut : 5.

4. Désactiver la collecte des facts si non nécessaire :

1
2
- hosts: all
  gather_facts: no

5. Utiliser async pour les tâches longues :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
- name: Longue tâche en arrière-plan
  command: /usr/local/bin/long-running-task
  async: 3600
  poll: 0
  register: long_task

- name: Vérifier plus tard
  async_status:
    jid: "{{ long_task.ansible_job_id }}"
  register: job_result
  until: job_result.finished
  retries: 30
  delay: 60

Idempotence

Principe : Un playbook doit pouvoir être exécuté plusieurs fois sans effets secondaires.

Mauvais exemple :

1
2
- name: Ajouter ligne (non idempotent)
  shell: echo "server=8.8.8.8" >> /etc/resolv.conf

Bon exemple :

1
2
3
4
5
- name: Configurer DNS (idempotent)
  lineinfile:
    path: /etc/resolv.conf
    line: "nameserver 8.8.8.8"
    state: present

Utiliser changed_when pour contrôler :

1
2
3
4
5
- name: Vérifier service
  command: systemctl is-active nginx
  register: nginx_status
  changed_when: false
  failed_when: nginx_status.rc not in [0, 3]

Tests

1. Tester la syntaxe :

1
ansible-playbook --syntax-check playbook.yml

2. Mode check avant déploiement :

1
ansible-playbook --check --diff playbook.yml

3. Utiliser Molecule pour tester les roles :

1
2
3
4
pip install molecule molecule-docker
cd roles/nginx
molecule init scenario
molecule test

4. Linter avec ansible-lint :

1
2
pip install ansible-lint
ansible-lint playbook.yml

Documentation

1. Commenter les playbooks :

1
2
3
4
5
6
7
8
- name: Configure web servers for production deployment
  hosts: webservers
  
  tasks:
    - name: Install nginx - Required for serving static content
      apt:
        name: nginx
        state: present

2. Documenter les variables :

Dans roles/nginx/README.md :

1
2
3
4
5
6
7
8
# Nginx Role

## Variables

| Variable | Default | Description |
|----------|---------|-------------|
| nginx_port | 80 | Port d'écoute HTTP |
| nginx_worker_processes | auto | Nombre de workers |

3. Utiliser des tags pour la documentation :

1
2
3
4
5
6
7
- name: Installation
  apt:
    name: nginx
    state: present
  tags:
    - install
    - packages

Versioning

1. Versionner les roles avec Galaxy :

Dans meta/main.yml :

1
2
3
4
galaxy_info:
  role_name: nginx
  namespace: mycompany
  version: 1.2.3

2. Pinning des versions de collections :

1
2
3
collections:
  - name: community.general
    version: "5.8.0"

3. Utiliser des branches Git :

1
2
3
main → production
develop → staging
feature/* → développement

Gestion des erreurs

1. Ignorer les erreurs contrôlées :

1
2
3
4
5
6
7
8
9
- name: Tâche qui peut échouer
  command: /opt/script-maybe-fails.sh
  ignore_errors: yes
  register: result

- name: Action si échec
  debug:
    msg: "Le script a échoué, c'est ok"
  when: result is failed

2. Définir des conditions d’échec personnalisées :

1
2
3
4
- name: Vérifier espace disque
  shell: df -h / | tail -1 | awk '{print $5}' | sed 's/%//'
  register: disk_usage
  failed_when: disk_usage.stdout|int > 90

3. Bloc rescue pour gestion avancée :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
- block:
    - name: Déploiement version nouvelle
      include_tasks: deploy-v2.yml
  
  rescue:
    - name: Rollback vers version stable
      include_tasks: deploy-v1.yml
    
    - name: Alerter l'équipe
      mail:
        to: ops@company.com
        subject: "Déploiement échoué"
  
  always:
    - name: Cleanup
      file:
        path: /tmp/deploy-temp
        state: absent

CI/CD Integration

Exemple GitLab CI :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
stages:
  - lint
  - test
  - deploy

lint:
  stage: lint
  image: quay.io/ansible/creator-ee:latest
  script:
    - ansible-lint playbooks/

test:
  stage: test
  image: quay.io/ansible/creator-ee:latest
  script:
    - ansible-playbook --syntax-check playbooks/site.yml
    - ansible-playbook --check playbooks/site.yml -i inventories/staging

deploy_staging:
  stage: deploy
  image: quay.io/ansible/creator-ee:latest
  script:
    - ansible-navigator run playbooks/site.yml -i inventories/staging
  only:
    - develop

deploy_production:
  stage: deploy
  image: quay.io/ansible/creator-ee:latest
  script:
    - ansible-navigator run playbooks/site.yml -i inventories/production
  only:
    - main
  when: manual

Ressources complémentaires

Documentation officielle :

Collections essentielles :

  • ansible.builtin : modules de base
  • community.general : modules communautaires variés
  • ansible.posix : modules Unix/Linux
  • community.docker : gestion Docker
  • kubernetes.core : gestion Kubernetes

Outils connexes :

  • Ansible Builder : création d’execution environments
  • Molecule : testing de roles
  • ansible-lint : linting de playbooks
  • AWX / Automation Controller : interface web pour Ansible

Bonnes pratiques de la communauté :


Dernière mise à jour : Octobre 2025