Polarys

Le faire une fois pour toutes vos machines : automatiser avec Ansible

Vous faites la même manipulation sur chaque serveur, un par un. Écrivez-la une seule fois, simulez-la, jouez-la partout, et rejouez-la sans rien casser.

Sommaire13

Le faire une fois pour toutes vos machines : automatiser avec Ansible

Vous avez trois serveurs. On vous demande d'installer fail2ban partout, parce qu'un audit l'a réclamé ou parce que les tentatives de connexion s'accumulent dans les journaux. Vous vous connectez au premier, vous installez, vous démarrez le service, vous vérifiez. Vous recommencez sur le deuxième. Sur le troisième, vous êtes déjà moins attentif : vous installez, et vous oubliez de l'activer au démarrage. Trois mois plus tard, ce serveur redémarre et fail2ban ne remonte pas. Personne ne s'en aperçoit.

Ce n'est pas un problème de sérieux. C'est un problème de méthode : une tâche faite à la main autant de fois qu'il y a de machines finit toujours par être faite légèrement différemment quelque part.

Ce guide règle exactement ça, sur un seul exemple mené jusqu'au bout. À la fin, cette installation sera décrite dans un fichier texte de quinze lignes, exécutée sur vos trois serveurs en une commande, et vous l'aurez relancée une seconde fois pour constater vous-même qu'elle n'a rien refait.

En clair

Vous décrivez l'état que vous voulez (« fail2ban installé, démarré, actif au redémarrage ») dans un fichier. Un outil se connecte à chaque machine, regarde si cet état est déjà là, et n'agit que sur ce qui manque. La machine qui est déjà conforme n'est pas touchée. C'est ce détail, et pas la connexion en masse, qui fait la différence avec un script.

Le préalable : se connecter sans taper de mot de passe

L'outil que nous allons utiliser, Ansible, ne s'installe pas sur vos serveurs. Il se connecte à eux en SSH (Secure Shell, le protocole d'administration à distance sous Linux), exactement comme vous le faites à la main. Il n'y a donc rien de nouveau à ouvrir, rien de nouveau à exposer.

Mais il se connecte à plusieurs machines d'affilée, sans personne devant le clavier. Cela impose une condition : l'accès par clé doit fonctionner. Si vos serveurs demandent encore un mot de passe, arrêtez-vous ici et réglez ce point d'abord, c'est le sujet du guide Configurer l'authentification SSH par clé. Le reste ne fonctionnera pas sans lui.

Vérification, depuis votre poste, pour chaque serveur :

ssh deploy@192.168.1.11 'hostname'

Si cette commande affiche le nom du serveur sans rien vous demander, vous êtes prêt. Sinon, le problème est là, pas dans Ansible.

Qui pilote, qui subit

graph LR
    P["Votre poste<br/>ansible installé ici<br/>inventaire + playbook"]
    P -- SSH --> W1["web01<br/>192.168.1.11"]
    P -- SSH --> W2["web02<br/>192.168.1.12"]
    P -- SSH --> D1["db01<br/>192.168.1.13"]
    W1 -. "état constaté" .-> P
    W2 -. "état constaté" .-> P
    D1 -. "état constaté" .-> P

Une seule machine porte Ansible : la vôtre. Les serveurs ne reçoivent aucun agent, aucun logiciel supplémentaire, aucun port ouvert. Ils répondent en SSH et c'est tout. Le trait en pointillé compte autant que l'autre : avant d'agir, Ansible demande à chaque machine dans quel état elle se trouve, et c'est cette réponse qui décide s'il fait quelque chose.

Installation sur votre poste, sous Debian ou Ubuntu :

sudo apt update && sudo apt install -y ansible
ansible --version

La liste des machines

Ansible a besoin de savoir à qui parler. Cette liste s'appelle l'inventaire : un simple fichier texte. Créez inventaire.ini dans un dossier de travail :

[serveurs]
web01 ansible_host=192.168.1.11
web02 ansible_host=192.168.1.12
db01 ansible_host=192.168.1.13

[serveurs:vars]
ansible_user=deploy

Trois machines, désignées par un nom court et leur adresse IP (Internet Protocol, l'adresse de la machine sur le réseau), regroupées sous une étiquette commune : serveurs. Cette étiquette est ce que vous viserez ensuite, au lieu de viser les machines une par une. ansible_user indique avec quel compte se connecter, le même partout ici.

Premier contact, avant toute modification :

ansible serveurs -i inventaire.ini -m ansible.builtin.ping

Trois réponses SUCCESS attendues. Une machine qui ne répond pas vous le dit maintenant, en dix secondes, plutôt qu'au milieu d'une opération.

Écrire la tâche une fois

Le fichier qui décrit le travail à faire s'appelle un playbook. Il est écrit en YAML, un format texte où l'indentation porte le sens : deux espaces de trop ou de trop peu changent la structure, et c'est la cause numéro un des échecs au démarrage. Recopiez exactement, y compris les espaces.

Créez fail2ban.yml à côté de l'inventaire :

---
- name: Fail2ban installé et actif sur tous les serveurs
  hosts: serveurs
  become: true

  tasks:
    - name: Installer le paquet fail2ban
      ansible.builtin.apt:
        name: fail2ban
        state: present
        update_cache: true
        cache_valid_time: 3600

    - name: Démarrer fail2ban et l'activer au redémarrage
      ansible.builtin.service:
        name: fail2ban
        state: started
        enabled: true

Trois choses méritent d'être lues au ralenti.

hosts: serveurs reprend l'étiquette de l'inventaire. Le jour où vous ajoutez un quatrième serveur, vous l'ajoutez à l'inventaire et ce fichier ne bouge pas.

become: true signifie « passe en administrateur pour ces tâches », l'équivalent de sudo. Sans lui, l'installation échoue sur un refus de droits.

state: present et state: started ne disent pas « installe » ni « démarre ». Ils disent « je veux que ce soit installé », « je veux que ce soit démarré ». La nuance est toute la suite de ce guide.

Simuler avant d'exécuter

Un outil qui agit sur une machine se trompe sur une machine. Un outil qui agit sur trois machines se trompe sur trois machines, en même temps, sans que vous ayez le temps de réagir.

Le geste normal, celui à prendre dès la première fois et pas quand vous serez expérimenté, c'est de lancer d'abord la version qui ne touche à rien :

ansible-playbook -i inventaire.ini fail2ban.yml --check --diff

--check demande à Ansible de traverser tout le playbook en annonçant ce qu'il ferait, sans le faire. --diff montre en plus le détail des fichiers qui seraient modifiés. Vous lisez, machine par machine, ce qui va se passer. Si une ligne vous surprend, vous corrigez maintenant, pendant que rien n'a bougé.

Une honnêteté nécessaire sur ce mode : il n'est pas parfait. Ici, sur une machine où fail2ban n'est pas encore installé, la simulation peut échouer sur la seconde tâche, parce qu'elle cherche un service qui n'existe pas encore et qui n'a pas été réellement installé par la tâche précédente. Ce n'est pas une erreur de votre part, c'est une limite structurelle de la simulation : elle ne peut pas deviner l'effet d'une action qu'elle n'a pas exécutée. Vous en tenez compte, et la simulation reste utile pour tout le reste.

Exécuter

La même commande, sans --check :

ansible-playbook -i inventaire.ini fail2ban.yml

Le résumé de fin ressemble à ceci :

PLAY RECAP ***********************************************************
web01 : ok=3    changed=2    unreachable=0    failed=0
web02 : ok=3    changed=2    unreachable=0    failed=0
db01  : ok=3    changed=2    unreachable=0    failed=0

changed=2 : sur chaque machine, deux choses ont réellement été modifiées, l'installation et l'activation du service. Ce qui vous prenait trois connexions et une vérification vient de tenir en une commande, et le troisième serveur a reçu exactement le même traitement que le premier, y compris l'activation au redémarrage que vous auriez oubliée.

Rejouer, et ne rien casser

Relancez maintenant la même commande, à l'identique, tout de suite :

ansible-playbook -i inventaire.ini fail2ban.yml
PLAY RECAP ***********************************************************
web01 : ok=3    changed=0    unreachable=0    failed=0
web02 : ok=3    changed=0    unreachable=0    failed=0
db01  : ok=3    changed=0    unreachable=0    failed=0

changed=0. Rien n'a été réinstallé, rien n'a été redémarré, le service n'a pas été coupé une seconde. Ansible a regardé, constaté que l'état demandé était déjà là, et s'est abstenu.

C'est le moment le plus important de ce guide, et c'est pour cela qu'il fallait le faire vous-même plutôt que le lire. Un script shell qui aurait fait apt install puis systemctl restart aurait, lui, redémarré le service trois fois, coupé les connexions en cours et réécrit la configuration. Ici, relancer est sans conséquence. Ce que vous venez de constater porte un nom, idempotence, mais le nom importe moins que sa conséquence pratique : vous pouvez relancer ce playbook n'importe quand, sur n'importe quelle machine, sans vous demander si c'est risqué.

Cela change l'usage de l'outil. Le playbook n'est plus une opération que l'on déclenche une fois : il devient la description de référence de vos serveurs. Un doute sur une machine, un serveur tout juste réinstallé, un quatrième serveur ajouté à l'inventaire : vous relancez, et seule la machine qui n'est pas conforme bouge.

Ajouter une machine

L'inventaire, une ligne de plus :

[serveurs]
web01 ansible_host=192.168.1.11
web02 ansible_host=192.168.1.12
db01 ansible_host=192.168.1.13
web03 ansible_host=192.168.1.14

Vous relancez le playbook. Les trois premières machines affichent changed=0, la nouvelle affiche changed=2. Vous n'avez rien écrit de neuf, rien exclu à la main, et rien redémarré sur les serveurs en production.

Erreurs fréquentes

  • Sauter l'accès par clé et vouloir « juste essayer ». L'exécution s'arrête sur la première machine en attendant un mot de passe que personne ne tape. Réglez SSH d'abord, tout le reste en dépend.
  • Oublier become: true. L'échec parle de permission refusée sur l'installation, et on cherche longtemps du côté d'Ansible alors que c'est simplement sudo qui manque.
  • Recopier le YAML en changeant l'indentation. Un décalage de deux espaces produit un message d'erreur qui pointe rarement la bonne ligne. En cas de doute, effacez le fichier et recopiez-le d'un bloc plutôt que de chercher.
  • Traiter --check comme une option d'expert. C'est l'inverse : plus vous avez de machines dans l'inventaire, plus la simulation est le seul moment où une erreur reste réparable.
  • Écrire un playbook qui redémarre systématiquement un service. C'est reproduire un script shell avec la syntaxe d'Ansible, et perdre la seule propriété qui justifiait l'outil.

Ce que ça change pour vous

Une tâche d'administration cesse d'être un geste que quelqu'un doit refaire, et devient un fichier texte qu'on relit, qu'on corrige et qu'on conserve avec le reste du code.

Le risque d'oubli sur la dernière machine de la série disparaît, parce qu'il n'y a plus de série : il y a une commande.

Le coût d'ajouter un serveur tombe à une ligne, ce qui rend enfin raisonnable de traiter tous les serveurs pareil plutôt que de tolérer des exceptions qu'on finit par oublier.

À retenir

  • On entre dans Ansible par une corvée réelle, pas par son vocabulaire : la corvée justifie l'outil, l'inverse ne se produit jamais.
  • Le playbook décrit un état voulu, pas une suite d'actions. C'est ce qui permet de le rejouer sans crainte.
  • --check --diff avant chaque exécution réelle, dès la première fois. Une erreur simulée ne coûte rien, la même erreur exécutée coûte trois serveurs.
  • L'accès par clé SSH est un préalable non négociable, pas un confort.
  • Ajouter une machine, c'est modifier l'inventaire, jamais le playbook.

Mini-exercice

Prenez la tâche que vous avez faite à la main le plus récemment sur plus d'une machine. Écrivez-la dans un playbook d'une seule tâche, lancez-la avec --check --diff, lisez la sortie, puis exécutez-la pour de vrai. Relancez immédiatement et vérifiez que le résumé affiche changed=0 partout.

Si ce n'est pas le cas, votre tâche n'est pas idempotente : elle refait quelque chose à chaque passage. Cherchez laquelle dans la sortie, c'est presque toujours une tâche qui commande une action (restart, une commande shell brute) au lieu de décrire un état.

Pour aller plus loin, quand un seul fichier ne suffira plus : le cours Automatisation avec Ansible traite des variables, des rôles et de la gestion des secrets, et le cours Linux CLI : les bases pour le helpdesk si l'aisance en CLI (Command Line Interface, la ligne de commande) vous manque encore.

À lire ensuite

Sur le même thème, pour aller plus loin.

Besoin d'un accompagnement personnalisé ?

Cours 1:1, conseil de solution, ou simplement une question précise - contacte-moi directement.