
Ansible fonctionne par défaut en mode push : un control node SSH vers les cibles. Mais il existe un mode pull : la cible récupère son playbook depuis un repo Git (avec ansible-pull) et s'exécute elle-même. Pas besoin de control node centralisé. Pas besoin d'accès SSH inverse. Pas besoin d'IP publique sur la cible.
À la fin de cette page, vous saurez quand choisir pull vs push, configurer un nœud Edge avec ansible-pull + cron + cloud-init, et comprendre les limites du mode pull (pas de centralisation des logs, incompatible AAP Tower).
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Différence push vs pull : qui initie la connexion.
- Lancer
ansible-pullmanuellement contre un repo Git. - Configurer une exécution périodique via
cronou systemd timer. - Intégrer
ansible-pulldanscloud-initpour qu'un nœud se configure seul au premier démarrage. - Comprendre les limites : logs distribués, pas d'AAP Tower, drift indétectable.
- Choisir push vs pull selon le cas d'usage.
Prérequis
Section intitulée « Prérequis »- Avoir validé le Premier playbook (mode push classique).
- Bases Git (clone, pull, branches).
Push vs Pull, qui initie la connexion
Section intitulée « Push vs Pull, qui initie la connexion »| Critère | Mode push (default) | Mode pull (ansible-pull) |
|---|---|---|
| Qui initie la connexion ? | Control node → cibles (SSH) | Cible → repo Git (HTTPS/SSH) |
| Centralisation | Oui (control node) | Non (chaque nœud autonome) |
| Visibilité logs | Centralisée | Distribuée (sur chaque nœud) |
| Cas d'usage typique | Datacenter, fleet maîtrisée | Edge, IoT, NAT, bootstrap |
| Compatible AAP Tower | Oui | Non (mode pur ansible-core) |
| FQCN, collections, vault | Oui | Oui |
| Testé à RHCE EX294 | Oui | Non |
🔍 Observation : ansible-pull utilise les mêmes playbooks qu'ansible-playbook. La différence est juste qui exécute, pas le contenu du playbook. Permet de basculer un projet push vers pull sans réécriture.
Cas d'usage 2026
Section intitulée « Cas d'usage 2026 »Edge computing / IoT
Section intitulée « Edge computing / IoT »Des nœuds isolés derrière un NAT, sans IP publique, qui ne peuvent pas être joints par SSH depuis un control node central. Ils tirent leur config depuis Git :
# Sur un nœud IoT (Raspberry Pi, Jetson Nano, etc.)ansible-pull -U https://github.com/myorg/iot-config.git pull-playbook.ymlBootstrap au premier démarrage, via cloud-init
Section intitulée « Bootstrap au premier démarrage, via cloud-init »Une nouvelle VM se configure elle-même au premier boot :
#cloud-configpackages: - ansible-core - git
runcmd: - ansible-pull -U https://github.com/myorg/infra.git pull-playbook.ymlEnchaînement : Terraform ou le cloud provisionne, cloud-init lance ansible-pull, la VM est prête. Aucune intervention SSH.
Ce n'est pas de l'infrastructure immuable, et la distinction n'est pas un détail de vocabulaire. Une infrastructure immuable remplace la machine à chaque changement ; ici, un cron modifie périodiquement une machine qui reste en place. Le terme juste est convergence périodique, ou gestion de configuration en mode pull : le dépôt décrit l'état désiré, et chaque nœud s'en rapproche à intervalle régulier. La différence se paie le jour d'un incident, quand on cherche à savoir si une machine a divergé ou si elle n'a jamais convergé.
Quand le control node devient le goulot
Section intitulée « Quand le control node devient le goulot »Un control node centralisé exécute tout le parc, et son parallélisme est borné par forks, la RAM et le CPU. En pull, chaque nœud s'exécute indépendamment : la charge ne se concentre plus. Le seuil où cela bascule dépend de la durée des playbooks, du réseau et du matériel du control node, il n'y a pas de nombre universel à citer.
Pattern GitOps strict
Section intitulée « Pattern GitOps strict »Le repo Git est la source de vérité. Chaque nœud reflète l'état de la branche. Modification → commit → push → tous les nœuds qui pull cron synchronisent dans la fenêtre suivante.
Anatomie d'ansible-pull
Section intitulée « Anatomie d'ansible-pull »sudo dnf install -y ansible-core git
ansible-pull \ -U https://github.com/stephrobert/ansible-pull-demo.git \ -d /var/lib/ansible-pull \ pull-playbook.ymlCe que fait ansible-pull :
git clone(ougit pullsi déjà clôné) le repo dans/var/lib/ansible-pull/.ansible-playbooksurpull-playbook.ymlavechosts: localhost(par défaut).- Exit avec le code de retour du playbook.
Options principales :
| Option | Effet |
|---|---|
-U <git-url> | URL du dépôt, obligatoire |
-d <chemin> | Où se fait le clone, défaut /var/lib/ansible/local |
-i <inventaire> | Inventaire, comme ansible-playbook |
-C <ref> | branche, tag ou commit à sortir |
--full | Clone complet au lieu du clone superficiel par défaut |
--verify-commit | Vérifie la signature GPG du commit, et abandonne si elle échoue |
--check / --diff | Simulation et affichage des différences, comme en push |
--only-if-changed | Ne joue le playbook que si le dépôt a bougé |
--vault-password-file <path> | Compatible Ansible Vault |
-K / --ask-become-pass | Demande le mot de passe sudo |
-C ne vaut pas « main » par défaut
Section intitulée « -C ne vaut pas « main » par défaut »C'est l'erreur la plus répandue sur cette commande, et elle a une conséquence directe sur la reproductibilité d'un parc. L'aide de la CLI est sans ambiguïté :
-C, --checkout CHECKOUT branch/tag/commit to checkout. Defaults to behavior of repository module.Le défaut n'est donc pas main, c'est la branche par défaut du dépôt,
quelle qu'elle soit. Mesuré sur un dépôt dont la branche par défaut s'appelle
principale :
ansible-pull -U file:///opt/depot -d /opt/ciblegit -C /opt/cible rev-parse --abbrev-ref HEADprincipaleUn dépôt qui change de branche par défaut change donc la configuration de tout un parc, sans qu'aucune ligne de cron ait bougé. C'est la raison d'épingler explicitement, et de préférence sur un commit.
Le pull-playbook.yml, pattern standard
Section intitulée « Le pull-playbook.yml, pattern standard »---- name: Se configurer soi-même depuis le dépôt hosts: localhost # ← cible LA MACHINE ELLE-MÊME connection: local # ← pas de SSH (déjà sur la cible) become: true gather_facts: true tasks: - name: Marker pull executed ansible.builtin.copy: dest: /var/log/ansible-pull-marker.txt content: | ansible-pull executed at: {{ ansible_date_time.iso8601 }} hostname: {{ ansible_hostname }} mode: "0644"Ce couple est le pattern normal, pas une obligation technique. La nuance
compte dès qu'on sort du cas simple : ansible-pull reste un frontend à
ansible-playbook et expose -i, --limit, -e et le reste. Rien n'interdit
de lui passer un inventaire cloné avec le dépôt, ni de cibler un groupe.
Ce qui est vrai, c'est que la machine est la cible : viser hosts: db1.lab
depuis db1.lab sans y avoir configuré de connexion échoue, faute de SSH vers
elle-même. connection: local évite précisément ce détour.
Vérifier la signature du commit avant de l'exécuter
Section intitulée « Vérifier la signature du commit avant de l'exécuter »Un nœud en pull exécute ce que le dépôt contient, sans relecture humaine.
C'est la contrepartie du modèle : quiconque obtient le droit de pousser sur la
branche suivie pilote toutes les machines qui la tirent, à la prochaine fenêtre
de cron. --verify-commit est la seule barrière que la CLI offre contre ce
scénario.
ansible-pull -U https://forge.example.lan/infra.git \ -d /var/lib/ansible-pull \ -C "$COMMIT_ATTENDU" \ --verify-commit \ pull-playbook.ymlSur un commit non signé, la commande s'arrête avant de jouer le playbook :
"msg": "Failed to verify GPG signature of commit/tag \"c2388d2...\"","rc": 1,Mesuré sur la machine du lab : aucun fichier n'est déposé, la convergence n'a pas lieu. Sur un commit signé par une clé présente dans le trousseau du nœud, le playbook s'exécute normalement.
Le piège du clone superficiel
Section intitulée « Le piège du clone superficiel »ansible-pull clone en superficiel, et cela casse l'épinglage sur un commit
ancien. C'est le défaut le plus coûteux du mode pull, parce qu'il échoue
sans rien changer : la machine garde la configuration précédente et rien ne le
signale au niveau du parc.
Le scénario, mesuré pas à pas. Un premier passage sur une branche laisse un clone de profondeur 1 :
ansible-pull -U file:///opt/depot -d /opt/cible -C experimentalegit -C /opt/cible rev-list --count HEAD # 1test -f /opt/cible/.git/shallow && echo superficielUn second passage, sur le même répertoire, vers un commit plus ancien :
"msg": "Failed to checkout c2388d2...","stderr": "fatal: unable to read tree (c2388d2...)\n",Le commit visé n'est pas dans le clone, puisque celui-ci ne porte qu'une révision. Et le marqueur déposé par le passage précédent est toujours là : la machine n'a pas reculé, elle est restée où elle était.
Le libellé exact de l'erreur dépend de la version de git : unable to read tree sur git 2.47, reference is not a tree sur git 2.43. Ne bâtissez pas une
alerte sur cette chaîne, mais sur le code de retour.
# Repartir propre quand la reference changerm -rf /var/lib/ansible-pullansible-pull -U ... -C "$COMMIT" --full pull-playbook.ymlExécution périodique via cron
Section intitulée « Exécution périodique via cron »*/30 * * * * root /usr/bin/ansible-pull \ -U https://github.com/myorg/infra.git \ -d /var/lib/ansible-pull \ pull-playbook.yml \ >> /var/log/ansible-pull.log 2>&1Via Ansible (push initial qui configure le pull) :
- name: Configurer ansible-pull en cron ansible.builtin.cron: name: ansible-pull user: root minute: "*/30" job: >- /usr/bin/ansible-pull -U https://github.com/myorg/infra.git -d /var/lib/ansible-pull pull-playbook.yml >> /var/log/ansible-pull.log 2>&1🔍 Observation : pattern bootstrap puis pull, push initial pour installer ansible-core + déposer le cron. Ensuite le nœud s'auto-configure depuis le repo. L'agent reste minimaliste (juste cron + ansible-core + git).
Limites du mode pull
Section intitulée « Limites du mode pull »| Limitation | Impact |
|---|---|
| Pas de centralisation des logs | Sur chaque nœud localement (/var/log/ansible-pull.log). Agréger via journalctl + rsyslog vers Loki/ELK central. |
| Pas d'AAP Tower | AAP/Automation Controller est strictement push. Si vous voulez le UI AAP, restez en push. |
| Auto-update du nœud lui-même | Risque si un commit casse ansible-pull lui-même → nœud bloqué dans une boucle. Tester en CI avant de merger sur main. |
| Drift indétectable depuis le centre | Pas de "PLAY RECAP" agrégé. Un nœud isolé peut diverger sans alerter. Solution : exporter le code retour cron vers un health-check (Healthchecks.io, Prometheus pushgateway). |
| Sortie non consultée | Cron tourne en arrière-plan : --check et --diff existent bien en mode pull, mais personne ne lit leur sortie. Les réserver à un lancement manuel, et router la sortie du cron vers un journal. |
Quand choisir push vs pull
Section intitulée « Quand choisir push vs pull »Choisir push (ansible-playbook classique) quand :
- Datacenter classique avec control node maîtrisé.
- Parc dont un control node maîtrisé reste capable d'absorber la charge.
- Vous voulez utiliser AAP / Automation Controller.
- Logs centralisés via le control node.
- Workflow "lancer un déploiement maintenant sur toutes les cibles".
Choisir pull (ansible-pull) quand :
- Nœuds Edge/IoT derrière NAT, sans IP publique.
- Bootstrap au premier démarrage, sans control node joignable.
- Parc où le control node devient un goulot, sans qu'un seuil universel existe.
- Pattern GitOps strict (repo Git = source unique de vérité).
- Pas de control node centralisé envisageable.
Le push reste le mode par défaut, et le pull répond à des contraintes précises : nœuds injoignables, absence de control node, dépôt Git comme source unique. Les deux coexistent sans difficulté dans une même organisation, push pour le datacenter, pull pour ce qui est hors de portée.
Mettre en pratique
Section intitulée « Mettre en pratique »Le mode pull ne se comprend vraiment qu'en voyant une machine aller chercher elle-même sa configuration. Le lab monte un dépôt Git local et un script d'orchestration qui lance ansible-pull depuis la cible, avec le pull-playbook.yml en hosts: localhost et connection: local décrits plus haut, puis sa planification périodique. La vérification est structurelle : elle contrôle que le dépôt, le playbook et la planification sont en place, le pattern étant ici mis en œuvre plutôt que mesuré.
Pièges classiques
Section intitulée « Pièges classiques »hosts: db1.labau lieu dehosts: localhost→ erreur de connexion (pas de SSH).gitnon installé sur le nœud →ansible-pulléchoue. Toujours installeransible-core + gitau bootstrap.- Repo privé sans deploy key → clone échoue. Déposer une clé SSH déploy via cloud-init.
- Pas de health-check → un nœud qui plante en boucle est invisible. Ajouter un push vers Prometheus pushgateway en fin de playbook.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »- Push = control node → cibles (SSH). Default. AAP compatible. EX294.
- Pull = cible → repo Git.
ansible-pull -U <url>. Hors EX294. hosts: localhost+connection: localdans le playbook (la machine est elle-même la cible).cronou timer systemd pour la convergence périodique,cloud-initpour le premier démarrage. Ce n'est pas de l'infrastructure immuable : la machine est modifiée, pas remplacée.- Logs distribués, agréger via syslog/Loki/ELK pour centralisation.
-Cne vaut pasmainmais la branche par défaut du dépôt : épinglez sur un commit si vous voulez figer un parc.--verify-commitrefuse un commit non signé avant d'exécuter le playbook, à condition que la clé publique soit sur le nœud.- Le clone est superficiel : sur un répertoire réutilisé, un SHA ancien échoue et la machine garde son état précédent. Surveillez le code de retour, pas le fait que le cron ait tourné.
- Le push reste le mode par défaut ; le pull répond à des contraintes précises, nœuds injoignables ou absence de control node.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Développer des modules Python : un dépôt cloné en pull peut embarquer ses propres modules.
- Extension VS Code Ansible : écrire le playbook de pull avec lint et autocomplétion en direct.
- Steampunk Spotter : analyser le dépôt que chaque nœud clone, puisque personne ne le relit au runtime.