Maximiser les performances d'Ansible avec ControlPersist et Pipelining

Améliorez considérablement les performances de vos playbooks Ansible en activant la réutilisation des connexions SSH avec ControlPersist et en rationalisant l'exécution des modules via Pipelining. Ce guide fournit des informations essentielles et des configurations pratiques pour réduire les temps d'exécution, en particulier dans les environnements à grande échelle. Apprenez à régler votre fichier `ansible.cfg` pour une automatisation informatique plus rapide et plus efficace.

32 vues

Maximiser les performances d'Ansible avec ControlPersist et Pipelining

Ansible est un outil puissant pour automatiser l'infrastructure informatique, permettant la gestion de configuration et le déploiement d'applications à grande échelle. Cependant, dans des environnements à fort volume ou lors de la gestion d'un grand nombre de nœuds, le surcoût inhérent à l'établissement de connexions SSH pour chaque tâche peut devenir un goulot d'étranglement important. Cela peut entraîner des temps d'exécution de playbook excessivement lents. Heureusement, Ansible offre deux fonctionnalités puissantes, ControlPersist et Pipelining, qui peuvent améliorer considérablement les performances en optimisant la façon dont Ansible communique avec les nœuds gérés.

Ce guide vous expliquera comment comprendre et implémenter ControlPersist et Pipelining. En tirant parti de ces techniques, vous pouvez réduire considérablement les temps d'exécution, rendant votre automatisation Ansible plus efficace et réactive, en particulier dans les environnements avec des centaines ou des milliers d'hôtes. Maîtriser ces optimisations est crucial pour quiconque souhaite faire évoluer efficacement ses déploiements Ansible.

Comprendre le comportement de connexion par défaut d'Ansible

Par défaut, Ansible établit une nouvelle connexion SSH à chaque hôte géré pour chaque tâche exécutée au sein d'un playbook. Pour chaque connexion, il effectue plusieurs étapes :

  1. Initier la connexion SSH : Une nouvelle connexion SSH est établie.
  2. Transférer les modules : Ansible transfère les modules Python nécessaires (ou d'autres fichiers pertinents) vers l'hôte distant.
  3. Exécuter le module : Le module est exécuté sur l'hôte distant.
  4. Recevoir la sortie : Ansible récupère les résultats de l'exécution.
  5. Fermer la connexion : La connexion SSH est terminée.

Bien que cette approche soit robuste et garantisse un état propre pour chaque tâche, le processus répété de connexion et de transfert de modules consomme un temps considérable, en particulier lorsqu'il s'agit de nombreuses tâches ou d'un inventaire important.

Optimiser les connexions avec ControlPersist

ControlPersist est une fonctionnalité SSH qui vous permet de maintenir les connexions SSH ouvertes pendant une période spécifiée, même après la fin de la commande initiale. Cela signifie que les tâches Ansible ultérieures ciblant le même hôte peuvent réutiliser la connexion existante et ouverte au lieu d'en établir une nouvelle. Cela réduit considérablement la latence associée à la mise en place de sessions SSH.

Comment fonctionne ControlPersist

Lorsqu'il est activé, ControlPersist indique au client SSH de maintenir une connexion maître de contrôle (control master connection). Les connexions SSH ultérieures vers le même hôte utilisant les mêmes identifiants et options peuvent alors être multiplexées sur cette connexion maître. Ansible en profite en définissant les options ControlPath et ControlPersist dans sa configuration SSH.

Activer ControlPersist dans Ansible

Vous pouvez activer ControlPersist de plusieurs manières :

  1. Via ansible.cfg (Recommandé pour les paramètres globaux ou spécifiques au projet) :
    Modifiez ou créez votre fichier ansible.cfg (situé dans votre répertoire de projet Ansible, ~/.ansible.cfg, ou /etc/ansible/ansible.cfg). Ajoutez la configuration suivante à la section [ssh_connection] :

    ini [ssh_connection] ssh_args = -o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p

    • -o ControlMaster=auto : Active le partage de connexion. Si une connexion maître existe, utilisez-la ; sinon, créez-en une.
    • -o ControlPersist=600 : Maintient la connexion de contrôle ouverte pendant 600 secondes (10 minutes). Ajustez cette valeur en fonction de votre flux de travail et de vos politiques de sécurité. Une durée plus longue signifie plus de réutilisation potentielle mais aussi plus de ressources maintenues ouvertes.
    • -o ControlPath=~/.ssh/ansible_control_%r@%h:%p : Définit le chemin du socket de contrôle. %r est le nom d'utilisateur distant, %h est le nom d'hôte et %p est le port. Cela garantit des sockets uniques pour différentes connexions.
  2. Via variable d'environnement :
    Vous pouvez définir les arguments SSH directement à l'aide d'une variable d'environnement :

    bash export ANSIBLE_SSH_ARGS='-o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p' ansible-playbook your_playbook.yml

  3. Via Playbook (moins courant pour ce paramètre) :
    Bien que cela soit possible, il n'est généralement pas recommandé de définir des options SSH persistantes au sein d'un playbook lui-même, car il s'agit d'un paramètre de niveau de connexion. Cependant, par souci d'exhaustivité, vous pourriez utiliser ansible.builtin.set_fact ou similaire pour l'influencer, mais ansible.cfg est préféré.

Considérations pour ControlPersist

  • Sécurité : Assurez-vous que le ControlPath est sécurisé afin que seuls les utilisateurs autorisés puissent accéder aux sockets de contrôle. Le chemin par défaut dans l'exemple est généralement sûr pour les configurations au niveau de l'utilisateur.
  • Utilisation des ressources : Maintenir les connexions ouvertes consomme des ressources sur le nœud de contrôle et sur les nœuds gérés. Surveillez l'utilisation des ressources si vous avez un très grand nombre de connexions persistantes.
  • Réinitialisation de connexion : Si un périphérique réseau intermédiaire ou le serveur SSH distant applique des délais d'attente de connexion plus courts que ControlPersist, la connexion pourrait quand même être interrompue. ControlPersist fonctionne mieux avec des environnements réseau stables.

Rationaliser l'exécution des modules avec Pipelining

Pipelining est une autre optimisation puissante d'Ansible qui réduit davantage le surcoût de l'exécution des tâches. Au lieu de transférer les modules vers l'hôte distant, de les exécuter, puis de récupérer la sortie, le pipelining diffuse les commandes directement sur la connexion SSH. Cela signifie qu'Ansible n'a pas besoin de placer les modules sur le système de fichiers distant ni de créer des fichiers temporaires pour la sortie.

Comment fonctionne le Pipelining

Lorsque le pipelining est activé, Ansible exécute les modules directement via ssh sur l'hôte distant. La sortie standard et l'erreur standard du module sont renvoyées à Ansible via la même connexion SSH. Cela élimine la nécessité pour Ansible d'écrire des fichiers sur le système de fichiers distant (comme /usr/bin/ansible_module_name ou des fichiers temporaires), puis de les exécuter. C'est particulièrement efficace pour les modules qui ne nécessitent pas d'escalade de privilèges ou d'interaction significative avec le système de fichiers distant.

Activer le Pipelining dans Ansible

Le pipelining est activé via le fichier ansible.cfg ou des variables d'environnement.

  1. Via ansible.cfg :
    Ajoutez ou modifiez la section [ssh_connection] :

    ini [ssh_connection] pipelining = True

  2. Via variable d'environnement :
    bash export ANSIBLE_PIPELINING=True ansible-playbook your_playbook.yml

Considérations pour le Pipelining

  • Escalade de privilèges : Le pipelining fonctionne mieux avec les modules qui ne nécessitent pas d'escalade de privilèges (par exemple, en utilisant become: yes ou sudo). Lorsque become est utilisé, Ansible a généralement besoin de copier des fichiers sur le système distant. Si vous utilisez fréquemment become, le pipelining pourrait ne pas offrir autant d'avantages ou pourrait même causer des problèmes avec certains types de modules.
  • Compatibilité des modules : La plupart des modules Ansible intégrés fonctionnent bien avec le pipelining. Cependant, les modules personnalisés ou ceux qui dépendent fortement des opérations sur le système de fichiers distant pourraient se comporter différemment. Testez minutieusement.
  • Stabilité de la connexion : Une connexion SSH stable est cruciale pour que le pipelining fonctionne correctement.
  • Paramètre SSH requiretty : Le pipelining est incompatible avec l'option SSH requiretty sur le serveur distant. Si votre serveur SSH a Defaults requiretty dans /etc/sudoers, vous devrez peut-être le désactiver ou utiliser !requiretty pour l'utilisateur spécifique avec lequel Ansible se connecte.

Combiner ControlPersist et Pipelining pour des performances maximales

Pour les gains de performance les plus significatifs, il est fortement recommandé d'activer à la fois ControlPersist et Pipelining. Cette combinaison résout les deux principaux surcoûts : l'établissement de la connexion et l'exécution du module.

Voici à quoi pourrait ressembler votre ansible.cfg avec les deux activés :

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p
pipelining = True

Lorsque les deux sont actifs :

  1. Ansible initie une connexion SSH et établit un ControlMaster si aucun n'existe (ControlPersist).
  2. Pour les tâches ultérieures, la connexion existante et ouverte est réutilisée.
  3. Les modules sont exécutés directement via le flux sans être copiés sur le système de fichiers (Pipelining).

Cette synergie réduit considérablement le temps qu'Ansible passe à communiquer avec chaque nœud géré, ce qui conduit à des exécutions de playbook beaucoup plus rapides.

Scénario d'exemple pratique

Imaginons un playbook qui doit exécuter 10 tâches simples sur 100 hôtes.

Sans optimisations :
Chaque tâche nécessite une nouvelle connexion SSH, un transfert de module, une exécution et une fermeture de connexion. Cela représente 100 hôtes * 10 tâches * (temps_connexion + temps_transfert_module). Si temps_connexion est de 0,5 seconde et temps_transfert_module de 0,2 seconde, cela fait 100 * 10 * 0,7 = 700 secondes de surcoût juste pour la communication et les transferts, sans inclure l'exécution réelle du module.

Avec ControlPersist et Pipelining activés :

  1. La première tâche sur chaque hôte établit la connexion initiale et configure le ControlMaster.
  2. Les 9 tâches suivantes sur cet hôte réutilisent la connexion ouverte et diffusent l'exécution du module.

Le surcoût par hôte se rapproche de temps_connexion + (9 * surcoût_minimal_diffusion). Le temps total est considérablement réduit, la majeure partie du temps d'exécution du playbook étant dédiée au travail réel effectué par les modules, plutôt qu'aux mécanismes de communication.

Quand être prudent

Bien que ces optimisations soient puissantes, elles ne sont pas universellement applicables sans considération :

  • Environnement avec des pare-feu stricts ou des restrictions réseau : Des interruptions fréquentes de connexion ou une inspection avec état (stateful inspection) pourraient interférer avec ControlPersist.
  • Environnements à haute sécurité : Des connexions SSH plus longues peuvent être un problème de sécurité dans des environnements fortement réglementés. Ajustez la durée de ControlPersist en conséquence.
  • Playbooks s'appuyant fortement sur become et les opérations de fichiers : L'efficacité du pipelining est réduite lorsque become est constamment utilisé, car cela nécessite souvent des opérations de fichiers. Testez l'impact sur les performances.

Conclusion

L'optimisation de la communication d'Ansible avec les nœuds gérés est une étape clé vers une automatisation efficace et évolutive. En comprenant et en implémentant ControlPersist et Pipelining, vous pouvez réduire considérablement les temps d'exécution des playbooks. ControlPersist maintient les connexions SSH actives, réduisant le surcoût de connexion, tandis que Pipelining diffuse l'exécution des modules, éliminant le besoin de transferts de fichiers. La combinaison de ces deux paramètres, principalement via ansible.cfg, est une bonne pratique pour tout utilisateur d'Ansible gérant un nombre important d'hôtes ou exécutant des playbooks complexes. Testez toujours ces configurations dans votre environnement spécifique pour affiner les performances et assurer la compatibilité.