Aller au contenu

Concepts Ansible

Les fondations d'Ansible : inventaire, playbooks, modules, collections et facts pour automatiser l'infrastructure sans agent.


Qu'est-ce qu'Ansible

Ansible est un outil open source maintenu par Red Hat pour l'automatisation de la configuration, du provisioning et du déploiement d'infrastructure. Son principal avantage est d'être agentless : aucun daemon n'est installé sur les machines cibles. La communication s'effectue via SSH pour les systèmes Linux/Unix, et via WinRM pour les systèmes Windows.

Les instructions sont écrites en YAML declaratif, dans des fichiers appelés playbooks. Ce format lisible par un humain permet de versionner l'infrastructure au même titre que le code applicatif.

# Installation via pip (Python 3.9+ requis)
pip install ansible

# Verifier l'installation
ansible --version

La sortie indique la version d'Ansible, la version de Python utilisée, le chemin de configuration actif et les chemins de modules. Ces informations sont utiles pour diagnostiquer les problèmes d'environnement.


Vue d'ensemble des objets

Ansible organisé ses composants en deux catégories : les éléments partageables (regroupes dans des collections) et les éléments spécifiques à l'environnement (inventaire et facts).

graph TB
    subgraph Collection["Collection (namespace.collection)"]
        direction TB
        RO[Roles]
        PB[Playbooks]
        PB --> RO
    end

    subgraph PARAME1["Paramètres et données d'env. E1"]
        direction LR
        INVE1[Inventaire]
        FAE1[Facts]
    end

    subgraph PARAME2["Paramètres et données d'env. E2"]
        direction LR
        INVE2[Inventaire]
        FAE2[Facts]
    end

    subgraph PARAME3["Paramètres et données d'env. E3"]
        direction LR        
        INVE3[Inventaire]
        FAE3[Facts]
    end

    PARAME1 --configure--> PB
    PARAME2 --configure--> PB
    PARAME3 --configure--> PB

    style Collection stroke-dasharray: 5 5
    style PARAME1 stroke-dasharray: 5 5
    style PARAME2 stroke-dasharray: 5 5
    style PARAME3 stroke-dasharray: 5 5

Séparation des responsabilités :

  • La collection regroupe tout ce qui est générique et réutilisable : rôles, modules, plugins, filtres. Elle se publie sur Ansible Galaxy ou un dépôt prive.
  • L'inventaire décrit les hôtes et groupes propres a un environnement (production, staging, recette). Il reste en dehors de la collection.
  • Les facts sont collectes dynamiquement sur chaque hôte cible au moment de l'exécution. Ils représentent l'état réel de la machine.

Cette séparation garantit qu'une collection peut être reutilisee sur n'importe quel environnement sans modification.


Inventaire

L'inventaire définit les hôtes et groupes sur lesquels Ansible opère. Il peut être statique (fichier INI ou YAML) ou dynamique (plugin interrogeant une API externe).

Format INI (statique)

[webservers]
web1.example.com
web2.example.com ansible_user=ubuntu

[dbservers]
db1.example.com ansible_port=2222

[production:children]
webservers
dbservers

Le groupe production:children est un groupe de groupes : il hérité de tous les hôtes des groupes webservers et dbservers.

Format YAML (statique)

Le même inventaire exprime en YAML est plus explicite et supporte des structures imbriquees complexes :

# inventory/hosts.yml
all:
  children:
    webservers:
      hosts:
        web1.example.com:
        web2.example.com:
          ansible_user: ubuntu
    dbservers:
      hosts:
        db1.example.com:
          ansible_port: 2222
    production:
      children:
        webservers:
        dbservers:

Inventaire dynamique (plugin GCP)

Pour les environnements cloud, les plugins d'inventaire interrogent l'API du fournisseur et construisent l'inventaire à la volee :

# inventory/gcp.yml
plugin: google.cloud.gcp_compute
projects:
  - mon-projet-gcp
regions:
  - europe-west1
auth_kind: serviceaccount
service_account_file: /path/to/sa.json
keyed_groups:
  - key: labels.env
    prefix: env
  - key: labels.role
    prefix: role
# Afficher l'inventaire genere
ansible-inventory -i inventory/gcp.yml --list

La sortie JSON liste tous les hôtes découverts, leurs variables et leurs groupes d'appartenance.


Playbooks

Un playbook est un fichier YAML contenant une liste de plays. Chaque play cible un groupe d'hôtes et définit une sequence de tâches a exécuter dans l'ordre.

# playbooks/install_nginx.yml
---
- name: Installer et demarrer Nginx
  hosts: webservers
  become: true

  tasks:
    - name: Installer nginx
      ansible.builtin.apt:
        name: nginx
        state: present
        update_cache: true
      when: ansible_os_family == "Debian"

    - name: Demarrer et activer nginx
      ansible.builtin.systemd:
        name: nginx
        state: started
        enabled: true

Structure d'un play :

Clé Rôle
name Description lisible du play
hosts Groupe ou motif de cibles (ex. webservers, all)
become Escalade de privileges (sudo)
tasks Liste ordonnée des tâches a exécuter

La directive when: ansible_os_family == "Debian" est une condition : la tâche n'est exécutée que si le fact ansible_os_family correspond. Cela permet d'écrire des playbooks portables sur plusieurs distributions.

# Executer le playbook
ansible-playbook -i inventory/hosts.yml playbooks/install_nginx.yml

# Dry run : simuler sans modifier les hotes
ansible-playbook -i inventory/hosts.yml playbooks/install_nginx.yml --check

# Afficher les differences de fichiers
ansible-playbook -i inventory/hosts.yml playbooks/install_nginx.yml --diff

L'option --check est indispensable avant d'appliquer un changement en production. Combinée a --diff, elle affiche exactement ce qui serait modifie dans les fichiers de configuration.


Modules

Les modules sont les unites d'action d'Ansible. Chaque tâche appelle un module avec des parametres. Ansible inclut plusieurs milliers de modules dans la collection ansible.builtin et dans les collections de l'écosystème.

Module FQCN Usage principal
ansible.builtin.apt Gestion des paquets Debian/Ubuntu
ansible.builtin.yum Gestion des paquets RHEL/CentOS
ansible.builtin.systemd Gestion des services systemd
ansible.builtin.copy Copie de fichiers vers les hôtes
ansible.builtin.template Déploiement de templates Jinja2
ansible.builtin.file Permissions, propriétaire, liens
ansible.builtin.user Gestion des comptes utilisateurs
ansible.builtin.command Exécution de commandes arbitraires
ansible.builtin.assert Validation de conditions dans un play

Toujours utiliser le FQCN

La notation courte (apt, copy, template) est obsolète. Utiliser systematiquement le FQCN (ansible.builtin.apt, ansible.builtin.copy) pour deux raisons : éviter toute ambiguite quand plusieurs collections sont installees, et satisfaire ansible-lint qui rejette les noms courts par défaut.


Collections

Une collection est une unite de distribution qui regroupe des rôles, modules, plugins et filtres sous un namespace commun. Elle se publie sur Ansible Galaxy ou un dépôt Artifactory prive.

Le FQCN (Fully Qualified Collection Name) suit le schéma :

namespace.collection.module

Par exemple : community.postgresql.postgresql_db, amazon.aws.ec2_instance, google.cloud.gcp_compute.

# Installer une collection depuis Galaxy
ansible-galaxy collection install community.postgresql

# Installer depuis un fichier requirements
ansible-galaxy collection install -r requirements.yml
# requirements.yml
collections:
  - name: community.postgresql
    version: ">=3.0.0"
  - name: amazon.aws
    version: ">=7.0.0"

Détail dans le chapitre Collections.


Facts

Les facts sont des variables collectees automatiquement par le module ansible.builtin.setup au début de chaque play. Ils représentent l'état réel de la machine cible : système d'exploitation, interfaces réseau, mémoire, CPU, etc.

Facts automatiques courants

Variable Ansible Exemple de valeur
ansible_hostname web1
ansible_distribution Ubuntu
ansible_distribution_version 22.04
ansible_os_family Debian
ansible_default_ipv4.address 10.0.1.5
ansible_memtotal_mb 3951
ansible_processor_vcpus 2
# Voir tous les facts d'un hote
ansible web1.example.com -i inventory/hosts.yml -m ansible.builtin.setup

# Filtrer sur un sous-ensemble
ansible web1.example.com -i inventory/hosts.yml -m ansible.builtin.setup -a "filter=ansible_distribution*"

Facts locaux

Les facts locaux permettent à un hôte de s'auto-décrire avec des metadonnees métier. Ansible lit au démarrage tous les fichiers places dans /etc/ansible/facts.d/ dont l'extension est .fact. Ces fichiers peuvent être des scripts executables retournant du JSON, ou des fichiers JSON statiques.

# Exemple de script fact executable
# /etc/ansible/facts.d/application.fact
#!/bin/bash
echo '{"version": "1.0", "status": "ok", "env": "production"}'
# Rendre le script executable
chmod +x /etc/ansible/facts.d/application.fact

Les facts locaux sont accessibles via le préfixe ansible_local :

- name: Afficher la version de l'application
  ansible.builtin.debug:
    msg: "Version : {{ ansible_local.application.version }}"

- name: Deployer uniquement si l'application est active
  ansible.builtin.template:
    src: templates/config.j2
    dest: /etc/app/config.yml
  when: ansible_local.application.status == "ok"

Cette mecanique permet d'adapter le comportement d'un playbook sans modifier l'inventaire : chaque hôte exprime son état via ses facts locaux.

Désactiver la collecte de facts

Sur de grands inventaires, la phase de collecte des facts peut prendre plusieurs secondes par hôte. Quand les facts ne sont pas nécessaires (ex. tâches de copie simples), désactiver la collecte pour gagner du temps :

- name: Copie de configuration rapide
  hosts: webservers
  gather_facts: false

  tasks:
    - name: Copier le fichier
      ansible.builtin.copy:
        src: files/app.conf
        dest: /etc/app/app.conf

Voir aussi la mise en cache des facts dans la section ansible.cfg ci-dessous.


Variables et facts : la différence

Variables et facts sont tous deux accessibles dans les templates Jinja2 et les conditions when, mais ils ont des origines différentes.

Critère Variables Facts
Origine Declarees par l'opérateur Collectees dynamiquement sur l'hôte
Ou définies Inventaire, playbook, rôles, ligne de commande Module setup, scripts /etc/ansible/facts.d
Moment Avant l'exécution Au début du play (gather_facts)
Exemple app_version: "2.1", env: production ansible_distribution, ansible_hostname

Les variables expriment l'intention de l'opérateur : quelle version déployer, quel port écouter, quel environnement cibler. Elles sont statiques par nature et controlees en dehors des hôtes.

Les facts expriment la réalité de la machine : quel OS tourne, combien de mémoire est disponible, quelle adresse IP est configurée. Ils sont dynamiques et produits par l'hôte lui-même.

En pratique, les deux s'utilisent ensemble dans les conditions :

- name: Installer le paquet selon l'OS et l'environnement
  ansible.builtin.apt:
    name: "{{ app_package_name }}"
    state: present
  when:
    - ansible_os_family == "Debian"
    - env == "production"

ansible.cfg

Le fichier ansible.cfg centralise la configuration du comportement d'Ansible. Il est charge selon l'ordre de priorité suivant (le premier trouve est utilisé) :

  1. Variable d'environnement ANSIBLE_CONFIG
  2. ./ansible.cfg dans le répertoire courant
  3. ~/.ansible.cfg dans le home de l'utilisateur
  4. /etc/ansible/ansible.cfg (configuration globale)

La pratique recommandee est de placer ansible.cfg à la racine du dépôt, aux cotes de l'inventaire et des playbooks.

# ansible.cfg — configuration de reference
[defaults]
# Nombre d'hotes traites en parallele
forks = 20

# Format de sortie lisible
stdout_callback = yaml

# Inventaire par defaut
inventory = inventory/hosts.yml

# Repertoire temporaire sur les hotes distants
remote_tmp = /tmp/.ansible/tmp

# Mise en cache des facts (evite de les recollectera avec gather_facts a chaque run)
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts_cache
fact_caching_timeout = 3600

# Desactiver la verification de la cle SSH pour les nouveaux hotes (dev uniquement)
# host_key_checking = false

[privilege_escalation]
become = false
become_method = sudo
become_user = root

[ssh_connection]
# Multiplexage SSH pour reduire la latence
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
pipelining = true

Utiliser stdout_callback = yaml

Le callback yaml produit une sortie structurée et coloree, beaucoup plus lisible que le format par défaut pour les tâches retournant de longues sorties JSON. C'est le premier parametre a configurer sur un nouveau projet.

# Verifier quelle configuration est active
ansible --version | grep "config file"

# Afficher toutes les options de configuration et leur valeur effective
ansible-config dump --only-changed