- 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
--drylä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,filesundsystemdwerden als Python-Code eingebunden, um Pakete zu installieren, Templates bereitzustellen und Services neu zu laden - Im Beispielcode werden die Pakete
nginxundcertbotinstalliert undtemplates/nginx.conf.j2nach/etc/nginx/sites-enabled/apiausgerollt - Im letzten Schritt wird mit
systemd.service("nginx", reloaded=True)der Dienstnginxneu 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) - Die Operationen
-
Inventory und Ausführungsergebnisse
- Das Inventory-Beispiel besteht aus Web-Hosts von
web-01.prodbisweb-23.prodsowie den Datenbank-Hostsdb-01.produnddb-02.prod - Der Befehl
$ pyinfra inventory.py deploy.py --limit webbeschränkt die Ausführung auf das Zielweb - Die Ausgabereihenfolge umfasst das Laden des Inventorys, die gleichzeitige Fact-Erfassung, die Ausführung von
deploy.pyund anschließend die Zusammenfassung - Die Beispielzusammenfassung verzeichnet 23 erfolgreiche Hosts, 18 Änderungen, 0 Fehlschläge und insgesamt 2,1 Sekunden
- Das Inventory-Beispiel besteht aus Web-Hosts von
-
Prüfung vor Änderungen
--dryzeigt 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
--drywerden 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.ymldie Installation vonnginx, das Rendern eines Templates und das Neuladen des Dienstes über einen handler-basierten Ablauf - Das pyinfra-Beispiel schreibt denselben Ablauf in 8 Zeilen
deploy.pyals Python-Code - Im pyinfra-Beispiel wird
systemd.service("nginx", reloaded=True)nur dann ausgeführt, wenncfg.will_changeim Ergebnis vonfiles.templatewahr 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) - Das Ansible-Beispiel konfiguriert in 16 Zeilen
-
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
- Der Installationsbefehl lautet
1 Kommentare
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
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
sedvermeidenIch 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
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
python3braucht, nur um ein paar Shell-Befehle auszuführen, erschien mir ebenfalls unsinnigÜber Google AI Mode bin ich auf
pyinfragestoß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-ywird auch noch eine Bestätigung eingeholtNachteile 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.groupsnicht besonders gut wirken. Vielleicht wäreoperation(..., filter_group='web_server')besserAm schlimmsten ist, dass das Schreiben eigener Connectoren extrem mühsam ist. Es scheint ein
pyproject.tomlmit einem pyinfra-spezifischen Entry Point nötig zu sein, und selbst mituvwirkt die Entwicklung interner Connectoren wie ein Albtraum. Das sollte einfach als normale Python-Datei innerhalb des Projekts möglich seinSeit 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
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
—dry-Flag, und es wird direkt auf der Startseite von pyinfra angezeigtFü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