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
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 :
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"}'
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é) :
- Variable d'environnement
ANSIBLE_CONFIG ./ansible.cfgdans le répertoire courant~/.ansible.cfgdans le home de l'utilisateur/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.