Ein effizientes internes DevOps-Team steht vor einem klassischen Dilemma: Jeder Entwickler braucht isolierte Testumgebungen, die schnell bereitgestellt und sicher bereinigt werden müssen. Doch manuelle Bereitstellungen sind langsam, Ressourcenverschwendung durch vergessene Umgebungen häufig, und echte Ausfalltests bleiben oft aus. Die Lösung? Eine selbst entwickelte Miniaturversion von Heroku – allerdings mit eingebauter Chaos-Engineering-Funktion und automatischer Selbstzerstörung. Das klingt nach einem eleganten Konzept, doch die Umsetzung auf Azure wurde zu einem echten Hindernislauf.
Eine DevOps-Sandbox, die sich selbst verwaltet
Das entwickelte System funktioniert als vollautomatisierte DevOps-Sandbox, die Entwicklern mit minimalem Aufwand isolierte Testumgebungen zur Verfügung stellt. Jede Umgebung wird nach einer definierten Laufzeit automatisch zerstört, während gleichzeitig die Möglichkeit besteht, gezielt Ausfälle zu simulieren – etwa Netzwerkprobleme, CPU-Spitzenlast oder Container-Abstürze. Die gesamte Infrastruktur läuft auf einer einzigen Azure-VM und lässt sich mit einem einzigen Befehl starten.
Kernfunktionen im Überblick
- Sofortige Bereitstellung: Ein einfacher Befehl reicht aus, um eine vollständige Testumgebung zu erstellen.
- Automatisierte Anwendungsbereitstellung: Apps werden direkt in die Umgebung deployt, ohne manuelle Eingriffe.
- Echtzeit-Überwachung: Ein Health-Monitor prüft alle 30 Sekunden den Zustand jeder aktiven Umgebung.
- Chaos-Engineering als Feature: Entwickler können gezielt Ausfälle simulieren, um die Robustheit ihrer Anwendungen zu testen.
- Automatische Bereinigung: Nach Ablauf der festgelegten Laufzeit (TTL) werden alle Ressourcen automatisch gelöscht.
Technische Architektur: Einfache VM, komplexe Logik
Die gesamte Lösung läuft auf einer einzigen Azure-Virtual-Machine und besteht aus fünf zentralen Komponenten:
Nginx als dynamischer Frontend-Router
Jede Testumgebung erhält automatisch einen eigenen Nginx-Konfigurationsblock. Bei der Erstellung einer neuen Umgebung wird die Konfiguration in nginx/conf.d/ geschrieben und der Nginx-Server neu geladen. Die Routing-Logik basiert auf Hostnamen, sodass jede Umgebung über eine eindeutige Subdomain erreichbar ist.
FastAPI-Steuerung: REST-API für alle Aktionen
Eine FastAPI-basierte REST-API fungiert als zentrale Schnittstelle für alle administrativen Aufgaben. Sie bietet sieben Endpunkte:
- Umgebungen erstellen und auflisten
- Logs abrufen und Zustände prüfen
- Gezielte Ausfälle simulieren (Crash, Netzwerkunterbrechung, CPU-Stress)
- Umgebungen zerstören
Die API ist über eine Swagger-Dokumentation unter /docs zugänglich und wird über einen einfachen Python-Webserver betrieben.
Bash-Skripte als Motor der Infrastruktur
Vier zentrale Bash-Skripte steuern die gesamte Logik:
create_env.sh: Erstellt Container, Netzwerke, Nginx-Konfiguration und Log-Routingdestroy_env.sh: Räumt alle Ressourcen sauber auf und archiviert Logssimulate_outage.sh: Führt Chaos-Tests durch (Container-Stopp, Netzwerkunterbrechung, CPU-Last)cleanup_daemon.sh: Ein Daemon, der alle 60 Sekunden abgelaufene Umgebungen löscht
Health-Monitor: Echtzeit-Überwachung in Python
Ein Python-Skript prüft alle aktiven Umgebungen alle 30 Sekunden über den /health-Endpunkt. Drei aufeinanderfolgende Fehlschläge markieren eine Umgebung als „degraded“ und können automatisch Maßnahmen auslösen.
Zustandsverwaltung: JSON-basierte Datensicherung
Alle Umgebungsmetadaten werden in JSON-Dateien unter envs/ gespeichert. Durch atomare Schreiboperationen (Temporärdatei + mv statt direkter Überschreibung) wird Korruption verhindert.
Die Deployment-Hölle: Warum Azure manchmal zum Gegner wird
Die Entwicklung der Plattform verlief zunächst reibungslos – bis es an die Bereitstellung auf Azure ging. Vier technische Hindernisse machten das Deployment zu einer echten Herausforderung.
Problem 1: Der falsche SSH-Schlüssel
Der erste Versuch, sich per SSH mit der VM zu verbinden, scheiterte mit der Fehlermeldung:
Warning: Identity file azureuser_key.pem not accessible: No such file or directory
Permission denied (publickey)Nach Überprüfung stellte sich heraus, dass der korrekte Schlüssel hng5-vm_key.pem hieß und sich im Download-Ordner befand. Doch selbst mit dem richtigen Pfad blieb die Verbindung verweigert: Der öffentliche Schlüssel stimmte nicht mit dem VM-Schlüssel überein. Die Lösung? Im Azure-Portal unter „Connect“ den SSH-Schlüssel der VM zurücksetzen. Eine klassische Ursache, die wertvolle Zeit kostete.
Problem 2: Azure-Firewall, die unsichtbar blockierte
Die Plattform lief lokal, doch der API-Endpunkt auf Port 5000 war von außen nicht erreichbar. Verschiedene Ansätze – NSG-Regeln anpassen, Nginx als Proxy nutzen, Container-Routing testen – scheiterten alle mit der Meldung „502 Bad Gateway“. Die Analyse mit ss -tlnp zeigte, dass der Port innerhalb der VM korrekt lauschte. Doch Azure blockierte den Traffic trotz korrekter NSG-Regeln.
Die Lösung kam durch einen Wechsel des Docker-Netzwerkmodus:
docker run -d \
--name sandbox-api \
--network host \
-v $(pwd):/app \
-v /var/run/docker.sock:/var/run/docker.sock \
-w /app \
devops-sandbox-api \
python3 platform/api.pyDurch --network host bindet der Container direkt an das VM-Netzwerk und umgeht damit Dockers Bridge-Netzwerk, das von Azures interner Firewall blockiert wurde.
Problem 3: Python-Namenskonflikt: „platform“ ist reserviert
Trotz korrektem Netzwerkmodus startete die API nicht:
ERROR: Could not import module "platform.api"Der Grund: platform ist ein eingebautes Python-Modul. Uvicorn versuchte, das Standardmodul statt der eigenen Datei platform/api.py zu importieren. Die Lösung bestand darin, die API direkt als Python-Skript auszuführen:
python3 platform/api.pyStatt über Uvicorn zu starten:
uvicorn platform.api:appEin einfacher, aber folgenreicher Fehler: Projekte sollten niemals nach Python-Standardmodulen benannt werden.
Problem 4: EOF-Probleme bei der Nginx-Konfiguration
Ein weiteres Hindernis trat bei der Erstellung von Nginx-Konfigurationsdateien auf. Die Verwendung von cat mit einem Here-Dokument führte zu Problemen:
# Dies führte zu fehlerhaften Konfigurationen:
cat > nginx/conf.d/api.conf << 'EOF'
server {
...
}
EOF # ← Dieses EOF wurde falsch interpretiertDie Terminal-Shell interpretierte das abschließende EOF als Teil der vorherigen Zeile. Die Lösung bestand im Einsatz von tee:
tee nginx/conf.d/api.conf > /dev/null << 'EOF'
server {
listen 8080;
location / {
proxy_pass
}
}
EOFAnschließend wurde die Konfiguration sofort überprüft:
cat nginx/conf.d/api.confEin scheinbar trivialer Fehler, der jedoch ohne systematische Validierung schwer zu debuggen war.
Fazit: Eine Plattform mit Zukunftspotenzial
Die entwickelte DevOps-Sandbox zeigt, wie interne Entwicklertools durch Automatisierung und Chaos-Engineering die Effizienz steigern können. Die gesammelten Erfahrungen mit Azure unterstreichen jedoch, wie wichtig gründliche Vorbereitung bei Cloud-Bereitstellungen ist. Die Plattform funktioniert nun stabil und bietet Entwicklern eine sichere, isolierte Umgebung für Tests und Experimente – inklusive der Möglichkeit, gezielt Ausfälle zu simulieren.
Die nächsten Schritte könnten die Integration weiterer Cloud-Ressourcen oder die Erweiterung um Multi-Region-Funktionen umfassen. Eines ist sicher: Die Kombination aus Selbstzerstörung, Chaos-Tests und automatisiertem Ressourcenmanagement ist ein vielversprechender Ansatz für zukünftige DevOps-Infrastrukturen.
KI-Zusammenfassung
Learn how a developer built a miniature Heroku with auto-destroying environments and chaos testing, then fought Azure’s hidden firewall and SSH pitfalls during deployment.