1 points par GN⁺ 4 시간 전 | 1 commentaires | Partager sur WhatsApp
  • 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 --dry permet 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, files et systemd sont importées en Python pour installer des paquets, déployer un template et recharger un service
    • Le code d’exemple installe les paquets nginx et certbot, puis déploie templates/nginx.conf.j2 vers /etc/nginx/sites-enabled/api
    • À la dernière étape, systemd.service("nginx", reloaded=True) recharge le service nginx
    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)
    
  • 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ées db-01.prod et db-02.prod
    • La commande $ pyinfra inventory.py deploy.py --limit web limite l’exécution à la cible web
    • 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
  • Vérification avant changement

    • --dry permet 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.yml de 16 lignes pour installer nginx, rendre un template et recharger le service via un handler
    • L’exemple pyinfra montre un deploy.py de 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 si cfg.will_change renvoie vrai pour le résultat de files.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)
    
  • 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

1 commentaires

 
GN⁺ 4 시간 전
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

    • Plus précisément, cela ressemble moins à un Ansible écrit en Python qu'à un interpréteur qui transforme Python en shell, avec les problèmes que cela implique
      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 sed
  • J'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

    • J'ai beaucoup utilisé Ansible, et pour moi c'est en réalité un langage de script déguisé
      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 python3 sur le serveur juste pour exécuter quelques commandes shell
    J'ai découvert pyinfra grâ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 confirmation
    Les 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.groups ne sont pas très élégantes non plus. operation(..., filter_group='web_server') est peut-être préférable
    Le pire reste que l'écriture de connecteurs personnalisés est vraiment pénible. Il semble falloir un pyproject.toml avec un entry point spécifique à pyinfra, et même avec uv, développer un connecteur interne ressemble à un cauchemar. On devrait pouvoir en faire un simple fichier Python ordinaire dans le projet

  • Cela 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

    • C'est un domaine intéressant. Je suis moi aussi en train de créer un outil de déploiement, et je l'utilise réellement pour des déploiements dans mon travail
      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

    • Il y a un flag —dry, affiché directement sur l'écran d'accueil de pyinfra
  • Pour 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