Ansible : inventaire et premier playbook
Tu sais expliquer ce qu'est Ansible, écrire un inventaire avec des groupes, lire et compléter un playbook qui installe et démarre nginx, et le lancer en vrai ou à blanc.
Mis à jour le
À recouper avec le cours. Cette leçon a été écrite à partir du plan du chapitre, avant relecture avec les supports. En cas de doute, le cours fait foi.
Pourquoi on voit ça
Configurer un serveur à la main, ça va. En configurer vingt, c’est long, et tu finis toujours par en oublier un ou par te tromper sur le douzième. Ansible règle ce problème : tu décris une fois, dans des fichiers texte, l’état que tu veux, et Ansible l’applique à toutes tes machines.
C’est un des outils centraux du DevOps, dans la famille de l’infrastructure as code : ta configuration devient du code, que tu peux relire, versionner dans Git et rejouer. Dans cette leçon, on suit un seul exemple du début à la fin : installer et démarrer nginx sur un groupe de serveurs web.
Ce qu’est Ansible
Trois idées à retenir.
- Sans agent. Tu installes Ansible sur ta machine, appelée machine de contrôle. Rien de spécifique à installer sur les serveurs : il leur faut seulement un accès SSH et Python.
- Par SSH. Ansible se connecte aux serveurs comme tu le ferais toi-même, y exécute ses instructions, puis se déconnecte.
- Idempotent. Tu ne décris pas des actions (« installe nginx »), tu décris un état (« nginx doit être présent »). Si l’état est déjà bon, Ansible ne touche à rien. Tu peux relancer dix fois : le résultat est le même.
L’idempotence, c’est comme un thermostat réglé sur 20 °C. S’il fait 17, il chauffe. S’il fait déjà 20, il ne fait rien. Tu peux appuyer dix fois sur « 20 », la pièce ne montera pas à 200.
Ansible a besoin de deux fichiers : l’inventaire (sur quelles machines ?) et le playbook (pour faire quoi ?).
L’inventaire : inventory.ini
L’inventaire est la liste de tes machines, rangées par groupes.
[webservers]
web1 ansible_host=192.168.56.11 ansible_user=deploy ansible_ssh_private_key_file=~/.ssh/id_ed25519
web2 ansible_host=192.168.56.12 ansible_user=deploy ansible_ssh_private_key_file=~/.ssh/id_ed25519
[db_servers]
db1 ansible_host=192.168.56.21 ansible_user=admin ansible_ssh_private_key_file=~/.ssh/id_ed25519
[linux:children]
webservers
db_servers
Comment le lire :
| Élément | Rôle |
|---|---|
[webservers] |
Un groupe. Les lignes en dessous sont ses hôtes |
web1 |
Le nom de l’hôte dans Ansible |
[linux:children] |
Un groupe de groupes : les lignes en dessous sont des noms de groupes |
ansible_host |
L’adresse à laquelle se connecter |
ansible_user |
Le compte utilisé pour la connexion SSH |
ansible_ssh_private_key_file |
Le chemin de la clé privée SSH |
Les variables d’hôte s’écrivent sur la même ligne que l’hôte, sous la forme nom=valeur, séparées par des espaces.
Ici, le groupe linux contient web1, web2 et db1. Il existe aussi un groupe automatique, all, qui contient tous les hôtes de l’inventaire.
Tester la connexion
Avant d’écrire un playbook, vérifie qu’Ansible arrive à joindre tes machines :
ansible all -i inventory.ini -m ping
all: la cible (tu peux mettrewebserversà la place) ;-i inventory.ini: l’inventaire à utiliser ;-m ping: le module à exécuter.
web1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Attention : ce n’est pas un ping réseau (ICMP). Le module ping vérifie qu’Ansible peut se connecter en SSH et exécuter du Python sur la machine. S’il répond pong, tout est prêt.
Le playbook : site.yml
Un playbook est un fichier YAML. Il contient un ou plusieurs plays. Un play associe un groupe de machines à une liste de tâches. Chaque tâche appelle un module.
---
- name: Installer et démarrer nginx
hosts: webservers
become: true
tasks:
- name: Installer le paquet nginx
ansible.builtin.apt:
name: nginx
state: present
- name: Déposer la configuration du site
ansible.builtin.template:
src: templates/monsite.conf.j2
dest: /etc/nginx/conf.d/monsite.conf
notify: Recharger nginx
- name: Démarrer nginx et l'activer au démarrage
ansible.builtin.service:
name: nginx
state: started
enabled: true
handlers:
- name: Recharger nginx
ansible.builtin.service:
name: nginx
state: reloaded
Les mots-clés du play
| Mot-clé | Rôle |
|---|---|
name |
Un titre lisible, affiché pendant l’exécution |
hosts |
Le groupe de l’inventaire visé |
become |
true = exécuter les tâches avec les droits d’administrateur (comme sudo) |
tasks |
La liste des tâches, jouées dans l’ordre, de haut en bas |
handlers |
Des tâches spéciales, jouées seulement si on les notifie |
Les trois modules
| Module | Ce qu’il fait | Paramètres utilisés |
|---|---|---|
ansible.builtin.apt |
Gère les paquets sur Debian et Ubuntu | name, state: present (installé) |
ansible.builtin.template |
Copie un fichier modèle vers le serveur, en remplaçant ses variables | src (le modèle, sur ta machine), dest (la destination, sur le serveur) |
ansible.builtin.service |
Gère un service | name, state: started (démarré), enabled: true (lancé au démarrage) |
ansible.builtin.apt est le nom complet du module : il fait partie de la collection ansible.builtin, fournie avec Ansible.
Remarque le vocabulaire de state : present, started. Ce sont des états, pas des ordres. C’est ce qui rend le playbook idempotent.
Contexte, pas à apprendre. Un fichier modèle porte l’extension
.j2car il est écrit en Jinja2 : on y place des variables entre doubles accolades, par exemple{{ ansible_hostname }}, qu’Ansible remplace par leur valeur pour chaque serveur.
notify et les handlers
Quand tu changes la configuration de nginx, il faut le recharger. Mais seulement si le fichier a vraiment changé. C’est le rôle du couple notify / handler.
- La tâche
templateportenotify: Recharger nginx. Le texte doit être exactement lenamedu handler. - Si la tâche modifie le fichier, elle renvoie
changedet notifie le handler. - Si le fichier était déjà identique, elle renvoie
ok: pas de notification. - Les handlers notifiés s’exécutent à la fin des tâches du play, et une seule fois, même si plusieurs tâches les ont notifiés.
L’image : une sonnette. La tâche appuie dessus seulement si elle a changé quelque chose. Le handler ne se déplace qu’à la fin, et une fois, peu importe le nombre de coups de sonnette.
Attention à l’indentation
En YAML, la structure vient de l’indentation, avec des espaces (jamais de tabulation). Les paramètres d’un module sont décalés sous le nom du module. notify, lui, est au niveau du nom du module : c’est un mot-clé de la tâche, pas un paramètre du module.
Lancer le playbook
ansible-playbook -i inventory.ini site.yml
À la fin, Ansible affiche un bilan par machine. Premier lancement :
PLAY RECAP
web1 : ok=5 changed=3 unreachable=0 failed=0
web2 : ok=5 changed=3 unreachable=0 failed=0
D’où viennent ces chiffres ? ok=5 compte la collecte d’informations qu’Ansible fait tout seul au début du play (Gathering Facts), les trois tâches et le handler. changed=3 : l’installation du paquet, le dépôt du fichier et le rechargement par le handler. La tâche service reste ok, car sur Debian et Ubuntu l’installation du paquet démarre déjà nginx.
Tu relances la même commande :
PLAY RECAP
web1 : ok=4 changed=0 unreachable=0 failed=0
web2 : ok=4 changed=0 unreachable=0 failed=0
changed=0 : tout était déjà dans le bon état, rien n’a été modifié. Et ok passe de 5 à 4 : le handler n’a pas été notifié, donc il n’a pas tourné. Voilà l’idempotence en pratique.
| Mot du bilan | Sens |
|---|---|
ok |
Tâches réussies (celles en changed comprises) |
changed |
Tâches qui ont modifié quelque chose |
unreachable |
Machine injoignable en SSH |
failed |
Tâches en erreur |
Simuler avant d’agir : --check
ansible-playbook -i inventory.ini site.yml --check
C’est une exécution à blanc : Ansible indique ce qu’il changerait, mais ne modifie rien. Un réflexe à prendre avant de lancer un playbook sur des serveurs importants.
À retenir
- Ansible automatise la configuration sans agent, par SSH. Il est idempotent : relancer ne change rien si l’état est déjà bon.
- Inventaire
inventory.ini: groupes entre crochets, groupe de groupes avec:children, variables d’hôte commeansible_useretansible_ssh_private_key_file. - Playbook YAML :
hosts(la cible),become(droits d’administrateur),tasks(jouées dans l’ordre), chaque tâche appelle un module. aptavecstate: present,serviceavecstate: started,templateavecsrcetdest.notifyappelle un handler par son nom ; le handler ne tourne que si la tâche a renvoyéchanged, à la fin des tâches, une seule fois.ansible-playbook -i inventory.ini site.ymlpour lancer,--checkpour simuler,ansible all -i inventory.ini -m pingpour tester la connexion.
Entraînement
12 questions, dont 4 à compléter. Tu réponds, on passe à la suivante. La note arrive à la fin.
Ta note
Cartes · 8
Réviser les cartes ici
Pourquoi