
Vous voulez comprendre ce qu’Ansible fait concrètement quand vous tapez ansible-playbook site.yml. Cette page explique l’architecture push SSH d’Ansible : le control node d’où partent les commandes, les managed nodes qui les exécutent, et toutes les briques entre les deux — modules, plugins, collections, Execution Environments. À la fin, le déroulé interne d’une tâche Ansible n’aura plus de zone d’ombre pour vous.
Analogie : Ansible fonctionne comme un chef d’orchestre (control node) qui dépose la partition (le module) devant chaque musicien (managed node) le temps qu’il joue son passage, puis ramasse la partition. Aucune partition ne reste sur le pupitre une fois la tâche finie. C’est éphémère, c’est sans agent, c’est SSH.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Le schéma général d’un déploiement Ansible et ses cinq composants principaux.
- Ce que contient un control node :
ansible-core,ansible-navigator, Execution Environment. - Les prérequis d’un managed node (SSH, sudo, Python).
- Le workflow détaillé d’un push SSH : connexion, upload module, exec, cleanup.
- Comment les plugins étendent Ansible (connection, inventory, callback, lookup, filter).
- Pourquoi les Execution Environments sont la mécanique 2026 de référence.
Vue d’ensemble : le schéma push SSH
Section intitulée « Vue d’ensemble : le schéma push SSH »Le schéma ci-dessous représente notre lab Ansible (1 control node + 3 managed nodes) avec le flux d’exécution. Lisez-le de gauche à droite : votre poste à gauche, les serveurs gérés à droite, et les flèches qui matérialisent le push SSH.
Trois enseignements à retenir du schéma. Premièrement, le control node est unique — c’est de lui que partent toutes les actions. Une seule machine pilote N managed nodes (10, 100, 1000 — la limite est votre patience SSH et votre paramètre forks). Deuxièmement, les flèches sont mono-directionnelles : Ansible se connecte aux managed nodes, jamais l’inverse. Troisièmement, deux ressources externes alimentent le control node : l’inventaire (qui décrit qui sont les managed nodes) et les collections (qui apportent les modules + plugins).
Le control node : votre poste de pilotage
Section intitulée « Le control node : votre poste de pilotage »Le control node est la machine où vous installez Ansible et d’où vous lancez les commandes. C’est typiquement votre poste de développement, ou un serveur de management dédié (souvent appelé « bastion » ou « jumphost »). Il héberge cinq éléments distincts qu’il faut savoir distinguer.
ansible-core est le moteur Python qui parse les playbooks YAML, négocie la connexion SSH, sérialise les modules, interprète les retours JSON. Vous l’installez avec pipx install --include-deps ansible, dnf install ansible-core, mise install ansible@latest, ou en l’embarquant dans un Execution Environment. Le binaire principal est /home/<user>/.local/bin/ansible (avec pipx) ou /usr/bin/ansible (avec dnf).
ansible-navigator est l’interface utilisateur moderne depuis Ansible Automation Platform 2.0. C’est un wrapper TUI/CLI qui exécute vos playbooks dans un conteneur (l’Execution Environment) au lieu de les lancer directement. Pour la RHCE 2026, savoir l’utiliser est attendu.
L’Execution Environment (EE) est une image conteneur OCI qui packagé ansible-core + collections + dépendances Python. Vous le construisez avec ansible-builder build à partir d’un fichier execution-environment.yml. C’est l’évolution de référence pour la production : le contenu est figé et reproductible.
L’inventaire est la source de vérité des managed nodes. Statique (un fichier YAML ou INI) ou dynamique (un plugin qui interroge AWS, Proxmox, NetBox). Vous le pointez via ansible.cfg ou la flag -i. C’est ce qui permet à ansible all -m ping de savoir quelles machines contacter.
Les collections sont les paquets de modules (ex: ansible.builtin, community.general, ansible.posix). ansible.builtin est livrée avec ansible-core. Les autres s’installent via ansible-galaxy collection install ou via un fichier requirements.yml versionné dans votre projet.
Les managed nodes : ce qui doit y vivre
Section intitulée « Les managed nodes : ce qui doit y vivre »Un managed node est un serveur Linux (ou Windows, mais c’est un cas à part) que le control node configure. La promesse d’Ansible : rien à installer dessus. C’est exact, à trois prérequis près que voici.
Le serveur SSH doit être actif et joignable depuis le control node. Sur AlmaLinux 10 / RHEL 10, c’est le cas par défaut (sshd.service). Le port 22 doit être ouvert dans le firewall de la cible (côté firewalld : firewall-cmd --permanent --add-service=ssh). Sans SSH, pas d’Ansible — c’est le seul vrai non-négociable.
Un compte utilisateur dédié avec sudo configuré (typiquement ansible avec NOPASSWD: ALL). Vous éviterez de lui donner accès direct à root — utiliser un compte applicatif plus sudo est un pattern de sécurité standard. La clé publique du control node doit être déposée dans ~ansible/.ssh/authorized_keys côté managed node.
Python 3 est le troisième prérequis. C’est l’interpréteur qui exécute les modules une fois qu’ils sont copiés sur le managed node. Sur AlmaLinux 10, /usr/bin/python3.12 est présent par défaut. Si la cible n’a pas Python (équipement réseau, conteneur minimaliste), Ansible bascule sur le module raw qui envoie des commandes shell brutes — solution de contournement, pas l’idéal.
Le workflow du push SSH, étape par étape
Section intitulée « Le workflow du push SSH, étape par étape »Quand vous tapez ansible-playbook site.yml sur votre control node, voici ce qui se passe pour chaque tâche dans le playbook. C’est précis, c’est mécanique, et c’est utile à connaître pour diagnostiquer un échec.
D’abord, Ansible lit l’inventaire (inventory/hosts.yml ou via le plugin dynamique) et résout le pattern d’hôtes du play (hosts: web1.lab → [10.10.20.21]). Ensuite, le plugin de connexion (par défaut ansible.builtin.ssh) ouvre une session SSH vers la cible. Ansible utilise les options SSH locales : votre ~/.ssh/config, votre clé privée, votre ssh-agent. Sortie réelle de cette étape, capturée avec -vvv :
<10.10.20.21> ESTABLISH SSH CONNECTION FOR USER: ansible<10.10.20.21> SSH: EXEC ssh -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentityFile="/home/bob/Projets/lab-ansible/ssh/id_ed25519" -o KbdInteractiveAuthentication=no -o PreferredAuthentications=...,publickey -o PasswordAuthentication=no -o User="ansible" -o ConnectTimeout=10 -o ControlPath="~/.ssh/cm-%r@%h:%p" -o NumberOfPasswordPrompts=1 10.10.20.21 '/bin/sh -c "sudo -H -S -n -u root /bin/sh -c ... && /usr/bin/python3.12 && sleep 0"'Notez les trois options qui matérialisent une optimisation cruciale : ControlMaster=auto, ControlPersist=60s et ControlPath. Elles activent le multiplexage SSH — la première tâche ouvre une session, et les suivantes la réutilisent au lieu de payer le coût d’un handshake TLS pour chaque tâche. Sur un playbook de 50 tâches, ça divise la durée totale par un facteur 5 à 10.
Ensuite, Ansible upload le module Python dans un répertoire temporaire de la cible (typiquement ~/.ansible/tmp/ansible-tmp-<timestamp>-<random>/). Le module est un fichier Python autonome contenant le code de la tâche (par exemple ansible.builtin.dnf = ~2000 lignes Python). C’est lourd mais sûr : pas d’agent persistant, juste un script Python qu’on écrase à chaque run.
Puis, le module s’exécute sur le managed node. Si le play utilise become: true, Ansible enrobe l’appel dans sudo -H -S -n -u root (visible dans la trace ci-dessus). Le module fait son boulot — installer un paquet, redémarrer un service, écrire un fichier — et retourne du JSON sur stdout : {"changed": true, "ok": true, "...": "..."}.
Enfin, Ansible lit ce JSON, met à jour son rapport interne (le compteur ok / changed / failed), et passe à la tâche suivante. Le répertoire temporaire est supprimé. Aucun processus Ansible ne reste actif sur la cible.
Les modules : built-in vs collections
Section intitulée « Les modules : built-in vs collections »Un module Ansible est un programme Python qui exécute une action sur le managed node. Vous en utilisez à chaque tâche, sans toujours en avoir conscience — ansible.builtin.dnf, ansible.builtin.copy, ansible.posix.firewalld sont tous des modules.
Les modules ansible.builtin sont livrés avec ansible-core. Ce sont les modules « système » de base : gestion de fichiers (file, copy, template, lineinfile), gestion de paquets (dnf, apt, package), gestion de services (systemd, service), gestion d’utilisateurs (user, group), exécution de commandes (command, shell, raw). Vous y avez accès dès ansible-core installé, sans rien à faire de plus.
Les modules des collections externes vivent dans des paquets séparés. community.general apporte ~600 modules tiers (firewalld n’y est plus, c’est passé dans ansible.posix, mais elle contient timezone, archive, htpasswd, ufw, etc.). ansible.posix apporte les modules POSIX étendus (mount, sysctl, firewalld, selinux, sefcontext). Vous installez ces collections explicitement.
ansible-galaxy collection list# Collection Version# ----------------------------- -------# ansible.builtin 2.18.x# ansible.netcommon 8.x.x# ansible.posix 2.x.x# community.general 10.x.x# community.libvirt 2.x.xFQCN obligatoire en 2026 : depuis ansible-core 2.10, vous appelez les modules par leur Fully Qualified Collection Name (ansible.builtin.dnf, pas juste dnf). Le nom court fonctionne encore par tolérance, mais ansible-lint le signale et le programme RHCE EX294 attend la forme complète.
Les plugins : extensions par type
Section intitulée « Les plugins : extensions par type »Les plugins sont la couche d’extensibilité d’Ansible. Au-delà des modules (qui font une action sur la cible), les plugins étendent le comportement du moteur : comment se connecter, comment afficher les logs, comment chercher une variable, etc. Il en existe plus d’une douzaine de types — vous n’aurez besoin de connaître que les principaux.
Les plugins de connexion définissent le canal d’accès aux managed nodes. Le plus courant est ansible.builtin.ssh (push SSH classique), et il y a ansible.builtin.local (exécution locale, sans SSH), ansible.builtin.psrp (Windows via PowerShell Remoting), community.docker.docker (exec dans un conteneur Docker), kubernetes.core.kubectl (exec dans un Pod Kubernetes). Vous voyez la liste avec ansible-doc -t connection -l :
ansible-doc -t connection -l# ansible.builtin.local execute on controller# ansible.builtin.paramiko_ssh Run tasks via Python SSH (paramiko)# ansible.builtin.psrp Run tasks over Microsoft PowerShell Remoting# ansible.builtin.ssh connect via SSH client binary# amazon.aws.aws_ssm connect to EC2 instances via AWS SSM# kubernetes.core.kubectl Execute on pods# community.docker.docker Run tasks in docker containersLes plugins d’inventaire transforment une source de vérité en inventaire Ansible exploitable. ansible.builtin.ini lit un fichier INI, ansible.builtin.yaml un fichier YAML, amazon.aws.aws_ec2 interroge l’API AWS pour découvrir vos instances EC2, community.general.proxmox fait la même chose côté Proxmox VE. C’est ainsi qu’on construit des inventaires dynamiques sans réécrire le YAML à chaque nouvelle VM.
Les autres plugins courants — callback (formatage de la sortie), filter (filtres Jinja2 personnalisés), lookup (récupération de données externes : fichiers, env, Vault), vars (sources de variables additionnelles) — sont des extensions pointues qu’on aborde au fil des sections.
Les Execution Environments : la mécanique 2026
Section intitulée « Les Execution Environments : la mécanique 2026 »Jusqu’ici, vous lancez Ansible directement sur votre poste. Cela marche, mais cela pose des problèmes dès qu’on veut industrialiser : versions Python qui changent entre postes, collections installées globalement qui collisionnent entre projets, dépendances Python (jmespath, netaddr) à gérer manuellement.
L’Execution Environment (EE) résout tout cela d’un coup. C’est une image conteneur OCI (au format Docker / Podman) qui contient ansible-core + collections + dépendances Python figées. Vous lancez vos playbooks via ansible-navigator run playbook.yml --eei mon-ee:1.0 — Ansible s’exécute dans ce conteneur, jamais sur votre poste.
version: 3images: base_image: name: registry.access.redhat.com/ubi9/python-312:latestdependencies: ansible_core: package_pip: ansible-core>=2.18,<2.19 python: - jmespath - netaddr galaxy: collections: - name: ansible.posix - name: community.generalTrois conséquences pratiques. Premièrement, ce que vous testez en local est identique à ce qui tourne en CI/CD ou en prod — l’image porte les mêmes binaires partout. Deuxièmement, Ansible Automation Platform (AAP) n’exécute que des EE depuis sa version 2.0 — l’utiliser sans EE n’est plus possible. Troisièmement, le RHCE EX294 attend que vous sachiez consommer un EE via ansible-navigator, parce que c’est ainsi que Red Hat opère ses propres exécutions.
Les facts : la fiche d’identité de chaque managed node
Section intitulée « Les facts : la fiche d’identité de chaque managed node »Au début de chaque play, Ansible collecte automatiquement ~100 à 300 variables sur chaque managed node — c’est le gather_facts: true par défaut. Cette collecte exécute le module ansible.builtin.setup, qui interroge le système (/proc, /etc/os-release, ip, lsblk…) et renvoie un gros JSON appelé facts.
Sur notre lab, on observe 108 facts collectés par managed node :
$ ansible web1.lab -m ansible.builtin.setup | python3 -c "import sys,json,re; \ out = sys.stdin.read(); start = out.find('{'); \ data = json.loads(out[start:]); print(f'{len(data[\"ansible_facts\"])} facts')"108 facts collectésLes facts qu’on utilise au quotidien : ansible_distribution (« AlmaLinux »), ansible_distribution_major_version (« 10 »), ansible_default_ipv4.address, ansible_memtotal_mb, ansible_kernel, ansible_processor_count. Vous les utilisez dans des conditions (when: ansible_distribution == "AlmaLinux") ou dans des templates Jinja2 ({{ ansible_default_ipv4.address }}).
Les facts ont un coût (quelques secondes par hôte, surtout sur fleet de 100+ nœuds). Pour optimiser, on active le fact caching dans ansible.cfg ou on désactive avec gather_facts: false quand un play n’en a pas besoin.
À retenir
Section intitulée « À retenir »- Le control node héberge
ansible-core,ansible-navigator, l’inventaire et les collections. Il pilote N managed nodes par SSH. - Un managed node n’a besoin que de trois choses : sshd, un compte sudo, Python 3.
- Chaque tâche fait un push SSH : connect → upload module Python → exec → retour JSON. Le multiplexage
ControlMasterréutilise la session. - Les modules font des actions (dnf, copy, systemd). Les plugins étendent le moteur (connection, inventory, filter, lookup).
- L’usage du FQCN (
ansible.builtin.dnf) est obligatoire en 2026 et au RHCE EX294. - Les Execution Environments packagent ansible-core + collections + Python en image OCI — c’est la mécanique de référence depuis AAP 2.0.
- Au début de chaque play, Ansible collecte ~100 facts par managed node — c’est ce qui rend les playbooks adaptables sans coder en dur la distribution.