1 Punkte von GN⁺ 4 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • Server-Automatisierungsaufgaben werden als Python-Code geschrieben und parallel über SSH ausgeführt, sodass Befehle ohne Agent idempotent ausgeführt werden
  • pyinfra wirbt damit, bei derselben Workload 6-mal schneller als Ansible zu sein, und nutzt gleichzeitige Ausführung auf Basis von gevent und SSH
  • Mit der Option --dry lässt sich vor der Anwendung der hostweise Änderungs-Diff prüfen; bei der tatsächlichen Ausführung kommen die Ergebnisse als paralleles Streaming zurück
  • Auf den Zielhosts werden nur Shell und SSH benötigt; es gibt keine Daemons, Statusdateien oder Control Plane
  • Hervorgehoben wird ein codezentrierter Ansatz, der Kontrollfluss nicht in YAML encodiert, sondern Schleifen und Bedingungen von Python direkt nutzt

Kernfunktionen und Ausführungsablauf

  • Automatisierung für Tausende Server

    • pyinfra ist ein Python-natives, agentenloses Automatisierungstool und führt Befehle per SSH aus
    • Bei der Befehlsausführung stehen Parallelität, Idempotenz und Geschwindigkeit im Vordergrund; für dieselbe Workload wird 6-mal schneller als Ansible beansprucht
    • Der Installationsbefehl lautet $ uv tool install pyinfra
    • Als genannte Grundlagen gelten MIT license, Python 3.10 oder höher, no agents und zero config
  • Beispiel für Deployment-Code

    • Die Operationen apt, files und systemd werden als Python-Code eingebunden, um Pakete zu installieren, Templates bereitzustellen und Services neu zu laden
    • Im Beispielcode werden die Pakete nginx und certbot installiert und templates/nginx.conf.j2 nach /etc/nginx/sites-enabled/api ausgerollt
    • Im letzten Schritt wird mit systemd.service("nginx", reloaded=True) der Dienst nginx neu geladen
    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)
    
  • Inventory und Ausführungsergebnisse

    • Das Inventory-Beispiel besteht aus Web-Hosts von web-01.prod bis web-23.prod sowie den Datenbank-Hosts db-01.prod und db-02.prod
    • Der Befehl $ pyinfra inventory.py deploy.py --limit web beschränkt die Ausführung auf das Ziel web
    • Die Ausgabereihenfolge umfasst das Laden des Inventorys, die gleichzeitige Fact-Erfassung, die Ausführung von deploy.py und anschließend die Zusammenfassung
    • Die Beispielzusammenfassung verzeichnet 23 erfolgreiche Hosts, 18 Änderungen, 0 Fehlschläge und insgesamt 2,1 Sekunden
  • Prüfung vor Änderungen

    • --dry zeigt zunächst den hostweisen Diff aller von pyinfra auszuführenden Änderungen
    • Bei der tatsächlichen Ausführung werden die Ergebnisse parallel gestreamt, einschließlich Änderungsanzahl und Laufzeit je Host
    • Die Beispielausführung verzeichnet bei 24 Hosts 18 mit Änderungen, 6 ohne Änderungen, 0 Fehlschläge und insgesamt 2,1 Sekunden

Merkmale, Vergleich mit Ansible und Grundsätze

  • Sechs Gründe für pyinfra

    • Just Python: Statt YAML und Jinja-in-YAML wird echter Kontrollfluss direkt in Python geschrieben
    • Concurrent SSH: Gleichzeitige Ausführung auf Basis von gevent und SSH, bei derselben Workload 6-mal schneller als Ansible
    • Diff before apply: Mit --dry werden alle Änderungen vorab angezeigt; idempotente Operationen werden bei erneutem Ausführen zu No-ops
    • 0 agents: Auf Hosts werden nur Shell und SSH benötigt; es gibt keine Daemons, Statusdateien oder Control Plane
    • Scale-ready: Funktioniert von 1 bis 10.000 Hosts und unterstützt parallele Ausführung sowie Streaming-Ausgabe in Echtzeit
    • Hackable: Eigene Operationen lassen sich in 10 Zeilen erstellen, und Verbindungen zu docker, lxc und k8s, die mit der Shell kommunizieren, sind möglich
  • Codevergleich zwischen Ansible und pyinfra

    • Das Ansible-Beispiel konfiguriert in 16 Zeilen playbook.yml die Installation von nginx, das Rendern eines Templates und das Neuladen des Dienstes über einen handler-basierten Ablauf
    • Das pyinfra-Beispiel schreibt denselben Ablauf in 8 Zeilen deploy.py als Python-Code
    • Im pyinfra-Beispiel wird systemd.service("nginx", reloaded=True) nur dann ausgeführt, wenn cfg.will_change im Ergebnis von files.template wahr ist
    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)
    
  • Leitsätze

    • Code > config: Schleifen bleiben Schleifen; Kontrollfluss wird nicht in YAML encodiert
    • Show, then do: Erst den Diff sehen, dann anwenden, um unerwartete Änderungen zu vermeiden
    • Stay out of the way: Direkte Ausführung über SSH ohne Agenten, Statusdateien oder Control Plane
    • Read like english: Operationen lesen sich in Form von Substantiv und Verb wie apt.packages, files.template, systemd.service
  • Startbefehl

    • Der Installationsbefehl lautet $ uv tool install pyinfra
    • Es wird dazu aufgefordert, das 5-Minuten-Quickstart zu lesen und den ersten Host zu deployen

1 Kommentare

 
GN⁺ 4 시간 전
Lobste.rs-Meinungen
  • pyinfra fühlt sich so an, wie Ansible ursprünglich hätte sein sollen. Statt YAML mit eingemischten Templates und nachträglich aufgesetztem Kontrollfluss kann man die Automatisierung direkt in Python schreiben
    Nachdem ich lange mit Ansible gearbeitet habe, wirkte das erfrischend, obwohl ich Ansible nicht einmal besonders gehasst habe

    • Genauer gesagt wirkt es weniger wie Ansible in Python als eher wie ein Interpreter, der Python in Shell umwandelt, und das bringt seine eigenen Probleme mit sich
      Ein hybrider Ansatz, der auch auf den Zielservern Python nutzt, wäre vermutlich besser. Dann gäbe es beim Aktualisieren von Dateien weniger Anführungszeichen-Hölle, und man würde auch Dinge wie die Regex-Grenzen von sed vermeiden
  • Ich mag pyinfra und wünschte, es würde breiter genutzt
    Alle Firmen, in denen ich bisher gearbeitet habe, nutzten Ansible, unabhängig davon, ob zusätzlich Terraform verwendet wurde, und nirgends war man bereit, die bestehende Automatisierung komplett mit einem Tool ohne Erfahrung im Team neu zu schreiben
    pyinfra setzt voraus, dass SysOps Python können, und ich persönlich finde, dass SysOps wenigstens eine Skriptsprache beherrschen sollten. Gerade bei Ansible kann man den YAML-Wildwuchs auch reduzieren, wenn man Module in Python schreibt, aber zumindest in Frankreich scheint das keine verbreitete Sichtweise zu sein

    • Ich habe viel mit Ansible gearbeitet und sehe es im Grunde als eine Skriptsprache unter anderem Namen
      Vielleicht ist das am Ende gar keine so hitzige Debatte
  • Ich habe Ansible im Homelab verwendet und fand es mit der Zeit immer frustrierender. YAML-Konfiguration ist schrecklich, alles fühlte sich wie ein Hack an, und die Geschwindigkeit war traurig. Dass man auf dem Server python3 braucht, nur um ein paar Shell-Befehle auszuführen, erschien mir ebenfalls unsinnig
    Über Google AI Mode bin ich auf pyinfra gestoßen, und in dem knappen Monat, in dem ich es genutzt habe, fühlte es sich deutlich frischer an. Vorteile sind: viel schneller als Ansible, Schleifen und Bedingungen lassen sich in Python schreiben, und auf dem Server braucht man ohne Rollen und verschachtelte Verzeichnisse nur eine Shell. Vor der Ausführung wird auf Basis des aktuellen Zustands ein Plan erstellt, und ohne -y wird auch noch eine Bestätigung eingeholt
    Nachteile sind, dass die eingebauten Aufgaben im Vergleich zu Ansible-Modulen nur eine kleine Teilmenge abdecken, der Code schnell zu Spaghetti werden kann und auch Dinge wie if 'web_server' in hosts.groups nicht besonders gut wirken. Vielleicht wäre operation(..., filter_group='web_server') besser
    Am schlimmsten ist, dass das Schreiben eigener Connectoren extrem mühsam ist. Es scheint ein pyproject.toml mit einem pyinfra-spezifischen Entry Point nötig zu sein, und selbst mit uv wirkt die Entwicklung interner Connectoren wie ein Albtraum. Das sollte einfach als normale Python-Datei innerhalb des Projekts möglich sein

  • Seit ein paar Tagen teste ich pyinfra als Deployment-Tool für mein Homelab, und im Vergleich zu Ansible gefällt mir bisher nicht einmal die Python-Syntax am besten, sondern die Geschwindigkeit
    Ansible fühlte sich für mich immer unerträglich langsam an

    • Das ist in diesem Bereich spannend. Ich baue auch gerade ein Deployment-Tool und nutze es in meinem Hauptjob bereits für reale Deployments
      Ich möchte damit an den meisten Stellen den Einsatz von Ansible und Salt ersetzen
  • Es ist interessant, dass sich Infrastructure as Code einmal im Kreis gedreht hat. Erst Skripte, dann YAML und nun wieder zurück zu ausgefeilteren Skripten
    Jeder Ansatz hat seinen passenden Punkt, und aus Sicht von Ansible-Nutzern sieht pyinfra ziemlich gut aus

  • Der entscheidende Grund für die Einführung von Ansible waren für mich Dry-Run- und Diff-Modus. So konnte ich sicher sein, dass keine unerwarteten Aktionen ausgeführt werden
    Bei der pyinfra-CLI scheint es so eine Option nicht zu geben. Vielleicht habe ich sie übersehen, weil ich kein alphabetisch sortiertes Referenzdokument mit allen Optionen gefunden habe

    • Es gibt ein —dry-Flag, und es wird direkt auf der Startseite von pyinfra angezeigt
  • Für Interessierte gibt es auch ein ähnliches, 14 Jahre altes Projekt von mir: https://github.com/sebastien/cuisine/tree/main
    Es arbeitet agentlos nur über SSH und legt eine Python-typische API über die grundlegenden Verwaltungsfunktionen, unterstützt aber keinen Dry-Mode

  • Wir verwenden Ansible zum Provisionieren von Ressourcen in OpenStack und erledigen den Rest mit pyinfra, und das funktioniert seit einigen Jahren ziemlich gut
    Der größte Nachteil ist, dass die Community klein ist und man Lösungen oft selbst schreiben muss. Zum Beispiel speichern wir die für Deployments nötigen Shared Secrets mit keyring + privy auf der Festplatte und haben ein paar Zeilen Code selbst geschrieben, um das OpenStack-Compute-Inventar in Hosts-Daten umzuwandeln