Aller au contenu

Utilisation de 'delegate_to' dans Ansible

Mise à jour :

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.

Pourquoi utiliser delegate_to

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

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)

Simplifier la gestion des tâches conditionnelles

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.

Séparer les responsabilités entre hôtes

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.

Gagner en sécurité

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.

Syntaxe de base & mise en place

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.

Combiner delegate_to avec run_once

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.

Utilisation dans les boucles (loop ou with_items)

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.

Filtrage dynamique avec when + delegate_to

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.

Cas d’usage courants

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.

Téléchargement local de fichiers

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

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.

Exécution de scripts SQL depuis le contrôleur

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.

Collecte de données et reporting

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.

Contrôle de connectivité réseau

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é.

Cas d’usage avancés

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é.

Mise à jour DNS centralisée

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.

Agrégation de logs vers un serveur central

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.

Génération et distribution de certificats TLS

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

Basculement de base de données automatisé

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.

Synchronisation de sauvegardes

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.

Mise à jour de configuration HAProxy

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

Tests de charge post-déploiement

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

Bonnes pratiques delegate_to

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é.

Toujours utiliser les FQDN dans delegate_to

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

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.

Documenter la logique de délégation

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

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

Pourquoi ce contrôle ?

Cet contrôle va vous permettre de valider vos connaissances sur le sujet abordé dans le guide. Il comporte des QCM, des questions vrai/faux et des réponses ouvertes à un mot.

🕒 Le chronomètre commence dès que vous cliquez sur Démarrer le test. Vous devrez terminer l’examen avant la fin du temps imparti.

🎯 Pour réussir, vous devez obtenir au moins 80% de bonnes réponses.

💡 Je ne fournis pas directement les réponses aux questions. Cependant, si certaines sont complexes, des pistes d’explication pourront être proposées dans le guide ou après l’examen.

Bonne chance ! 🚀

Conclusion

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.