Tom Daluzeau
← Parcours Ansible
Ansible · leçon 1 / 1Ansible12 minTerminée

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.

Machine de contrôle inventory.ini site.yml Ansible installé ici aucun agent sur les serveurs SSH SSH linux (groupe de groupes) [webservers] web1 web2 [db_servers] db1
Ansible ne tourne que sur ta machine : il pilote les groupes de l'inventaire par SSH. Le groupe all contient les trois hôtes.

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 mettre webservers à 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
Un play : quelles machines, quels droits, quelles tâches hosts: webservers le groupe visé dans l'inventaire become: true tâches lancées en root, comme sudo tasks : jouées dans l'ordre, de haut en bas apt : name=nginx state=present template : src=… dest=… service : name=nginx state=started notify handlers : Recharger nginx, joué à la fin si notifié
Le play choisit les machines et les droits ; chaque tâche appelle un module ; notify relie une tâche à un handler.

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 .j2 car 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 template porte notify: Recharger nginx. Le texte doit être exactement le name du handler.
  • Si la tâche modifie le fichier, elle renvoie changed et 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.

Tâche template Fichier modifié ? oui : changed il est notifié Handler joué après les tâches, une seule fois non : ok, pas de notification nginx n'est pas rechargé
Le handler ne dépend que d'une chose : la tâche qui le notifie a-t-elle renvoyé changed ?

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 comme ansible_user et ansible_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.
  • apt avec state: present, service avec state: started, template avec src et dest.
  • notify appelle 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.yml pour lancer, --check pour simuler, ansible all -i inventory.ini -m ping pour tester la connexion.

Entraînement

12 questions, dont 4 à compléter. Tu réponds, on passe à la suivante. La note arrive à la fin.

Cartes · 8

Réviser les cartes ici

Espace : retourner