Aller au contenu
Infrastructure as Code medium

Utilisation de 'delegate_to' dans Ansible

15 min de lecture

logo

Dans un playbook Ansible, chaque tâche s’exécute par défaut sur l’hôte ciblé. Mais que faire lorsqu’une tâche doit s’exécuter sur un autre hôte, comme le serveur de contrôle ou un serveur central ? C’est là qu’intervient delegate_to. Cette directive permet de déléguer l’exécution d’une tâche à un autre hôte que celui initialement visé. Elle est idéale pour les actions centralisées : récupérer un fichier, envoyer une alerte, ou appliquer une configuration partagée. Grâce à delegate_to, vous gagnez en souplesse, en centralisation, et en efficacité opérationnelle dans vos automatisations.

Automatiser l’exécution de tâches sur un hôte différent avec delegate_to n’est pas juste une astuce technique. C’est une méthode puissante pour gagner en efficacité, fiabilité et lisibilité dans vos workflows d’automatisation.

Centraliser l’exécution des opérations critiques

Section intitulée « Centraliser l’exécution des opérations critiques »

Imaginez que vous deviez générer un fichier de configuration ou télécharger un binaire depuis Internet. Faut-il vraiment répéter cette action sur tous les serveurs ? delegate_to vous permet de centraliser l’exécution sur un hôte précis, souvent le serveur de contrôle (localhost), pour ensuite diffuser le résultat aux autres machines.

Exemple typique :

- name: Télécharger l'archive sur le serveur de contrôle
ansible.builtin.get_url:
url: https://monfichier.com/outil.tar.gz
dest: /tmp/outil.tar.gz
delegate_to: localhost

Cette méthode :

  • Évite les duplications de téléchargement
  • Réduit la bande passante utilisée
  • Sécurise les connexions sortantes (un seul point de sortie)

Certaines tâches ne doivent être exécutées qu’une fois, mais profiter à tous les hôtes. Avec delegate_to combiné à run_once, vous pouvez conditionner cela proprement :

- name: Générer une clé SSH commune pour tous les nœuds
ansible.builtin.command: ssh-keygen -t rsa -b 4096 -f /tmp/id_rsa -N ''
delegate_to: localhost
run_once: true

Ici, un certificat est généré une fois, puis distribué. Cela évite les conflits et standardise la configuration.

Vous pouvez définir clairement les rôles de chaque machine dans vos infrastructures IaC :

  • Le nœud de contrôle fait les opérations critiques
  • Les nœuds cibles appliquent simplement la configuration

Cela favorise la modularité des playbooks et améliore la lisibilité du code Ansible.

Limiter l’exécution de certaines commandes sensibles à un hôte de confiance (comme localhost) renforce la sécurité :

  • Pas de duplication de secrets sur chaque hôte
  • Moins d’expositions réseau
  • Moins de privilèges nécessaires sur les serveurs

Utiliser delegate_to, c’est donc combiner efficacité, cohérence et sécurité dans vos automatisations Ansible, tout en structurant vos tâches dans une logique claire d’infrastructure as code.

La directive delegate_to s’emploie sur une tâche pour indiquer à Ansible d’exécuter une commande sur un hôte différent de celui ciblé par le playbook. C’est une syntaxe simple mais puissante, qui peut changer profondément la logique de vos déploiements.

Voici un exemple de base pour déléguer une tâche au serveur de contrôle (localhost) :

- hosts: all
tasks:
- name: Créer un fichier localement
ansible.builtin.file:
path: /tmp/fichier_test.txt
state: touch
delegate_to: localhost

Même si le playbook vise tous les hôtes, la tâche s’exécute uniquement sur localhost.

Lorsque vous voulez exécuter une tâche une seule fois dans un playbook qui cible plusieurs hôtes, la combinaison run_once: true et delegate_to devient essentielle. Elle permet d’éviter l’exécution répétée d’une tâche qui ne doit se produire qu’une fois.

- name: Générer une clé SSH commune pour tous les nœuds
ansible.builtin.command: ssh-keygen -t rsa -b 4096 -f /tmp/id_rsa -N ''
delegate_to: localhost
run_once: true

Ainsi, la génération se fait une seule fois sur localhost, quel que soit le nombre de nœuds ciblés.

Par défaut, quand vous bouclez sur une liste dans Ansible, la tâche est exécutée pour chaque élément sur chaque hôte. Avec delegate_to, cette logique peut être recentrée sur un hôte unique.

- name: Créer des fichiers de logs d’inventaire
ansible.builtin.copy:
content: "Machine : {{ item }}"
dest: "/tmp/log_{{ item }}.txt"
loop: "{{ groups['all'] }}"
delegate_to: localhost
run_once: true

Cela permet par exemple de générer des rapports pour tous les hôtes depuis un point central, sans les contacter individuellement.

Il est possible d’exécuter une tâche déléguée uniquement si certaines conditions sont remplies :

- name: Recharger HAProxy si on est sur le maître
ansible.builtin.service:
name: haproxy
state: reloaded
delegate_to: "{{ inventory_hostname }}"
when: "'haproxy-master' in group_names"

Cette souplesse offre une logique conditionnelle puissante, en évitant des duplications de tâches dans les playbooks.

Utiliser delegate_to dans Ansible devient incontournable dans plusieurs situations où la centralisation de tâches est bénéfique. Voici des cas concrets pour illustrer son utilité et son efficacité dans des scénarios réels.

Plutôt que de télécharger un fichier depuis Internet sur chaque hôte cible, il est bien plus efficace de le faire une seule fois sur le serveur de contrôle :

- name: Télécharger une archive depuis Internet
ansible.builtin.get_url:
url: https://example.com/outil.tar.gz
dest: /tmp/outil.tar.gz
delegate_to: localhost

Ensuite, on peut copier cette archive sur chaque serveur avec une tâche classique copy.

Génération de configuration avec Jinja2 centralisée

Section intitulée « Génération de configuration avec Jinja2 centralisée »

Certains fichiers de configuration doivent être générés dynamiquement, mais leur création ne dépend que d’un seul point de vue (par exemple, un fichier YAML d’inventaire global). Dans ce cas, on peut centraliser la génération :

- name: Générer le fichier de configuration Nginx
ansible.builtin.template:
src: nginx.j2
dest: /tmp/nginx.conf
delegate_to: localhost
run_once: true

Puis, ce fichier est ensuite distribué aux serveurs Nginx.

Si vous gérez plusieurs bases de données mais que vous centralisez les accès via un tunnel SSH ou un hôte bastion, vous pouvez exécuter une requête SQL depuis une seule machine :

- name: Appliquer un script SQL
ansible.builtin.command: psql -h db.example.com -U admin -f /tmp/mise_a_jour.sql
delegate_to: bastion

Cela limite la surface d’exposition du mot de passe ou des accès sensibles.

Quand vous voulez générer un rapport d’état, une sauvegarde, ou un audit de configuration, vous pouvez rassembler les informations des hôtes cibles, puis traiter ou stocker les résultats centralement :

- name: Stocker les résultats d’audit localement
ansible.builtin.copy:
content: "{{ audit_result }}"
dest: "/var/log/audits/{{ inventory_hostname }}.log"
delegate_to: localhost

Chaque hôte envoie son résultat, mais l’enregistrement est centralisé sur localhost.

Vous pouvez tester la connectivité entre le serveur de contrôle et un hôte cible, ou entre deux hôtes, sans installer quoi que ce soit sur les machines :

- name: Vérifier la connectivité SSH vers un serveur
ansible.builtin.wait_for:
host: 10.0.0.5
port: 22
timeout: 10
delegate_to: localhost

Cela s’avère très utile dans des workflows de validation de disponibilité, ou avant un déploiement automatisé.

Dans des environnements plus complexes, delegate_to devient un outil clé pour gérer des tâches critiques de manière centralisée et sécurisée. Voici quelques scénarios avancés où cette directive brille par son efficacité.

Lorsqu’un changement dans l’infrastructure nécessite une mise à jour DNS (ex. ajout d’une nouvelle IP), cela doit se faire depuis un serveur DNS maître, et non depuis chaque hôte.

- name: Mettre à jour une entrée DNS via nsupdate
ansible.builtin.command: nsupdate /tmp/update.zone
delegate_to: dns-master
run_once: true

Cette action permet de centraliser les changements DNS tout en maintenant un playbook simple et lisible.

Au lieu de transmettre les logs individuellement à un SIEM ou un système distant, chaque hôte peut déléguer l’envoi à un collecteur central :

- name: Transférer les logs au serveur central
ansible.builtin.copy:
src: /var/log/syslog
dest: "/srv/logs/{{ inventory_hostname }}.log"
delegate_to: logs-collector

Cela renforce la cohérence des journaux et simplifie l’analyse.

Un serveur d’autorité interne peut être responsable de générer les certificats. Vous pouvez ainsi déléguer cette tâche à cet hôte unique, et distribuer ensuite les certificats aux machines concernées.

- name: Générer un certificat TLS
ansible.builtin.command: /usr/local/bin/gen-cert.sh {{ inventory_hostname }}
delegate_to: ca-server
run_once: false

Lors d’un failover, une tâche de promotion peut être lancée depuis un hôte central :

- name: Promouvoir le nouveau master PostgreSQL
ansible.builtin.shell: patronictl switchover --master db1 --candidate db2
delegate_to: pg-controller
run_once: true

Cela permet une gestion centralisée et fiable du cluster.

Plutôt que chaque serveur pousse sa sauvegarde, vous pouvez les récupérer depuis un serveur de sauvegarde unique :

- name: Récupérer les dumps SQL
ansible.builtin.synchronize:
src: "/srv/db/{{ inventory_hostname }}.sql"
dest: "/mnt/backups/"
mode: pull
delegate_to: backup-server

Le mode pull permet de garder le contrôle centralisé sur les transferts.

Vous pouvez construire une configuration haproxy.cfg sur un serveur central, la tester, puis la propager :

- name: Générer le fichier haproxy.cfg
ansible.builtin.template:
src: haproxy.j2
dest: /tmp/haproxy.cfg
delegate_to: haproxy-controller
run_once: true

Une fois l’application déployée, vous pouvez exécuter un test de charge via ab (Apache Bench) depuis une machine dédiée :

- name: Lancer un test de performance
ansible.builtin.command: ab -n 1000 -c 10 http://app.example.com/
delegate_to: bench-runner
run_once: true

L’usage de delegate_to dans Ansible ouvre la voie à une gestion plus fine et centralisée de vos automatisations. Mais pour éviter les pièges classiques et garantir un fonctionnement cohérent en production, il est essentiel d’adopter certaines bonnes pratiques. Voici les recommandations essentielles pour tirer le meilleur parti de cette fonctionnalité.

Pour éviter les erreurs de résolution DNS ou les confusions dans l’inventaire, utilisez systématiquement les noms d’hôtes complets (FQDN) dans delegate_to. Cela garantit que la tâche est bien dirigée vers l’hôte prévu, sans ambiguïté.

- name: Redémarrer HAProxy sur le nœud principal
ansible.builtin.service:
name: haproxy
state: restarted
delegate_to: haproxy1.example.local

Cela évite les conflits dans des environnements multi-réseaux ou hybrides.

Coupler delegate_to avec run_once quand nécessaire

Section intitulée « Coupler delegate_to avec run_once quand nécessaire »

Lorsque vous exécutez une tâche unique mais centrale, n’oubliez pas d’ajouter run_once: true pour empêcher la duplication sur plusieurs hôtes.

- name: Générer un token d’authentification
ansible.builtin.command: /usr/bin/gen-token.sh
delegate_to: auth.example.local
run_once: true

Sans run_once, la tâche serait lancée pour chaque hôte ciblé, même si delegate_to l’exécute toujours au même endroit.

Ajoutez des commentaires clairs dans vos tâches utilisant delegate_to, pour indiquer le but de la redirection. Cela facilite la maintenance et la compréhension pour les autres administrateurs.

# Cette tâche est centralisée sur le serveur de contrôle
# pour éviter les téléchargements multiples
- name: Télécharger une archive une seule fois
ansible.builtin.get_url:
url: https://example.com/outil.tar.gz
dest: /tmp/outil.tar.gz
delegate_to: control-node.example.local
run_once: true

Tester systématiquement sur un environnement de staging

Section intitulée « Tester systématiquement sur un environnement de staging »

La combinaison delegate_to et run_once peut parfois produire des comportements inattendus si mal utilisée. Testez toujours vos playbooks dans un environnement de préproduction avant de les exécuter en production.

Contrôle de connaissances : Inventaires statiques Ansible

Section intitulée « Contrôle de connaissances : Inventaires statiques Ansible »

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

7 questions
5 min.
80%

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

delegate_to permet de centraliser l’exécution des tâches dans Ansible, en les déléguant à un hôte spécifique comme le contrôleur ou un serveur central. C’est un outil simple mais puissant, qui améliore la lisibilité, la sécurité et l’efficacité des playbooks. Utilisé avec soin – en particulier avec run_once et des FQDN explicites – il devient indispensable dans toute stratégie Infrastructure as Code moderne.