In vielen cloudbasierten Softwareprojekten wird ein CI/CD-Prozess aufgesetzt und gepflegt, um Anwendungen effizient, sicher und produktiv in Cloud-Umgebungen auszurollen.
Im Mittelpunkt steht dabei meist die Cloud- bzw. Remote-Seite des CI/CD-Prozesses. Über die Phase, die unmittelbar davor liegt, sprechen wir dagegen selten: die lokale Entwicklung und das Testen auf dem Laptop des Entwicklers.
In diesem Beitrag zeige ich, warum viele gängige Methoden zur lokalen Entwicklung alles andere als ideal sind, und stelle anschließend einen alternativen, cloud-nativen Ansatz vor, der Ihre Produktivität – oder die Ihrer Engineers – spürbar steigert. 🌤
Foto von Christina @ wocintechchat.com auf Unsplash
👨🏼💻 Lokale Entwicklung
Eine universelle Best Practice gibt es nicht – sie hängt immer von den Anforderungen der jeweiligen Organisation oder des Projekts ab. Typischerweise sieht ein CI/CD-Flow aber ungefähr so aus:

Schauen wir uns an, was direkt vor Schritt 1 passiert: die lokale Entwicklung.
In den meisten Fällen findet sie auf dem Rechner des Entwicklers statt. Also: planen, designen, Code schreiben, Tests schreiben, Tests ausführen, vielleicht ein PoC – und manchmal auch manuell prüfen, ob alles wie erwartet läuft.
Viele Entwicklungsprojekte stecken viel Aufwand in lokale Setups, die die Cloud-Umgebung nachbilden, um zu prüfen, ob ein neues Feature oder ein Bugfix sauber funktioniert – ohne andere Features oder Logik zu beeinträchtigen.
Solche Setups dienen vor allem dazu, bestimmte automatisierte Tests auszuführen (Systemtests, Integrationstests oder End-to-End-Tests). Und wer mag, kann darin natürlich auch manuell testen 😏.
Daneben werden lokale Umgebungen häufig zum Debuggen genutzt. Manche Entwickler sind eingefleischte Anhänger dessen, was ich "Debug-Driven Development" nenne – aber Debugging kann mehr leisten als das. Es hilft Ihnen, einem hartnäckigen Bug auf den Grund zu gehen oder einen komplexen Ablauf besser zu verstehen.
Gängige Methoden für die lokale Entwicklung
Angenommen, Sie arbeiten an einem Projekt mit mehreren Microservices, die auf Kubernetes deployt werden. Hier sind einige Ansätze, die mir in der Praxis immer wieder begegnen:
- Docker-Compose-Methode: Pflege von docker-compose-Manifests (im Grunde Duplikate der vorhandenen K8s-YAML-Manifests), die Ihre Services und externe Abhängigkeiten für lokale Tests hochfahren.
- Lokale K8s-Methode: Betrieb eines lokalen Kubernetes-Clusters per minikube/k3s/kind/etc. mit lokalem Deployment Ihrer Services, ergänzt durch eine Reihe von Skripten.
- Testsuite-Methode: Makefiles oder Bash-Skripte starten pro Service eine Integrationstestsuite, in der Drittanbieter-Abhängigkeiten lokal als Container über Docker hochgefahren werden (dockertest ist hier zum Beispiel eine beliebte Wahl).
All das sind valide Wege, um Ihre Anwendung lokal auszuführen und zu testen.
Nachteile gängiger Methoden zur lokalen Entwicklung
Diese Ansätze haben aber auch Schwächen:
Fehlende lokale Unterstützung von Drittanbietern
Manche Cloud-Abhängigkeiten von Drittanbietern lassen sich schlicht nicht lokal betreiben. In manchen Fällen können Sie die APIs per Mocking/Stubbing emulieren, doch das verursacht hohen Pflegeaufwand und bildet die Realität nicht wirklich ab. Im Grunde mogeln Sie sich da durch. Was passiert zum Beispiel, wenn eine Ihrer Datenbankabfragen fehlerhaft ist? Wie sollen Sie das beim Testen oder Debuggen aufdecken, wenn Sie gar nicht mit einer echten DB-Instanz "sprechen"?
Ressourcenhunger
Bei ressourcenintensiven Anwendungen kommt Ihr Laptop schnell an seine Grenzen. Ein Beispiel: Sie führen einen Stresstest durch, um ein Memory Leak zu reproduzieren. Oder ein Bug tritt nur auf, wenn 20 Replikate Ihrer Anwendung gleichzeitig laufen. Am Ende reagiert Ihr Laptop kaum noch 😅. Das geht direkt zulasten der Produktivität.
Abstürze beim Debuggen
Wenn Sie einen schwer reproduzierbaren Bug debuggen wollen, der nur alle paar Tage auftritt, kann Ihr Rechner zwischendurch herunterfahren oder in den Ruhezustand wechseln – und schon fangen Sie wieder bei null an.
Keine Single Source of Truth
Bei der Docker-Compose-Methode verstoßen Sie gegen das Prinzip der "Single Source of Truth", weil Sie mehrere Repräsentationen Ihrer Umgebungen parallel pflegen müssen.
Integrationstests ≠ echte Integration
Bei der Testsuite-Methode sind Integrationstests zwar sinnvoll und bringen viele Vorteile (auch lokal), aber sie sind nicht dasselbe wie die Integration Ihrer Änderung in eine echte Cloud-Umgebung. Bestimmte Integrations- und Deployment-Probleme bleiben so unentdeckt – etwa Netzwerkprobleme zu anderen Services, Konfigurationsfehler oder Boot-Crashes.
Die genannten Nachteile trüben Ihre Entwicklungserfahrung und schmälern die Produktivität. Häufig spiegeln sie zudem nicht die Realität wider (klassischer Fall von "It works on my machine!") und liefern damit nur wenig Mehrwert.
Gibt es einen besseren, moderneren Weg für die lokale Entwicklungsphase – einen, der Produktivität und Usability steigert? Ja, den gibt es.
☁️ **_Cloud-native Entwicklerumgebungen_**
Werfen wir nun einen Blick auf entfernte, cloud-native Umgebungen.
Wenn Sie Ihre lokale Umgebung in eine Remote-Umgebung verlagern, sind die genannten Probleme passé. Gleichzeitig heben Sie Ihre Entwicklungserfahrung auf ein modernes, zuverlässiges, cloud-natives Niveau.
Wie funktionieren cloud-native Entwicklerumgebungen?
Sie stellen jedem Entwickler eine eigene Cloud-Umgebung bereit, die ein Replikat Ihrer Entwicklungs- bzw. Produktionsumgebung ist (nicht zu 100 %, aber nah genug dran).
Mit diesem Ansatz hat jeder Entwickler im Team die Freiheit, seine Umgebung so zu nutzen, wie es am besten passt: zum Testen neuer Features und Bugfixes, zum Reproduzieren von Bugs oder einfach zum Experimentieren und Lernen. Und das alles in einer Umgebung, die der Produktion sehr nahekommt. ✌️
Ihr Tooling drumherum lässt sich so anpassen, dass diese Umgebungen noch wertvoller werden – etwa indem Sie manuelle oder automatisierte Tests ausführen oder Produktionstraffic in die persönlichen Umgebungen "spiegeln".
Ein weiterer Vorteil: Live-Remote-Debugging in diesen Umgebungen, vollständig isoliert und ohne andere Umgebungen zu beeinträchtigen. Dafür gibt es bereits ausgereifte Tools von der Stange (im nächsten Kapitel sehen wir uns ein Beispiel an).
Pluspunkte für Produktivität, Wartbarkeit und Zuverlässigkeit
Es gibt viele gute Gründe, auf cloud-native Entwicklerumgebungen umzusteigen. Hier meine Top 8.
Sie werden:
- Ihre vorhandenen K8s-YAML-Manifests wiederverwenden, ohne doppelte Deployment-Konfigurationen pflegen zu müssen (DRY-Prinzip 🌵).
- genauso in eine Cloud-Umgebung deployen wie in Dev/Prod – nur mit zusätzlicher Isolation.
- nicht mehr von Ihrer lokalen Hardware abhängig sein. Cloud-Infrastruktur lässt sich problemlos hochskalieren, wenn Tests viele Ressourcen brauchen, und am Wochenende wieder herunterfahren.
- langlaufende Tests starten können, ohne Sorge, dass Ihr Laptop herunterfährt oder in den Ruhezustand wechselt.
- Integrationsprobleme früh erkennen, weil Sie mit echten Cloud-Service-APIs arbeiten und nicht mit Mocks (z. B. mit PubSub, Cloud SQL, Datastore und vielen weiteren Cloud-Diensten).
- von der eingebauten Cloud-Infrastruktur für Monitoring, Alerting, Profiling, Tracing und Log-Aggregation profitieren – genauso wie in der Produktion.
- Zeit sparen, weil Sie nicht ständig komplexe Setup-Skripte ausführen müssen. Die Cloud ist schnell. Ihre Umgebung steht bereit, wenn Sie sie brauchen.
- diese Umgebungen nutzen, um Kubernetes praxisnah zu lernen (falls Sie Einsteiger sind), ohne andere Umgebungen zu beeinflussen.
Und nicht nur Entwickler profitieren – auch DevOps- und SRE-Engineers können Infrastrukturänderungen in ihrer eigenen Umgebung erproben, bevor sie geteilte Umgebungen anfassen.
🙋♂️ Moment, ich habe eine Frage!
Explodiert dadurch nicht meine Cloud-Rechnung?
Der erste Reflex ist, für jeden Entwickler ein vollständig getrenntes, unabhängiges Replikat der Cloud-Instanzen aufzusetzen, isoliert über Projekte hinweg, wobei jedes Projekt ein Replikat Ihrer Infrastruktur enthält.
Das ist grundsätzlich gute Praxis, vor allem aus Sicherheitssicht, weil es eine saubere Isolation gewährleistet. Allerdings können die Kosten dieses Ansatzes problematisch werden – besonders, wenn Ihr Unternehmen oder Team wächst.
Da es um Entwicklungsumgebungen geht, die in vielen Fällen ohnehin von der Produktion getrennt sind, können Sie hier einen Kompromiss zwischen Kosten und Sicherheit eingehen.
Hinweis: Dieser Trade-off zwischen Sicherheit und Kosten fällt je nach Organisation und Anforderungen unterschiedlich aus – machen Sie sich die Konsequenzen bewusst. Dieser GKE Security Guide kann dabei helfen.
Wie sieht dieser Kompromiss konkret aus? Sie können Multi-Tenant-Funktionen Ihrer Cloud-Dienste nutzen, um Kosten zu sparen, indem Sie Ressourcen zwischen Umgebungen teilen.
Das nennt sich häufig "Soft Multi-Tenancy": "Soft" deshalb, weil das Risiko begrenzt bleibt, indem mehrere Nutzer derselben "vertrauenswürdigen" Organisation Ressourcen gemeinsam nutzen.
Beispiel: Alle Entwickler eines Teams, die an einer Anwendung arbeiten, teilen sich einen K8s-Cluster, wobei jeder Entwickler den gesamten Anwendungs-Stack in seinem eigenen K8s-Namespace repliziert hat.
Ein anderes Beispiel: Alle Entwickler teilen sich eine einzige DB-Instanz, in der jeder einen eigenen DB-User, ein eigenes Schema und eigene Tabellen hat.
Genau diesen Ansatz zeigen wir im nächsten Kapitel in einer Demo.
Ist das nicht aufwendig einzurichten und zu pflegen? 🤕🥸
Eigentlich nicht! Sie können (und sollten) das Ganze mit Infrastructure as Code und GitOps-Prinzipien automatisieren und einfach reproduzierbar machen.
Sobald die gesamte Konfiguration als Code beschrieben ist, ist das Anlegen oder Löschen einer persönlichen Umgebung eine Sache von wenigen Klicks. Und weil der Prozess automatisiert ist, bleibt weniger Raum für menschliche Fehler.
Warum gehört das nicht in den Scope der Entwicklungsumgebung? 🤔
Die klassische Entwicklungsumgebung ist nicht isoliert – sie wird von allen Entwicklern gemeinsam genutzt. Sie mergen Ihren Code, Ihre Kollegin mergt zur gleichen Zeit ihren Code, und am Ende ist es ein Schmelztiegel. Sobald Ihr Team wächst, lässt sich in einer geteilten Umgebung kaum noch sinnvoll debuggen oder experimentieren.
Außerdem ist die Phase der Entwicklungsumgebung schon zu spät dran: Sie haben den PR bereits erstellt, das Code-Review durchlaufen und gemergt. Erst dann stellen Sie fest, dass Ihre Änderungen den Service sofort zum Absturz bringen. Das ist ein Blocker und erfordert Revert, Rollback oder Hotfix – zeitraubend für Sie und Ihre Kolleginnen und Kollegen.
Persönliche oder ephemere Umgebungen? 👀
Die einfache Antwort: Das entscheiden Sie.
Im Kern gilt: Bei persönlichen Umgebungen widmen Sie eine Umgebung dauerhaft einer bestimmten Person. Bei ephemeren Umgebungen erstellen Sie eine Umgebung für eine konkrete Änderung (die wieder verschwindet, sobald die Änderung gemergt ist).
Mein Kollege
hat einen großartigen Artikel zu ephemeren Umgebungen geschrieben – schauen Sie dort unbedingt rein.
Sie können natürlich auch beides kombinieren – aber das dürfte für die meisten Anforderungen Overkill sein.
In Teil 2 zeige ich anhand einer Beispielarchitektur, wie ein solches Setup mit Terraform, ArgoCD und Telepresence aussehen kann. Hier geht es zu Teil 2!