Les tâches asynchrones sous Ansible
Mise à jour :
L’automatisation des tâches via Ansible permet de simplifier la gestion des infrastructures, mais certaines opérations peuvent prendre beaucoup de temps. Par exemple, l’installation de logiciels lourds, le provisionnement de machines virtuelles ou encore des opérations de sauvegarde. Par défaut, Ansible exécute les tâches de manière synchrone, c’est-à-dire qu’il attend que chaque tâche se termine avant de passer à la suivante. Cela peut parfois ralentir le déploiement global.
C’est ici que les tâches asynchrones entrent en jeu. Elles permettent à Ansible de démarrer une tâche et de continuer l’exécution des autres instructions sans attendre que la tâche initiale se termine. En parallèle, Ansible peut vérifier de façon périodique l’avancement de ces tâches. Ce modèle est particulièrement utile pour les opérations longues, car il permet de gagner du temps tout en gardant un contrôle sur l’avancement des tâches.
Utilisation de la commande ad-hoc Ansible avec async
Ansible permet l’exécution de tâches individuelles sur des hôtes distants via des commandes ad-hoc. Ces commandes sont particulièrement utiles pour lancer rapidement une tâche sans avoir à écrire un playbook complet. Il est également possible d’exécuter des tâches en mode asynchrone avec la commande ad-hoc, offrant ainsi une flexibilité supplémentaire pour les administrateurs qui souhaitent effectuer des opérations rapides sans bloquer leur terminal.
Rappel : Qu’est-ce qu’une commande ad-hoc ?
Une commande ad-hoc dans Ansible est une instruction simple lancée directement depuis la ligne de commande. Elle permet d’exécuter une tâche unique sur un ou plusieurs hôtes sans avoir besoin d’écrire un fichier de playbook. Voici un exemple classique d’une commande ad-hoc pour redémarrer un service :
Cette commande redémarre le service httpd
sur tous les hôtes inventoriés.
Ajouter async
à une commande ad-hoc
Ansible permet d’ajouter les paramètres async
et poll
aux commandes ad-hoc
pour exécuter une tâche en arrière-plan et continuer immédiatement à d’autres
opérations. La syntaxe est assez simple : vous ajoutez l’option -B
(pour
async
) et -P
(pour poll
) à la commande ad-hoc.
Syntaxe de base avec async
dans une commande ad-hoc :
- -B 600 indique que la tâche peut s’exécuter en arrière-plan pendant un maximum de 600 secondes (10 minutes).
- -P 5 spécifie que l’état de la tâche sera vérifié toutes les 5 secondes.
Exemple d’utilisation
Imaginons que vous souhaitiez exécuter une sauvegarde longue sur plusieurs
serveurs. Plutôt que d’attendre que chaque serveur termine sa sauvegarde, vous
pouvez utiliser une commande ad-hoc avec async
pour lancer la tâche sur tous
les serveurs en même temps et vérifier son état périodiquement.
Voici un exemple où l’on lance un script de sauvegarde sur tous les serveurs du groupe backup_servers en mode asynchrone :
Dans cet exemple :
- Le script de sauvegarde
backup.sh
peut s’exécuter pendant un maximum de 3600 secondes (1 heure). - Ansible vérifiera l’état de la tâche toutes les 60 secondes pour voir si elle est terminée.
Vérification de l’état des tâches asynchrones
Une fois la tâche lancée en arrière-plan, vous pouvez vérifier son statut à tout
moment à l’aide de la commande async_status
. Cela permet de suivre
l’avancement de la tâche sans attendre qu’elle se termine.
Pour vérifier l’état d’une tâche asynchrone spécifique lancée avec une commande ad-hoc, vous devez utiliser le Job ID (identifiant de tâche), que vous pouvez récupérer depuis les résultats de la commande initiale. Voici un exemple de vérification du statut de la tâche :
Cette commande utilise le module async_status
pour vérifier l’état de la tâche
associée à l’identifiant de travail 123456789.
Commande ad-hoc avec async
et throttle
Dans certaines situations, vous pourriez vouloir limiter le nombre de tâches
asynchrones exécutées simultanément sur vos serveurs afin d’éviter une
surcharge. Vous pouvez utiliser l’option --forks
pour limiter le nombre
d’hôtes auxquels Ansible se connecte simultanément, ce qui permet de contrôler
la charge.
Exemple de commande ad-hoc avec une exécution limitée à 5 hôtes simultanément :
Cette commande exécute la tâche de sauvegarde sur les serveurs, mais seulement sur 5 serveurs à la fois, ce qui est utile lorsque vous voulez éviter de surcharger vos ressources.
Limites des commandes ad-hoc avec async
Bien que les commandes ad-hoc avec async
soient très pratiques, elles
présentent certaines limites. En effet, contrairement aux playbooks, les
commandes ad-hoc ne conservent pas l’historique des tâches exécutées sur
plusieurs hôtes et le suivi des erreurs peut être plus difficile à gérer. De
plus, l’utilisation d’async dans des commandes ad-hoc convient mieux pour des
tâches rapides et ponctuelles plutôt que pour des opérations complexes
nécessitant un suivi détaillé.
Utilisation d’async
dans les playbooks
Le paramètre async
spécifie le temps maximum (en secondes) qu’Ansible
alloue à une tâche pour s’exécuter en arrière-plan. Cela permet à Ansible de
lancer la tâche et de la laisser tourner indépendamment, tout en continuant à
traiter d’autres tâches. Une fois la tâche terminée ou le délai atteint, Ansible
vérifiera son état pour savoir si elle a réussi ou échoué.
Voici la syntaxe de base d’une tâche asynchrone dans un playbook Ansible :
Dans cet exemple, la commande /usr/bin/long_running_task
est exécutée en
asynchrone, avec un temps d’attente maximum de 600 secondes. Le paramètre
poll
détermine la fréquence à laquelle Ansible vérifiera l’état de la tâche.
Cela permet d’éviter d’attendre la fin de la tâche tout en maintenant un
contrôle périodique sur son état.
Si vous ne souhaitez pas que la tâche soit vérifiée périodiquement, vous pouvez
définir le paramètre poll
à 0. Dans ce cas, Ansible lancera la tâche, mais
ne vérifiera pas son état, ce qui la laisse fonctionner complètement en
arrière-plan sans intervention. Vous devrez alors utiliser une autre tâche pour
vérifier manuellement son statut.
Exemple sans vérification périodique :
Dans ce cas, la tâche est simplement lancée en arrière-plan et Ansible ne fera pas de vérification automatique. Cela peut être utile pour des tâches très longues où vous ne voulez pas consommer des ressources inutiles en vérifiant l’état trop souvent.
Attendre la fin des taches asynchrones
Le module async_status d’Ansible est le module pour suivre l’avancement des tâches asynchrones exécutées avec le paramètre async. Ce module permet de vérifier si une tâche exécutée en arrière-plan est toujours en cours, si elle a réussi, échoué, ou si elle est encore en attente. Utiliser async_status est indispensable pour gérer les tâches longues ou parallélisées sans bloquer l’exécution d’autres opérations dans un playbook.
Chaque tâche asynchrone en cours d’exécution est associée à un Job ID unique, également appelé ansible_job_id. Ce Job ID est généré automatiquement par Ansible lorsque la tâche asynchrone est lancée. Vous devez enregistrer ce Job ID afin de pouvoir utiliser async_status pour interroger l’état de la tâche.
Voici un exemple de syntaxe pour vérifier l’état d’une tâche asynchrone :
Le module async_status retourne des informations sur l’état de la tâche. Voici quelques exemples des données que vous pouvez recevoir dans le retour :
- finished : Indique si la tâche est terminée ou non. Un résultat de True signifie que la tâche est terminée.
- started : Confirme si la tâche a bien démarré. Si la tâche n’a pas pu être initiée, cela peut indiquer un problème.
- exit_code : Le code de retour de la tâche. Un exit_code de 0 signifie généralement que la tâche s’est bien déroulée.
- stdout et stderr : Ces champs contiennent respectivement la sortie standard et les messages d’erreur de la tâche asynchrone.
- failed : Si ce champ est défini à True, cela signifie que la tâche a échoué.
Exemple de résultat de l’utilisation d’async_status :
Comment stopper le parralèlisme des tâches
Voici un playbook Ansible que je vais expliquer en détail pour illustrer l’utilisation des tâches asynchrones et du module async_status pour attendre la fin des tâches synchrones en cours :
Quelques explications :
- register: job_result : Le résultat de la commande async_status (c’est-à-dire l’état actuel de la tâche asynchrone) est stocké dans la variable job_result. Cette variable contient des informations telles que si la tâche est terminée ou encore en cours d’exécution, ainsi que les messages de sortie et les éventuelles erreurs.
- until: job_result.finished : Cette condition signifie que la tâche continuera de s’exécuter tant que la variable job_result.finished est False. Autrement dit, Ansible va répéter cette tâche de vérification jusqu’à ce que la tâche asynchrone soit terminée.
- retries: 100 : Ansible tentera de vérifier l’état de la tâche jusqu’à 100 fois maximum. Si la condition until n’est pas remplie après 100 tentatives, la tâche échouera.
- delay: 10 : Il y aura un délai de 10 secondes entre chaque tentative de vérification de l’état de la tâche asynchrone. Cela permet de ne pas interroger trop souvent le statut de la tâche.
Limiter les ressources avec throttle
Lorsque vous exécutez des tâches asynchrones sur plusieurs hôtes dans Ansible, il est important de prendre en compte l’impact sur les ressources système. Lancer trop de tâches en parallèle peut surcharger vos serveurs ou votre réseau, entraînant une dégradation des performances. Pour éviter cela, Ansible offre la possibilité de limiter le nombre de tâches qui s’exécutent simultanément en utilisant le paramètre throttle.
Le paramètre throttle permet de contrôler le nombre de tâches asynchrones qui peuvent être exécutées en parallèle sur les hôtes cibles. Cette fonctionnalité est particulièrement utile dans des environnements avec des ressources limitées ou lors de déploiements sur des centaines de machines. Par exemple, si vous devez installer un logiciel sur plusieurs dizaines de serveurs, vous pouvez limiter le nombre d’installations exécutées simultanément afin de ne pas surcharger vos systèmes ou votre réseau.
En utilisant throttle, Ansible s’assure de ne pas lancer trop de tâches à la fois, ce qui permet de mieux gérer les ressources et d’éviter des pics de charge inutiles.
Utilisation de throttle dans un playbook
Le paramètre throttle est spécifié directement dans une tâche de votre playbook. Il définit le nombre maximum d’instances de cette tâche qui peuvent être exécutées simultanément sur les hôtes définis.
Voici un exemple de tâche où throttle limite le nombre de tâches simultanées à 3 :
Dans cet exemple :
- async: 600 exécute la tâche d’installation en arrière-plan pendant un maximum de 600 secondes.
- poll: 5 signifie qu’Ansible vérifie l’état de chaque tâche toutes les 5 secondes.
- throttle: 3 limite le nombre de tâches asynchrones exécutées simultanément à 3. Cela signifie que, même si vous avez 10 serveurs web, seules 3 installations seront lancées à la fois. Les autres serveurs attendent leur tour pour que les ressources ne soient pas surchargées.
Comparaison avec forks
Il est important de différencier throttle de forks, une autre option d’Ansible qui contrôle le nombre d’hôtes auxquels Ansible se connecte simultanément. Forks définit le nombre de connexions en parallèle aux hôtes, tandis que throttle limite le nombre d’exécutions simultanées d’une tâche donnée.
Par exemple, vous pourriez utiliser forks pour limiter Ansible à se connecter à 10 hôtes simultanément et à l’intérieur de ces connexions, utiliser throttle pour limiter à 2 le nombre de tâches asynchrones exécutées simultanément.
Limites de throttle
Même si throttle est un outil puissant, il a certaines limitations :
- Synchronisation globale : Si vous avez besoin de synchroniser des actions sur plusieurs hôtes en fonction de l’état global du groupe, throttle seul ne suffira pas. Vous devrez peut-être utiliser d’autres techniques de gestion d’état ou de déploiement progressif.
- Gestion fine des priorités : Throttle ne permet pas de donner la priorité à certaines tâches ou hôtes. Si vous avez des serveurs plus critiques, vous devrez les gérer différemment.
Conclusion
Les tâches asynchrones sous Ansible offrent une solution puissante pour exécuter des opérations longues ou complexes sans bloquer l’ensemble du déploiement. Grâce à l’utilisation des paramètres async et poll, il est possible de lancer des tâches en arrière-plan, de les surveiller et de continuer l’exécution d’autres parties du playbook en parallèle. Cela permet non seulement d’optimiser les temps d’exécution, mais aussi de mieux gérer les ressources disponibles sur vos serveurs.
Que ce soit pour installer des paquets sur plusieurs serveurs, gérer des sauvegardes volumineuses, ou orchestrer des déploiements complexes sur des infrastructures distribuées, les tâches asynchrones sont une fonctionnalité essentielle pour les administrateurs systèmes. Elles permettent d’éviter les blocages inutiles et de garantir une meilleure efficacité dans la gestion des ressources.
Ces fonctionnalités rendent Ansible encore plus adapté aux déploiements à grande échelle ou à des opérations complexes, tout en offrant une meilleure gestion des performances. Toutefois, comme pour toute opération, il est essentiel de bien configurer et surveiller l’utilisation des tâches asynchrones pour s’assurer que les ressources sont utilisées efficacement et que les tâches s’exécutent dans les temps prévus.