Aller au contenu
Infrastructure as Code medium

Sous le capot : ce qu'un managed node Ansible doit fournir

12 min de lecture

Logo Ansible

Sur le lab du site, make provision s'occupe de tout, vous n'avez rien à faire. Cette page n'est pas un how-to où vous lancez quoi que ce soit : c'est l'ouverture du capot. On regarde ce qui se passe quand make provision enchaîne virt-install + cloud-init + le playbook de préparation, on apprend les 5 prérequis techniques qu'un managed node doit fournir à Ansible, et on décortique ligne par ligne le playbook qui les pose. Objectif : sortir de cette page capable de reproduire la préparation sur n'importe quelle fleet existante, hors du lab.

C'est aussi le moment où vous découvrez le principe « Ansible se prépare lui-même » : cloud-init pose le strict minimum (utilisateur + clé SSH), et Ansible converge le reste via un playbook idempotent. Cette approche reste valable partout : à condition d'avoir SSH + Python 3, un seul ansible-playbook aligne tout.

  • Identifier les 5 prérequis techniques d'un managed node Ansible et savoir les vérifier ;
  • Comprendre ce que make provision joue derrière le rideau, et donc ce que vous devrez faire à la main sur une fleet existante ;
  • Bootstrapper un host sans Python via le module raw (cas RHEL minimal, Alpine, équipements réseau) ;
  • Lire le playbook bootstrap/prepare-managed-nodes/playbook.yml ligne par ligne et comprendre chaque module utilisé ;
  • Vérifier l'idempotence avec un second ansible-playbook qui doit afficher changed=0.

Cette page suppose que :

  • Le lab KVM est provisionné (cf. Préparer le lab KVM) ;
  • Vous avez un inventaire fonctionnel sous inventory/hosts.yml avec un groupe parent rhce_lab regroupant webservers et dbservers ;
  • L'utilisateur ansible existe sur les managed nodes avec sudo NOPASSWD et la clé SSH publique en authorized_keys.
PrérequisPourquoiComment vérifier
Python 3 (3.6+)Tous les modules Ansible (sauf raw) sont du Python exécuté côté ciblessh ansible@web1.lab python3 --version
Accès SSH par clé (compte non-root)Modèle agentless, pas de mot de passe interactifssh -i ssh/id_ed25519 ansible@web1.lab doit passer
Sudo NOPASSWD sur ce comptebecome: true doit fonctionner sans saisie interactivessh ansible@web1.lab sudo -n true doit retourner 0
Firewall ouvert sur SSHLe moteur push s'appuie sur tcp/22nc -z web1.lab 22 doit réussir
Horloge synchroniséeLes modules de fichiers (mtime), les certificats, les logs corréléschronyc tracking côté managed node

Quatre des cinq sont déjà couverts par le cloud-init du lab. Le firewall, la synchro NTP, SELinux en mode enforcing, et l'inscription dans /etc/hosts sont posés par le playbook de préparation.

Le lab fournit labs/bootstrap/prepare-managed-nodes/playbook.yml. Voici la structure complète, commentée.

---
- name: Préparation des managed nodes (chrony, paquets utiles, /etc/hosts)
hosts: rhce_lab # cible le groupe parent (webservers + dbservers)
gather_facts: true # récupère ansible_distribution, ansible_default_ipv4...
become: true # toutes les tâches s'exécutent en root via sudo
vars:
lab_packages:
- python3-libselinux # indispensable quand SELinux est enforcing
- firewalld # firewall standard RHEL (objectif RHCE)
- python3-firewall # binding Python pour ansible.posix.firewalld
- chrony # synchro horaire entre managed nodes
- bash-completion
- vim-enhanced
- tar
- rsync
lab_hosts_entries:
- { ip: 10.10.20.10, name: control-node }
- { ip: 10.10.20.21, name: web1 }
- { ip: 10.10.20.22, name: web2 }
- { ip: 10.10.20.31, name: db1 }

Le bloc vars regroupe toutes les valeurs du playbook au même endroit, ajouter un paquet ou un hôte ne demande qu'une ligne.

- name: Installer les paquets de base
ansible.builtin.dnf:
name: "{{ lab_packages }}"
state: present

Le module dnf est idempotent : il vérifie chaque paquet, n'installe que ceux qui manquent. Au second run, changed=0.

- name: Activer et démarrer chronyd
ansible.builtin.systemd:
name: chronyd
enabled: true # démarrage au boot
state: started # démarré maintenant
- name: Activer et démarrer firewalld
ansible.builtin.systemd:
name: firewalld
enabled: true
state: started

Le module systemd combine enable + start en une seule tâche. Sans enabled: true, le service redémarrerait pas après reboot.

- name: Autoriser le service SSH dans firewalld (zone publique par défaut)
ansible.posix.firewalld:
service: ssh
permanent: true # écrit dans /etc/firewalld/zones/public.xml
immediate: true # applique aussi à la session runtime en cours
state: enabled

permanent: true + immediate: true est le combo standard : la règle survit au reboot et s'applique tout de suite. Sans immediate: true, il faudrait recharger firewalld manuellement.

- name: Inscrire chaque hôte du lab dans /etc/hosts
ansible.builtin.lineinfile:
path: /etc/hosts
line: "{{ item.ip }} {{ item.name }}.lab {{ item.name }}"
regexp: "^{{ item.ip | regex_escape }}\\s"
state: present
owner: root
group: root
mode: "0644"
loop: "{{ lab_hosts_entries }}"
loop_control:
label: "{{ item.name }}"

lineinfile ajoute la ligne si elle n'existe pas, ou la remplace si une ligne match regexp: (utile quand les IPs changent). Le loop_control.label: rend la sortie plus lisible (affiche web1 au lieu du dict complet).

- name: Vérifier que SELinux est en mode enforcing
ansible.posix.selinux:
state: enforcing
policy: targeted
- name: Régler la timezone du lab (Europe/Paris)
community.general.timezone:
name: Europe/Paris

SELinux enforcing est attendu en production RHEL et sur l'examen RHCE. Le module détecte l'état courant et n'agit que si nécessaire.

make provision a déjà joué ce playbook une fois pour vous. Le rejouer manuellement n'est pas obligatoire, c'est un exercice utile pour observer l'idempotence en action et se familiariser avec la sortie d'ansible-playbook avant de basculer sur les guides suivants.

Depuis la racine du repo ansible-training :

Fenêtre de terminal
ansible-playbook labs/bootstrap/prepare-managed-nodes/playbook.yml

(L'option -i inventory/hosts.yml est implicite : ansible.cfg à la racine du repo pointe déjà sur ce fichier.)

Au second passage sur un lab déjà préparé, vous devez voir le PLAY RECAP suivant :

PLAY RECAP *********************************************************************
db1.lab : ok=8 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web1.lab : ok=8 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
web2.lab : ok=8 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

changed=0 est la preuve d'idempotence : tous les modules ont vérifié l'état réel, l'ont trouvé conforme à l'état désiré, et n'ont rien modifié. Au premier run sur un lab fraîchement provisionné, vous verrez plutôt changed=6 ou changed=7 car les paquets, services, règles firewall et lignes /etc/hosts doivent être ajoutés.

Cas particulier, Bootstrap d'un host sans Python 3

Section intitulée « Cas particulier, Bootstrap d'un host sans Python 3 »

Sur certaines images minimales (RHEL UBI, Alpine, équipements réseau), Python 3 n'est pas installé. Vous ne pouvez pas faire un ansible all -m ping directement, vous devez passer par le module raw qui exécute du shell brut via SSH, sans Python côté cible.

---
- name: Bootstrap Python 3 sur les managed nodes minimaux
hosts: rhce_lab
gather_facts: false # désactivé, sinon Ansible essaie d'utiliser setup et plante
become: true
tasks:
- name: Vérifier la présence de Python 3
ansible.builtin.raw: which python3 || dnf install -y python3
register: python_check
changed_when: "'Installed' in python_check.stdout"

Une fois Python 3 installé via raw, vous bascule sur les modules normaux (dnf, systemd, etc.) dans les plays suivants. Le gather_facts: false est obligatoire dans le play de bootstrap, sinon Ansible essaie d'exécuter le module setup qui demande Python.

  • Un managed node doit fournir : Python 3, SSH par clé, sudo NOPASSWD, firewall ouvert, horloge synchronisée.
  • Le cloud-init du lab ne fait que poser l'utilisateur et la clé SSH ; Ansible converge le reste via le playbook de préparation.
  • Le module dnf est idempotent ; systemd combine enable + start ; firewalld avec permanent: true + immediate: true est le combo standard.
  • Sans Python 3 côté cible, on bootstrappe via le module raw (avec gather_facts: false).
  • changed=0 au second passage est la preuve d'idempotence, le critère de qualité d'un playbook bien écrit.

Cette page a un lab d'accompagnement : labs/bootstrap/prepare-managed-nodes/ dans stephrobert/ansible-training. Il contient un README.md guidé, un Makefile (make verify lance les tests), et un challenge final auto-évalué : préparer les 3 managed nodes (chrony, firewalld, SELinux, /etc/hosts) via un playbook idempotent.

Une fois le lab provisionné :

Fenêtre de terminal
cd ~/Projets/ansible-training/labs/bootstrap/prepare-managed-nodes/
cat README.md # tuto pas à pas
cat challenge/README.md # consigne du challenge final
pytest -v challenge/tests/ # lancer les tests testinfra

Si les tests passent, vous maîtrisez les concepts couverts dans ce guide. En cas de blocage, docs/troubleshooting.md à la racine du repo couvre les pièges fréquents (rate-limit SSH, clé absente, collection manquante).

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn