- Les tâches d’automatisation des serveurs s’écrivent en code Python et s’exécutent en parallèle via SSH, ce qui permet d’exécuter des commandes de manière idempotente sans agent
- pyinfra met en avant une vitesse 6 fois supérieure à Ansible sur une charge de travail identique, grâce à une exécution concurrente basée sur gevent et SSH
- L’option
--drypermet de vérifier avant application le diff des changements hôte par hôte, et lors de l’exécution réelle les résultats reviennent en streaming parallèle - Les hôtes cibles n’ont besoin que d’un shell et de SSH, sans démon, fichier d’état ni control plane
- L’outil met l’accent sur une approche centrée sur le code, sans encoder les flux de contrôle en YAML, en utilisant directement les boucles et conditions de Python
Fonctionnalités clés et déroulement d’exécution
-
Automatisation de milliers de serveurs
- pyinfra est un outil d’automatisation Python-native et agentless qui exécute des commandes via SSH
- L’exécution des commandes met l’accent sur la concurrence, l’idempotence et la vitesse, avec l’affirmation d’être 6 fois plus rapide qu’Ansible sur la même charge de travail
- La commande d’installation est
$ uv tool install pyinfra - Les prérequis indiqués sont : licence MIT, Python 3.10 ou supérieur, no agents, zero config
-
Exemple de code de déploiement
- Les opérations
apt,filesetsystemdsont importées en Python pour installer des paquets, déployer un template et recharger un service - Le code d’exemple installe les paquets
nginxetcertbot, puis déploietemplates/nginx.conf.j2vers/etc/nginx/sites-enabled/api - À la dernière étape,
systemd.service("nginx", reloaded=True)recharge le servicenginx
from pyinfra.operations import apt, files, systemd apt.packages( packages=["nginx", "certbot"], update=True, ) files.template( src="templates/nginx.conf.j2", dest="/etc/nginx/sites-enabled/api", ) systemd.service("nginx", reloaded=True) - Les opérations
-
Inventaire et résultats d’exécution
- L’exemple d’inventaire comprend des hôtes web allant de
web-01.prodàweb-23.prod, ainsi que les hôtes de base de donnéesdb-01.prodetdb-02.prod - La commande
$ pyinfra inventory.py deploy.py --limit weblimite l’exécution à la cibleweb - La sortie d’exécution suit l’ordre suivant : chargement de l’inventaire, collecte concurrente des facts, exécution de
deploy.py, puis résumé - Le résumé d’exemple indique 23 hôtes réussis, 18 modifiés, 0 échec, pour un total de 2,1 secondes
- L’exemple d’inventaire comprend des hôtes web allant de
-
Vérification avant changement
--drypermet d’examiner à l’avance le diff par hôte de toutes les opérations que pyinfra va effectuer- Lors de l’exécution réelle, les résultats sont diffusés en parallèle, avec pour chaque hôte le nombre de changements et le temps d’exécution affichés
- L’exemple d’exécution indique 18 hôtes modifiés, 6 inchangés, 0 échec, sur 24 hôtes au total, en 2,1 secondes
Caractéristiques, comparaison avec Ansible et principes
-
Six raisons de choisir pyinfra
- Just Python : au lieu de YAML et de Jinja dans du YAML, les flux de contrôle s’écrivent directement en Python
- Concurrent SSH : l’exécution concurrente repose sur gevent et SSH, avec une vitesse annoncée 6 fois supérieure à Ansible sur la même charge
- Diff before apply : avec
--dry, tous les changements sont visibles à l’avance, et les opérations idempotentes deviennent des no-op lors d’une réexécution - 0 agents : les hôtes n’ont besoin que d’un shell et de SSH, sans démon, fichier d’état ni control plane
- Scale-ready : fonctionne de 1 à 10 000 hôtes, avec exécution en parallèle et sortie en streaming en temps réel
- Hackable : il est possible de créer une opération personnalisée en 10 lignes et de se connecter à docker, lxc et k8s qui communiquent avec un shell
-
Comparaison de code entre Ansible et pyinfra
- L’exemple Ansible montre un
playbook.ymlde 16 lignes pour installernginx, rendre un template et recharger le service via un handler - L’exemple pyinfra montre un
deploy.pyde 8 lignes qui décrit le même flux en code Python - Dans l’exemple pyinfra,
systemd.service("nginx", reloaded=True)ne s’exécute que sicfg.will_changerenvoie vrai pour le résultat defiles.template
from pyinfra.operations import apt, files, systemd apt.packages(["nginx"], update=True) cfg = files.template( src="nginx.conf.j2", dest="/etc/nginx/sites-enabled/api", ) if cfg.will_change: systemd.service("nginx", reloaded=True) - L’exemple Ansible montre un
-
Déclaration de principes
- Code > config : une boucle reste une boucle, sans encoder les flux de contrôle dans du YAML
- Show, then do : on affiche d’abord le diff, puis on applique, afin d’éviter les changements inattendus
- Stay out of the way : l’exécution se fait directement en SSH, sans agent, fichier d’état ni control plane
- Read like english : les opérations se lisent sous forme de noms et de verbes comme
apt.packages,files.template,systemd.service
-
Commande de démarrage
- La commande d’installation est
$ uv tool install pyinfra - Une invitation est proposée pour lire le quickstart de 5 minutes et déployer le premier hôte
- La commande d’installation est
1 commentaires
Avis sur Lobste.rs
pyinfra donne l'impression que c'est ainsi qu'Ansible aurait dû être conçu à l'origine. Au lieu d'ajouter du contrôle de flux à du YAML mêlé de templates, on peut écrire directement l'automatisation en Python
Après avoir longtemps utilisé Ansible, c'était rafraîchissant, alors que je n'étais même pas particulièrement anti-Ansible
Un modèle hybride utilisant aussi Python sur les serveurs cibles serait sans doute préférable. Cela réduirait l'enfer des guillemets lors des mises à jour de fichiers et éviterait aussi les limites des regex de
sedJ'aime pyinfra et j'aimerais qu'il soit plus largement utilisé
Toutes les entreprises où j'ai travaillé jusqu'ici utilisaient Ansible, avec ou sans Terraform en parallèle, et aucune n'était prête à réécrire toute son automatisation existante avec un outil que les employés ne connaissaient pas
pyinfra suppose que les équipes SysOps connaissent Python, et personnellement je pense qu'elles devraient au moins maîtriser un langage de script. En particulier, même avec Ansible, écrire des modules en Python permet de réduire le chaos YAML, mais au moins en France, cela ne semble pas être une idée très répandue
Ce n'est peut-être pas un sujet de débat si brûlant que ça
J'utilisais Ansible dans mon homelab, puis j'ai fini par le trouver de plus en plus frustrant. La configuration en YAML est horrible, tout donnait l'impression d'être du bricolage, et les performances étaient déprimantes. Je ne comprenais pas non plus pourquoi il fallait
python3sur le serveur juste pour exécuter quelques commandes shellJ'ai découvert
pyinfragrâce à Google AI Mode, et sur le mois environ où je l'ai utilisé, l'expérience a été bien plus agréable. Ses avantages sont d'être bien plus rapide qu'Ansible, de permettre d'écrire boucles et conditions en Python, de ne pas imposer de rôles ni d'arborescences imbriquées, et de n'exiger qu'un shell côté serveur. Il construit un plan à partir de l'état actuel avant l'exécution et, sans-y, demande une confirmationLes inconvénients sont que les opérations de base ne couvrent qu'un sous-ensemble bien plus restreint que les modules Ansible, que le code peut vite devenir du spaghetti, et que des approches comme
if 'web_server' in hosts.groupsne sont pas très élégantes non plus.operation(..., filter_group='web_server')est peut-être préférableLe pire reste que l'écriture de connecteurs personnalisés est vraiment pénible. Il semble falloir un
pyproject.tomlavec un entry point spécifique àpyinfra, et même avecuv, développer un connecteur interne ressemble à un cauchemar. On devrait pouvoir en faire un simple fichier Python ordinaire dans le projetCela fait quelques jours que je teste pyinfra comme outil de déploiement pour mon homelab, et comparé à Ansible, ce que je préfère le plus jusqu'ici n'est pas la syntaxe Python mais la vitesse
Ansible m'a toujours semblé insupportablement lent
J'aimerais remplacer l'usage d'Ansible et de Salt dans la plupart des environnements
C'est amusant de voir l'infrastructure as code boucler la boucle. On est passé des scripts au YAML, puis on revient à des scripts plus sophistiqués
Chaque approche a sa zone de pertinence, et du point de vue d'un utilisateur d'Ansible, pyinfra a l'air plutôt bien
La raison principale pour laquelle j'avais adopté Ansible, c'était son mode dry run et son affichage des différences. Cela permettait d'avoir confiance dans le fait qu'il n'allait rien faire d'inattendu
Or, il ne semble pas y avoir d'option équivalente dans la CLI de pyinfra. J'ai peut-être raté quelque chose faute d'avoir trouvé une doc de référence listant toutes les options par ordre alphabétique
—dry, affiché directement sur l'écran d'accueil de pyinfraPour ceux que ça intéresse, j'ai aussi un projet similaire vieux de 14 ans : https://github.com/sebastien/cuisine/tree/main
Il fonctionne sans agent, uniquement via SSH, et propose une API Pythonique au-dessus de fonctions de gestion de base, mais sans prendre en charge le mode dry
Chez nous, nous utilisons Ansible pour provisionner des ressources dans OpenStack, et nous gérons le reste avec pyinfra, ce qui fonctionne plutôt bien depuis plusieurs années
Le principal inconvénient est la petite taille de la communauté, ce qui nous oblige à écrire nous-mêmes certaines solutions. Par exemple, nous stockons les secrets partagés nécessaires au déploiement sur disque avec keyring + privy, et nous avons aussi écrit quelques lignes de code pour transformer l'inventaire de calcul OpenStack en données hosts