Ansible est un outil d'automatisation open source maintenu par Red Hat. Il permet de configurer des systèmes, déployer des logiciels et orchestrer des workflows complexes. Son architecture agentless (sans agent) le distingue de Puppet ou Chef : Ansible se connecte aux machines cibles via SSH et exécute les tâches décrites en YAML. Aucune installation n'est requise sur les nœuds gérés, ce qui simplifie considérablement la mise en place et la maintenance.
Prérequis
Avant de commencer avec Ansible, assurez-vous de disposer des éléments suivants :
- Machine de contrôle : Un poste Linux ou macOS avec Python 3.8+ installé. Windows n'est pas supporté comme contrôleur mais fonctionne comme nœud cible via WinRM.
- Accès SSH : Connexion SSH configurée vers les machines cibles, idéalement avec des clés SSH (pas de mot de passe).
- Privilèges : Un utilisateur avec accès sudo sur les machines cibles pour les tâches d'administration.
- Python sur les cibles : Python 3 installe sur les machines gérées (present par défaut sur la plupart des distributions Linux).
# Vérifier Python sur la machine de controle
python3 --version
# Générer une cle SSH si nécessaire
ssh-keygen -t ed25519 -C "ansible-controller"
# Copier la cle sur les machines cibles
ssh-copy-id user@serveur-cible
Installation multi-OS
Ansible s'installe uniquement sur la machine de contrôle. Voici les méthodes d'installation selon votre système.
Ubuntu / Debian
# Ajouter le PPA officiel Ansible
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible
# Vérifier l'installation
ansible --version
CentOS / RHEL
# Activer le depot EPEL
sudo dnf install -y epel-release
sudo dnf install -y ansible
# Sur RHEL 8+ avec subscription
sudo subscription-manager repos --enable ansible-automation-platform
sudo dnf install -y ansible-core
Installation via pip (toutes plateformes)
# Installation dans un virtualenv (recommande)
python3 -m venv ~/ansible-venv
source ~/ansible-venv/bin/activate
pip install ansible
# Ou installation globale
pip3 install ansible
# Installer une version spécifique
pip3 install ansible-core==2.16.0
Configuration de base
La configuration d'Ansible repose sur deux fichiers principaux : le fichier de configuration ansible.cfg et l'inventaire des hôtes.
ansible.cfg
Ansible cherche sa configuration dans cet ordre : variable d'environnement ANSIBLE_CONFIG, ./ansible.cfg (répertoire courant), ~/.ansible.cfg, puis /etc/ansible/ansible.cfg. Placez votre fichier à la racine de votre projet.
# ansible.cfg
[defaults]
inventory = ./inventory/hosts.ini
remote_user = deploy
host_key_checking = False
retry_files_enabled = False
forks = 10
timeout = 30
log_path = ./ansible.log
[privilège_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
Inventaire statique
L'inventaire définit les machines gérées par Ansible. Le format INI est le plus courant :
# inventory/hosts.ini
[webservers]
web1.example.com ansible_host=192.168.1.10
web2.example.com ansible_host=192.168.1.11
[databases]
db1.example.com ansible_host=192.168.1.20
db2.example.com ansible_host=192.168.1.21
[monitoring]
grafana.example.com ansible_host=192.168.1.30
# Groupe de groupes
[production:children]
webservers
databases
# Variables pour tout le groupe
[webservers:vars]
http_port=80
ansible_python_interpreter=/usr/bin/python3
Inventaire en YAML
# inventory/hosts.yml
all:
children:
webservers:
hosts:
web1.example.com:
ansible_host: 192.168.1.10
web2.example.com:
ansible_host: 192.168.1.11
vars:
http_port: 80
databases:
hosts:
db1.example.com:
ansible_host: 192.168.1.20
Inventaire avancé
Pour les environnements complexes, Ansible offre des fonctionnalités d'inventaire avancées.
Variables de groupe et d'hôte
Organisez les variables dans des fichiers séparés selon la convention suivante :
# Structure des variables d'inventaire
inventory/
hosts.ini
group_vars/
all.yml # Variables globales
webservers.yml # Variables du groupe webservers
databases.yml # Variables du groupe databases
host_vars/
web1.example.com.yml # Variables spécifiques a web1
# inventory/group_vars/webservers.yml
---
nginx_worker_processes: auto
nginx_worker_connections: 1024
ssl_certificate_path: /etc/ssl/certs
deploy_user: www-data
Inventaire dynamique
Pour les environnements cloud, utilisez un inventaire dynamique qui interroge l'API du provider :
# inventory/aws_ec2.yml
---
plugin: amazon.aws.aws_ec2
regions:
- eu-west-1
- eu-west-3
filters:
tag:Environment: production
keyed_groups:
- key: tags.Role
prefix: role
- key: placement.availability_zone
prefix: az
compose:
ansible_host: private_ip_address
# Tester un inventaire dynamique
ansible-inventory -i inventory/aws_ec2.yml --list
ansible-inventory -i inventory/aws_ec2.yml --graph
Modules essentiels
Ansible dispose de milliers de modules. Voici les plus utilisés au quotidien.
Gestion des paquets : apt et yum
- name: Installer des paquets (Debian/Ubuntu)
ansible.builtin.apt:
name:
- nginx
- curl
- htop
state: present
update_cache: yes
cache_valid_time: 3600
- name: Installer des paquets (CentOS/RHEL)
ansible.builtin.yum:
name:
- httpd
- vim
state: latest
Gestion des services : service
- name: Demarrer et activer nginx
ansible.builtin.service:
name: nginx
state: started
enabled: yes
- name: Redémarrer un service
ansible.builtin.service:
name: nginx
state: restarted
Gestion des fichiers : copy, template, file
- name: Copier un fichier de configuration
ansible.builtin.copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: "0644"
backup: yes
- name: Déployer un template Jinja2
ansible.builtin.template:
src: templates/vhost.conf.j2
dest: "/etc/nginx/sites-available/{{ domain }}.conf"
owner: root
mode: "0644"
- name: Creer un repertoire
ansible.builtin.file:
path: /var/www/app
state: directory
owner: www-data
group: www-data
mode: "0755"
recurse: yes
Exécution de commandes : shell et command
- name: Executer une commande simple
ansible.builtin.command:
cmd: whoami
register: current_user
- name: Commande shell avec pipe
ansible.builtin.shell:
cmd: "df -h | grep /dev/sda1"
register: disk_usage
changed_when: false
- name: Afficher le resultat
ansible.builtin.debug:
msg: "Espace disque : {{ disk_usage.stdout }}"
Gestion des utilisateurs : user
- name: Creer un utilisateur applicatif
ansible.builtin.user:
name: deploy
shell: /bin/bash
groups: sudo,docker
append: yes
create_home: yes
generate_ssh_key: yes
ssh_key_bits: 4096
Playbooks
Les playbooks sont le cœur d'Ansible. Ils décrivent l'état desire de vos systèmes dans des fichiers YAML.
Syntaxe YAML de base
---
# playbook-webserver.yml
- name: Configurer les serveurs web
hosts: webservers
become: yes
vars:
app_name: monapp
app_port: 8080
tasks:
- name: Mettre à jour le cache apt
ansible.builtin.apt:
update_cache: yes
cache_valid_time: 3600
- name: Installer les dépendances
ansible.builtin.apt:
name: "{{ item }}"
state: present
loop:
- nginx
- python3-pip
- supervisor
- name: Déployer la configuration nginx
ansible.builtin.template:
src: templates/nginx-app.conf.j2
dest: "/etc/nginx/sites-available/{{ app_name }}.conf"
notify: Recharger nginx
handlers:
- name: Recharger nginx
ansible.builtin.service:
name: nginx
state: reloaded
Handlers
Les handlers sont des tâches déclenchées uniquement quand une autre tâche les notifie via notify. Ils s'executent une seule fois à la fin du play, même s'ils sont notifies plusieurs fois :
handlers:
- name: Redémarrer nginx
ansible.builtin.service:
name: nginx
state: restarted
- name: Recharger systemd
ansible.builtin.systemd:
daemon_reload: yes
Conditions
- name: Installer sur Debian uniquement
ansible.builtin.apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
- name: Configurer le firewall si actif
ansible.builtin.ufw:
rule: allow
port: "{{ http_port }}"
when:
- firewall_enabled | default(false)
- http_port is defined
Boucles
- name: Creer plusieurs utilisateurs
ansible.builtin.user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
shell: /bin/bash
loop:
- { name: "alice", groups: "sudo" }
- { name: "bob", groups: "docker" }
- { name: "charlie", groups: "sudo,docker" }
- name: Copier plusieurs fichiers
ansible.builtin.copy:
src: "files/{{ item }}"
dest: "/etc/app/{{ item }}"
loop:
- app.conf
- db.conf
- logging.conf
Tags
Les tags permettent d'exécuter selectivement certaines tâches d'un playbook :
- name: Installer nginx
ansible.builtin.apt:
name: nginx
state: present
tags:
- install
- nginx
- name: Configurer nginx
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
tags:
- configure
- nginx
# Executer uniquement les taches taguees "configure"
ansible-playbook site.yml --tags configure
# Exclure les taches taguees "install"
ansible-playbook site.yml --skip-tags install
# Lister les tags disponibles
ansible-playbook site.yml --list-tags
Variables et templates
Types de variables
Ansible propose plusieurs niveaux de variables avec un ordre de precedence precis. Les plus courants :
# Variables dans le playbook
vars:
app_name: monapp
app_port: 8080
db_config:
host: localhost
port: 5432
name: mydb
# Variables depuis un fichier externe
vars_files:
- vars/common.yml
- "vars/{{ env }}.yml"
Facts Ansible
Ansible collecte automatiquement des informations (facts) sur les machines cibles. Utilisez-les dans vos playbooks :
- name: Afficher les facts système
ansible.builtin.debug:
msg: |
OS: {{ ansible_distribution }} {{ ansible_distribution_version }}
IP: {{ ansible_default_ipv4.address }}
RAM: {{ ansible_memtotal_mb }} MB
CPU: {{ ansible_processor_cores }} cores
# Consulter tous les facts d'un hote
ansible web1.example.com -m setup
# Filtrer les facts
ansible web1.example.com -m setup -a "filter=ansible_distribution*"
Templates Jinja2
Les templates Jinja2 permettent de générer des fichiers de configuration dynamiques :
# templates/nginx-vhost.conf.j2
server {
listen {{ http_port | default(80) }};
server_name {{ domain }};
root /var/www/{{ app_name }};
{% if ssl_enabled | default(false) %}
listen 443 ssl;
ssl_certificate {{ ssl_cert_path }};
ssl_certificate_key {{ ssl_key_path }};
{% endif %}
{% for location in app_locations | default([]) %}
location {{ location.path }} {
proxy_pass http://127.0.0.1:{{ location.port }};
proxy_set_header Host $host;
}
{% endfor %}
access_log /var/log/nginx/{{ domain }}_access.log;
error_log /var/log/nginx/{{ domain }}_error.log;
}
Roles
Les rôles structurent votre code Ansible en composants réutilisables et modulaires.
Structure d'un rôle
# Structure standard d'un role
roles/
nginx/
tasks/
main.yml # Taches principales
handlers/
main.yml # Handlers du role
templates/
nginx.conf.j2 # Templates Jinja2
files/
index.html # Fichiers statiques
vars/
main.yml # Variables du role (haute priorite)
defaults/
main.yml # Valeurs par défaut (basse priorite)
meta/
main.yml # Metadonnees et dépendances
Créer un rôle
# Générer la structure avec ansible-galaxy
ansible-galaxy init roles/nginx
# Ou creer manuellement
mkdir -p roles/nginx/{tasks,handlers,templates,files,vars,defaults,meta}
# roles/nginx/tasks/main.yml
---
- name: Installer nginx
ansible.builtin.apt:
name: nginx
state: present
- name: Déployer la configuration
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Redémarrer nginx
- name: Activer le service
ansible.builtin.service:
name: nginx
state: started
enabled: yes
# roles/nginx/defaults/main.yml
---
nginx_worker_processes: auto
nginx_worker_connections: 1024
nginx_keepalive_timeout: 65
# Utiliser un role dans un playbook
---
- hosts: webservers
become: yes
roles:
- role: nginx
vars:
nginx_worker_connections: 2048
- role: app
- role: monitoring
Ansible Galaxy
Galaxy est le dépôt communautaire de rôles Ansible. Utilisez-le pour trouver et partager des rôles :
# Chercher un role
ansible-galaxy search nginx --platforms Ubuntu
# Installer un role depuis Galaxy
ansible-galaxy install geerlingguy.nginx
# Installer des roles depuis un fichier requirements
ansible-galaxy install -r requirements.yml
# requirements.yml
---
roles:
- name: geerlingguy.nginx
version: "3.1.0"
- name: geerlingguy.postgresql
version: "3.4.0"
collections:
- name: community.general
version: ">=5.0.0"
Ansible Vault
Vault permet de chiffrer les données sensibles (mots de passe, clés API, certificats) directement dans vos fichiers Ansible.
# Creer un fichier chiffre
ansible-vault create vars/secrets.yml
# Chiffrer un fichier existant
ansible-vault encrypt vars/production.yml
# Editer un fichier chiffre
ansible-vault edit vars/secrets.yml
# Dechiffrer un fichier
ansible-vault decrypt vars/secrets.yml
# Chiffrer une variable individuelle
ansible-vault encrypt_string "MonMotDePasse123" --name "db_password"
# vars/secrets.yml (contenu avant chiffrement)
---
db_password: "SuperSecret123"
api_key: "ak_live_xxxxxxxxxxxx"
ssl_private_key: |
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBg...
-----END PRIVATE KEY-----
# Executer un playbook avec Vault
ansible-playbook site.yml --ask-vault-pass
# Utiliser un fichier de mot de passe (recommandé en CI/CD)
ansible-playbook site.yml --vault-password-file ~/.vault_pass
# Plusieurs mots de passe Vault avec des identifiants
ansible-vault encrypt --vault-id prod@prompt vars/prod-secrets.yml
ansible-playbook site.yml --vault-id prod@~/.vault_pass_prod
Bonnes pratiques
Structure de projet
Adoptez une structure standardisee pour vos projets Ansible :
# Structure recommandee
ansible-project/
ansible.cfg
site.yml # Playbook principal
webservers.yml # Playbook par groupe
databases.yml
inventory/
production/
hosts.ini
group_vars/
all.yml
webservers.yml
host_vars/
web1.yml
staging/
hosts.ini
group_vars/
roles/
common/
nginx/
postgresql/
playbooks/ # Playbooks operationnels
deploy.yml
backup.yml
rollback.yml
Idempotence
Chaque tâche doit être idempotente : l'exécuter plusieurs fois produit le même resultat qu'une seule execution. Evitez les modules shell et command quand un module dédié existe.
# Mauvais : pas idempotent
- name: Creer le repertoire
ansible.builtin.shell: mkdir -p /var/www/app
# Bon : idempotent
- name: Creer le repertoire
ansible.builtin.file:
path: /var/www/app
state: directory
mode: "0755"
Conventions de nommage
- Noms de tâches descriptifs :
Installer les dépendances Pythonplutôt questep 1 - Variables en snake_case :
app_port,db_host - Roles nommes par fonction :
nginx,postgresql,monitoring - Utilisez les FQCN (Fully Qualified Collection Names) :
ansible.builtin.aptau lieu deapt
Troubleshooting
Module debug
- name: Afficher une variable
ansible.builtin.debug:
var: my_variable
- name: Afficher un message formate
ansible.builtin.debug:
msg: "L'utilisateur {{ user }} a ete cree sur {{ inventory_hostname }}"
- name: Capturer et afficher la sortie d'une commande
ansible.builtin.command: systemctl status nginx
register: nginx_status
changed_when: false
- name: Afficher le resultat
ansible.builtin.debug:
var: nginx_status.stdout_lines
Mode verbose
# Niveaux de verbosity
ansible-playbook site.yml -v # Sortie detaillee
ansible-playbook site.yml -vv # Plus de details
ansible-playbook site.yml -vvv # Debug connexion SSH
ansible-playbook site.yml -vvvv # Debug complet avec scripts
# Mode check (dry-run) avec diff
ansible-playbook site.yml --check --diff
# Limiter l'execution a un hote
ansible-playbook site.yml --limit web1.example.com
# Demarrer a une tache spécifique
ansible-playbook site.yml --start-at-task "Déployer la configuration"
# Executer etape par etape
ansible-playbook site.yml --step
Problèmes courants
- Permission denied : Vérifiez que
become: yesest défini et que l'utilisateur a les droits sudo sans mot de passe, ou utilisez--ask-become-pass. - Host unreachable : Testez la connectivité avec
ansible all -m ping. Vérifiez la configuration SSH et les cles. - Module not found : Installez la collection requise avec
ansible-galaxy collection install community.general. - Variable undefined : Utilisez le filtre
default()pour définir des valeurs par défaut :{{ var | default("fallback") }}. - Lenteur d'exécution : Activez le pipelining dans
ansible.cfg, augmentez les forks, et desactivez la collecte de facts si non nécessaire avecgather_facts: no.
Conclusion
Ansible est un outil puissant qui simplifie l'automatisation de l'infrastructure grâce à son approche agentless et à sa syntaxe YAML accessible. En maîtrisant les concepts présentés dans ce tutoriel (inventaires, modules, playbooks, rôles et Vault), vous disposez des bases solides pour automatiser la gestion de vos serveurs, standardiser vos déploiements et garantir la cohérence de votre infrastructure. Commencez par des playbooks simples, puis structurez progressivement votre code en rôles réutilisables. L'investissement initial est rapidement rentabilisé par le gain de temps et la réduction des erreurs humaines.
- Privilégiez les modules dédiés plutôt que shell/command pour garantir l'idempotence
- Structurez votre code en rôles dès que vous avez plus de 2-3 playbooks
- Chiffrez systematiquement les secrets avec Ansible Vault
- Testez toujours en mode --check --diff avant d'appliquer en production
- Versionnez l'ensemble de votre code Ansible avec Git
Commentaires