Module 1 : Architecture & Premiers Pas
Objectif du Module
Comprendre l'architecture agentless d'Ansible, maîtriser les concepts fondamentaux (inventory, modules), et exécuter vos premières commandes ad-hoc pour gérer des serveurs à distance.
Durée : 2 heures
Introduction : Automatiser ou Disparaître
Le Paradoxe de l'Échelle
"Automate or die trying." — Loi de survie du DevOps
Le problème de l'administration manuelle :
Imaginez cette situation quotidienne :
# Lundi 09h : Votre manager demande
"Peux-tu installer Nginx sur nos 3 serveurs web ? Et mettre à jour OpenSSH sur les 5 serveurs de prod ? Ah, et vérifier l'espace disque partout."
# Votre approche manuelle (avant Ansible)
ssh web1.company.com
sudo apt update && sudo apt install nginx -y
exit
ssh web2.company.com
sudo apt update && sudo apt install nginx -y
exit
ssh web3.company.com
sudo apt update && sudo apt install nginx -y
exit
# Répéter 5 fois pour OpenSSH...
# Puis 8 fois pour vérifier l'espace disque...
# Total : 16 connexions SSH manuelles
# Temps : 45 minutes (si aucune erreur)
# Risque d'erreur humaine : ÉLEVÉ
Maintenant, imaginez gérer 100 serveurs. Ou 1000.
La Réalité du DevOps Moderne
Statistiques de l'industrie :
- Temps moyen d'un déploiement manuel sur 10 serveurs : 2-3 heures
- Temps avec Ansible : 5-10 minutes
- Taux d'erreur manuelle : 15-20% (oubli, typo, mauvais serveur)
- Taux d'erreur Ansible : <1% (reproductibilité garantie)
Ce que vous allez apprendre :
# Avec Ansible (APRÈS ce module)
ansible web -b -m apt -a "name=nginx state=present"
# 3 serveurs configurés en 10 secondes ✅
ansible all -b -m apt -a "name=openssh-server state=latest"
# 8 serveurs mis à jour en parallèle ✅
ansible all -m shell -a "df -h /"
# Espace disque vérifié partout instantanément ✅
# Total : 3 commandes, 30 secondes
Ansible = Multiplicateur de force pour les équipes Ops/DevOps.
Concept : L'Architecture Ansible
Architecture Agentless - La Force d'Ansible
Différence fondamentale avec les autres outils (Puppet, Chef, Salt) :
| Aspect | Ansible | Puppet/Chef/Salt |
|---|---|---|
| Agent sur serveurs cibles | ❌ NON (Agentless) | ✅ OUI (agent daemon) |
| Communication | SSH (Linux) / WinRM (Windows) | Agent → Master (port custom) |
| Installation cible | ❌ Rien à installer | ✅ Package agent + config |
| Maintenance | ❌ Aucune (pas d'agent) | ✅ Mise à jour agents |
| Overhead serveur | ❌ Minimal (SSH déjà présent) | ✅ CPU/RAM pour agent |
| Firewall | ✅ Port 22 SSH (déjà ouvert) | ⚠️ Ports customs (1024+) |
| Complexité | ✅ Simple | ⚠️ Infrastructure Master/Slave |
Pourquoi "Agentless" est révolutionnaire :
- Aucune préparation des serveurs : Si SSH fonctionne, Ansible fonctionne
- Pas de "chicken-and-egg" : Pas besoin d'installer un agent avant d'automatiser
- Sécurité native : Utilise SSH (déjà durci dans le Module Hardening Linux)
- Pas de maintenance supplémentaire : Aucun agent à mettre à jour
Architecture en Image :

Flux d'exécution typique :
- Control Node (votre machine) : Vous exécutez
ansible ... - Ansible lit l'Inventory : Liste des serveurs cibles
- Connexion SSH : Ansible se connecte aux serveurs (en parallèle)
- Transfert du module Python : Copie temporaire dans
/tmp/sur la cible - Exécution : Le module s'exécute (ex: installer nginx)
- Retour des résultats : SUCCESS (green) ou FAILED (red)
- Nettoyage : Suppression du fichier temporaire sur la cible
Prérequis des Managed Nodes :
- Python 3.x (ou Python 2.7 pour anciennes versions Ansible)
- SSH activé (ce que vous avez fait au Module Hardening Linux !)
- Utilisateur avec droits sudo (ex: alice)
C'est tout. Rien d'autre à installer.
Inventory - La Liste des Cibles
Qu'est-ce qu'un Inventory ?
L'inventory est le fichier qui définit sur quels serveurs Ansible va agir.
Formats supportés :
- INI (simple, recommandé pour débuter)
- YAML (plus structuré)
- Dynamic Inventory (scripts Python/JSON pour cloud AWS/Azure/GCP)
Exemple d'Inventory Statique (INI)

Fichier hosts.ini :
# Serveurs individuels (sans groupe)
mail.company.com
[web]
# Groupe "web" : serveurs web
web1.company.com
web2.company.com
web3.company.com
[db]
# Groupe "db" : bases de données
db1.company.com ansible_user=dbadmin
db2.company.com ansible_user=dbadmin
[monitoring]
# Serveur de monitoring
grafana.company.com ansible_port=2222
[production:children]
# Groupe de groupes (meta-groupe)
web
db
monitoring
Syntaxe des variables d'inventory :
ansible_user: Utilisateur SSH à utiliser (par défaut: utilisateur courant)ansible_port: Port SSH (par défaut: 22)ansible_host: IP réelle si le nom est un aliasansible_python_interpreter: Chemin Python sur la cible
Exemple avec variables :
[web]
webserver1 ansible_host=192.168.1.10 ansible_user=deploy ansible_port=2222
webserver2 ansible_host=192.168.1.11 ansible_user=deploy
Groupes Spéciaux Ansible
all: TOUS les serveurs de l'inventory (implicite)ungrouped: Serveurs sans groupe explicite
Exemple de ciblage :
ansible all -m ping # Tous les serveurs
ansible web -m ping # Uniquement groupe "web"
ansible db -m ping # Uniquement groupe "db"
ansible production -m ping # Tous les groupes dans "production" (web+db+monitoring)
Inventory Dynamique (Mention)
Pour les infrastructures cloud :
Au lieu d'un fichier statique, un script interroge l'API du cloud provider et génère l'inventory en temps réel.
Exemples :
- AWS EC2 :
aws_ec2.yml(plugin officiel) - Azure :
azure_rm.yml - GCP :
gcp_compute.yml - VMware vSphere :
vmware_vm_inventory.yml
Avantage : Les serveurs ajoutés/supprimés dans le cloud sont automatiquement pris en compte.
Note : Nous verrons les inventaires dynamiques dans un module avancé. Pour débuter, l'inventory statique est parfait.
Modules - Les Outils de la Boîte
Qu'est-ce qu'un Module Ansible ?
Un module est une unité de travail réutilisable : installer un package, copier un fichier, redémarrer un service, etc.
Ansible inclut 3000+ modules couvrant tous les cas d'usage.
Modules Essentiels (Top 10)
| Module | Fonction | Exemple |
|---|---|---|
ping |
Tester la connectivité | ansible all -m ping |
shell |
Exécuter une commande shell | ansible all -m shell -a "uptime" |
command |
Exécuter commande (sans shell) | ansible all -m command -a "ls -la" |
apt |
Gérer packages Debian/Ubuntu | ansible all -m apt -a "name=nginx state=present" |
yum / dnf |
Gérer packages RHEL/CentOS | ansible all -m yum -a "name=httpd state=present" |
copy |
Copier fichier local → distant | ansible all -m copy -a "src=file.txt dest=/tmp/" |
file |
Gérer fichiers/répertoires | ansible all -m file -a "path=/tmp/test state=directory" |
service / systemd |
Gérer services | ansible all -m service -a "name=nginx state=started" |
user |
Gérer utilisateurs | ansible all -m user -a "name=alice state=present" |
template |
Déployer template Jinja2 | ansible all -m template -a "src=nginx.j2 dest=/etc/nginx/nginx.conf" |
Idempotence - Le Superpouvoir des Modules
Définition : Un module idempotent peut être exécuté plusieurs fois sans effet secondaire si l'état cible est déjà atteint.
Exemple avec le module apt :
# Première exécution
ansible web -b -m apt -a "name=nginx state=present"
# Résultat : CHANGED (nginx installé)
# Deuxième exécution (nginx déjà installé)
ansible web -b -m apt -a "name=nginx state=present"
# Résultat : SUCCESS (OK, déjà installé, rien à faire)
Avantage :
- ✅ Pas de double installation
- ✅ Pas d'erreur si déjà fait
- ✅ Sûr de ré-exécuter (convergence vers état désiré)
Contre-exemple avec shell (NON idempotent) :
# Première exécution
ansible all -m shell -a "echo 'test' >> /tmp/file.txt"
# Résultat : CHANGED (ligne ajoutée)
# Deuxième exécution
ansible all -m shell -a "echo 'test' >> /tmp/file.txt"
# Résultat : CHANGED (ligne ajoutée ENCORE → doublon!)
Règle d'or : Préférer les modules dédiés (apt, copy, service) au module shell pour garantir l'idempotence.
Pratique : La CLI Ad-Hoc
Installation d'Ansible
Prérequis :
- Python 3.8+ installé
- Pip (gestionnaire de packages Python)
Installation via pip (recommandé) :
# Installer Ansible
pip install ansible
# Vérifier l'installation
ansible --version
# ansible [core 2.16.0]
# config file = None
# python version = 3.11.0
OU via package manager :
Vérification :
Configuration de l'Inventory
Créer un répertoire de travail :
Créer un fichier inventory simple (hosts.ini) :
Contenu pour un lab local (simulation avec localhost) :
[local]
localhost ansible_connection=local
[web]
web1 ansible_host=localhost ansible_connection=local
web2 ansible_host=localhost ansible_connection=local
[db]
database ansible_host=localhost ansible_connection=local
Explication :
ansible_connection=local: Ne pas utiliser SSH, exécuter en local (simulation)- En production, vous utiliseriez de vraies IPs/hostnames
Le Ping - Le "Hello World" d'Ansible
Commande :
Décomposition :
ansible: Commande ad-hocall: Cible tous les serveurs de l'inventory-m ping: Utilise le moduleping-i hosts.ini: Chemin vers l'inventory
Sortie attendue :
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
web1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
web2 | SUCCESS => {
"changed": false,
"ping": "pong"
}
database | SUCCESS => {
"changed": false,
"ping": "pong"
}
Interprétation :
- ✅ SUCCESS : Connectivité OK
- "changed": false : Rien n'a été modifié (ping est une vérification)
- "ping": "pong" : Réponse du module
Si vous voyez ça, Ansible fonctionne ! 🎉
Exécuter des Commandes Ad-Hoc
1. Vérifier l'Uptime
Sortie :
localhost | CHANGED | rc=0 >>
10:23:45 up 2 days, 3:14, 1 user, load average: 0.52, 0.58, 0.59
web1 | CHANGED | rc=0 >>
10:23:45 up 2 days, 3:14, 1 user, load average: 0.52, 0.58, 0.59
2. Vérifier l'Espace Disque
Sortie :
localhost | CHANGED | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 28G 20G 59% /
3. Lister les Utilisateurs Connectés
4. Créer un Fichier (Module file)
Sortie :
Vérification :
5. Installer un Package (Nécessite sudo)
Options :
-b: Become (utiliser sudo)name=htop: Package à installerstate=present: S'assurer qu'il est installé
Note : En local, cela installera htop sur votre machine.
Options Importantes des Commandes Ad-Hoc
| Option | Fonction | Exemple |
|---|---|---|
-i |
Spécifier l'inventory | -i hosts.ini |
-m |
Spécifier le module | -m ping |
-a |
Arguments du module | -a "name=nginx" |
-b |
Become (sudo) | -b |
--become-user |
Devenir un utilisateur spécifique | --become-user=postgres |
-u |
Utilisateur SSH | -u alice |
-k |
Demander le mot de passe SSH | -k |
-K |
Demander le mot de passe sudo | -K |
--limit |
Limiter à certains hosts | --limit web1 |
-v, -vv, -vvv |
Verbosité (debug) | -vvv |
Exemples d'utilisation :
# Installer nginx sur le groupe web avec sudo
ansible web -b -m apt -a "name=nginx state=present" -i hosts.ini
# Redémarrer nginx (en tant qu'utilisateur alice via sudo)
ansible web -b -u alice -m service -a "name=nginx state=restarted" -i hosts.ini
# Copier un fichier sur database uniquement
ansible database -m copy -a "src=backup.sql dest=/tmp/" --limit database -i hosts.ini
# Debug mode (voir les détails SSH)
ansible all -m ping -i hosts.ini -vvv
Exercice : Hello Ansible
Scénario
Vous allez créer un lab Ansible minimal pour gérer 2 "serveurs" simulés :
- Groupe
web: 2 serveurs web (web1, web2) - Groupe
db: 1 serveur de base de données (database)
Simulation : Tous pointent vers localhost (votre machine) pour faciliter le lab.
Objectif : Maîtriser l'inventory, la configuration Ansible, et les commandes ad-hoc.
Étapes de l'Exercice
Étape 1 : Créer l'Inventory
Fichier inventory.ini :
Créez ce fichier avec le contenu suivant :
[web]
web1 ansible_host=localhost ansible_connection=local
web2 ansible_host=localhost ansible_connection=local
[db]
database ansible_host=localhost ansible_connection=local
[all:vars]
ansible_python_interpreter=/usr/bin/python3
Explication :
[web]: Groupe de serveurs web[db]: Groupe de base de données[all:vars]: Variables appliquées à tous les hosts (ici, l'interpréteur Python)
Étape 2 : Configurer ansible.cfg
Pourquoi ?
Par défaut, Ansible vérifie les clés SSH des hosts (host key checking). En lab local, cela génère des erreurs. On le désactive.
Fichier ansible.cfg :
[defaults]
inventory = inventory.ini
host_key_checking = False
deprecation_warnings = False
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
Explication :
inventory = inventory.ini: Inventory par défaut (plus besoin de-i)host_key_checking = False: Désactiver vérification clés SSH (LAB UNIQUEMENT)become = True: Utiliser sudo par défautbecome_ask_pass = False: Ne pas demander le mot de passe sudo (si NOPASSWD configuré)
⚠️ IMPORTANT : En production, ne jamais désactiver host_key_checking (risque MITM).
Étape 3 : Tester la Connectivité
Ping le groupe web :
Résultat attendu :
web1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
web2 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Ping TOUS les serveurs :
Résultat attendu :
Étape 4 : Vérifier l'Espace Disque
Commande ad-hoc pour vérifier / sur tous les serveurs :
OU avec le module command :
Résultat attendu :
web1 | CHANGED | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 28G 20G 59% /
web2 | CHANGED | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 28G 20G 59% /
database | CHANGED | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 28G 20G 59% /
Étape 5 : Vérifier l'Uptime
Étape 6 : Créer un Fichier de Test
Créer /tmp/hello-ansible.txt sur le groupe web uniquement :
Vérifier la création :
Étape 7 : Installer un Package (Bonus)
Installer htop sur le groupe db :
Vérifier l'installation :
Questions de Validation
- Quelle est la différence entre
ansible all -m pingetping google.com? - Pourquoi désactive-t-on
host_key_checkingen lab (et pourquoi c'est dangereux en production) ? - Quelle est la différence entre le module
shellet le modulecommand? - Que se passe-t-il si on exécute
ansible web -m apt -a "name=nginx state=present"deux fois ?
Solution
Solution Complète - Hello Ansible
Fichiers de Configuration
1. Fichier inventory.ini :
[web]
web1 ansible_host=localhost ansible_connection=local
web2 ansible_host=localhost ansible_connection=local
[db]
database ansible_host=localhost ansible_connection=local
[all:vars]
ansible_python_interpreter=/usr/bin/python3
2. Fichier ansible.cfg :
[defaults]
inventory = inventory.ini
host_key_checking = False
deprecation_warnings = False
stdout_callback = yaml
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
Commandes Exécutées
Étape 3 : Ping
Sortie attendue :
Étape 4 : Vérifier l'Espace Disque
Sortie attendue :
web1:
changed: true
cmd: df -h /
rc: 0
stdout: |-
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 28G 20G 59% /
Étape 5 : Vérifier l'Uptime
Sortie attendue :
web1:
changed: true
cmd: uptime
stdout: ' 10:45:23 up 2 days, 3:36, 1 user, load average: 0.45, 0.50, 0.52'
Étape 6 : Créer Fichier de Test
Sortie attendue :
Vérification :
Étape 7 : Installer Package
Sortie attendue (première exécution) :
database:
changed: true
stderr: ''
stdout: |-
Reading package lists...
Building dependency tree...
The following NEW packages will be installed:
htop
Sortie attendue (deuxième exécution - idempotence) :
Réponses aux Questions de Validation
1. Différence entre ansible all -m ping et ping google.com ?
ping google.com: Ping ICMP réseau (teste connectivité IP)ansible all -m ping: Module Ansible qui :- Teste connectivité SSH
- Vérifie que Python fonctionne sur la cible
- Valide que Ansible peut exécuter des modules
- Ce ne sont PAS la même chose !
2. Pourquoi désactiver host_key_checking en lab ?
En lab : - Les "serveurs" sont simulés (localhost) - Pas de vraies clés SSH à valider - Évite les erreurs lors des tests rapides
Pourquoi c'est DANGEREUX en production : - Désactiver cette vérification expose aux attaques Man-in-the-Middle (MITM) - Un attaquant pourrait intercepter la connexion SSH - EN PRODUCTION : TOUJOURS LAISSER ACTIVÉ
3. Différence entre shell et command ?
| Aspect | shell |
command |
|---|---|---|
| Interpréteur | Utilise /bin/sh |
Exécute directement |
| Variables shell | ✅ Supportées ($HOME, ~, etc.) |
❌ Non supportées |
| Pipes/Redirections | ✅ Supportés (\|, >, <) |
❌ Non supportés |
| Sécurité | ⚠️ Risque injection | ✅ Plus sûr |
| Performance | ⚠️ Légèrement plus lent | ✅ Plus rapide |
Exemples :
# ✅ OK avec shell
ansible all -m shell -a "echo $HOME"
# ❌ KO avec command (pas de variable shell)
ansible all -m command -a "echo $HOME"
# Résultat : "$HOME" (littéral)
# ✅ OK avec shell (pipe)
ansible all -m shell -a "cat /etc/passwd | grep root"
# ❌ KO avec command (pas de pipe)
ansible all -m command -a "cat /etc/passwd | grep root"
# Résultat : Erreur
Règle : Préférer command par défaut (sécurité), utiliser shell uniquement si nécessaire.
4. Exécuter ansible web -m apt -a "name=nginx state=present" deux fois ?
Première exécution :
→ Nginx installé, état CHANGED (modifié)
Deuxième exécution :
→ Nginx déjà présent, état SUCCESS mais changed: false
C'est l'idempotence ! Le module détecte que l'état désiré est déjà atteint et ne fait rien.
Structure Finale du Lab
~/ansible-lab/
├── inventory.ini ← Liste des serveurs
├── ansible.cfg ← Configuration Ansible
└── /tmp/hello-ansible.txt ← Fichier créé par l'exercice
Commandes de Nettoyage
Conclusion du Module
Ce que Vous Avez Appris
✅ Architecture Agentless : Ansible utilise SSH, aucun agent à installer sur les cibles
✅ Inventory : Définir des groupes de serveurs (statique INI/YAML, dynamique pour cloud)
✅ Modules : Unités de travail réutilisables (ping, shell, apt, copy, service...)
✅ Idempotence : Les modules garantissent la convergence vers l'état désiré sans effet secondaire
✅ CLI Ad-Hoc : Exécuter des commandes rapides sans écrire de playbook
✅ Configuration : ansible.cfg pour personnaliser le comportement
Commandes Clés à Retenir
# Installation
pip install ansible
# Ping tous les serveurs
ansible all -m ping -i hosts.ini
# Exécuter une commande shell
ansible all -m shell -a "uptime" -i hosts.ini
# Installer un package avec sudo
ansible web -b -m apt -a "name=nginx state=present"
# Copier un fichier
ansible all -m copy -a "src=file.txt dest=/tmp/"
# Vérifier l'inventory
ansible-inventory --list -i hosts.ini
# Mode debug
ansible all -m ping -vvv
Différence Shell vs Command vs Module Dédié
| Besoin | ❌ Mauvais | ✅ Bon |
|---|---|---|
| Installer nginx | shell: apt install nginx -y |
apt: name=nginx state=present |
| Créer fichier | shell: touch /tmp/file |
file: path=/tmp/file state=touch |
| Redémarrer service | shell: systemctl restart nginx |
service: name=nginx state=restarted |
| Uptime | shell: uptime |
shell: uptime (OK, pas de module dédié) |
Règle d'or : Toujours chercher un module dédié avant d'utiliser shell.
Prochaines Étapes
Ce module couvre les commandes ad-hoc. Limites :
- ❌ Pas de réutilisabilité (commandes à retaper)
- ❌ Pas de gestion de l'ordre d'exécution complexe
- ❌ Pas de conditionnelles/boucles
Module 2 : Playbooks résoudra ces limites avec l'Infrastructure as Code.
Ressources Complémentaires
Documentation officielle :
Bonnes pratiques :
- Toujours utiliser un inventory explicite (ne jamais modifier
/etc/ansible/hosts) - Préférer les modules dédiés à
shell/command - Utiliser
--check(dry-run) avant exécution critique - Activer
host_key_checkingen production - Documenter vos inventories (commentaires)
Félicitations ! Vous maîtrisez les fondamentaux d'Ansible et pouvez gérer des serveurs avec des commandes ad-hoc. 🎉
Prochaine étape : Module 2 - Playbooks pour automatiser des workflows complets !
Navigation
| ← Programme | Module 2 : Playbooks - L'Art de l'Aut... → |