Der Ausgangspunkt.
Die On-Premise-Plattform verband eine Vue-Oberfläche, zwei Spring-Boot-Dienste, einen Python-Temporal-Worker, Temporal, Keycloak, PostgreSQL und MinIO. Sie verarbeitete Dokumente und KI-gestützte Workflows, doch die Umgebungen hatten keinen gemeinsamen, verlässlichen Setup-Weg.
Nur von einer Cloud-Migration zu sprechen, hätte das Ziel beschrieben, nicht die eigentliche Arbeit. Stateful und stateless Komponenten mussten bewusst verschoben, Demo und Produktion getrennt und der Wechsel zwischen zwei Produktionsslots kontrolliert werden.
Ich zerlegte die Änderung in vier verbundene Grenzen: Workload-Paketierung, verwaltete Daten, Umgebungskonfiguration und Releasekontrolle. So konnte „auf Kubernetes verschieben“ nicht zum gesamten Design werden.
Was das Design lösen musste.
Das neue Plattformmodell musste fünf Dinge sichtbar machen:
- Vue-, Spring-Boot-, Python-, Temporal- und Keycloak-Workloads brauchten ein gemeinsames Kubernetes-Deployment-Modell.
- Die Verantwortlichkeiten von PostgreSQL und MinIO mussten zu Cloud SQL und Cloud Storage wechseln, ohne die Änderung hinter weiteren Containern zu verstecken.
- Die wiederverwendbare Infrastruktur musste gemeinsam bleiben, während umgebungsspezifische Werte als prüfbare Eingaben sichtbar blieben.
- Demo-Pipeline und Produktionsrelease benötigten unterschiedliche Kontrollen, weil sie unterschiedliche betriebliche Risiken trugen.
- Der Produktionsrollout verlangte einen inaktiven Slot, Smoke-Tests und einen ausdrücklichen manuellen Wechsel.
Die Diagnose.
Der fragile Teil war kein einzelner Dienst. Es war der Weg vom Quellcode zu einer laufenden Umgebung. Wenn dieser Weg je Umgebung variiert, trägt jede Änderung versteckte Annahmen mit sich.
Ein reines Lift-and-shift hätte diese Annahmen nur an einem neuen Ort reproduziert. PostgreSQL und MinIO im neuen Cluster zu betreiben, hätte zudem Betriebsaufgaben erhalten, die Google Cloud an klareren verwalteten Grenzen übernehmen konnte.
Ich behandelte deshalb Reproduzierbarkeit und Reversibilität als zentrale Anforderungen. Terraform-Module definieren das Google-Cloud-Fundament, Helm paketiert die Kubernetes-Workloads und Umgebungswerte bleiben von den wiederverwendbaren Definitionen getrennt.
Das resultierende Plattformmodell.
GitLab CI startet den Produktionsweg, Cloud Build erstellt die auslieferbaren Images und Artifact Registry hält die Version für GKE. Das Deployment erreicht den inaktiven Blue/Red-Slot. Kubernetes-Readiness und Smoke-Test müssen erfolgreich sein, bevor ein Operator den Traffic umschaltet. Cloud SQL und Cloud Storage ersetzen die selbstverwalteten PostgreSQL- und MinIO-Verantwortlichkeiten.
Warum diese Technologien zur Migration passten.
Diese Entscheidungen fielen innerhalb eines bestehenden Produkts und eines festgelegten Google-Cloud-Ziels; sie waren kein Greenfield-Vergleich aller denkbaren Plattformen. Entscheidend war, welche Grenzen genau diesen Workload-Mix wiederholbar und betreibbar machten.
GKE als gemeinsame Grenze für die Workloads
- Warum
- Die Plattform verband bereits eine Vue-Oberfläche, Spring-Boot-Dienste, einen Python-Worker, Temporal und Keycloak. GKE gab diesen unterschiedlichen Workloads ein gemeinsames Modell für Deployment, Readiness und Blue/Red-Slots, während verwaltete Daten den Cluster verliessen.
- Was ich ausgeschlossen habe
- Eine Verteilung auf mehrere Serverless-Produkte hätte verschiedene Ausführungsmodelle in denselben Releaseweg gebracht; dauerhaft laufende VMs hätten mehr hostspezifischen Aufbau und Wartung bewahrt.
- Der Preis dafür
- Das Team übernimmt die Kubernetes-Betriebsoberfläche, den Cluster-Lebenszyklus und die Pflicht, Ressourcen, Readiness und Upgrades der Workloads ausdrücklich zu pflegen.
Terraform-Module für das Google-Cloud-Fundament
- Warum
- Wiederverwendbare Module hielten gemeinsame Infrastrukturdefinitionen zusammen und machten Umgebungsunterschiede zu sichtbaren, prüfbaren Eingaben. Das adressierte direkt den umgebungsspezifischen Aufbau, den die Migration beseitigen sollte.
- Was ich ausgeschlossen habe
- Konfiguration in der Konsole oder kopierte Templates hätten die erste Umgebung schneller erzeugt, doch spätere Änderungen wären schwerer prüfbar gewesen und jede Kopie hätte unabhängig abweichen können.
- Der Preis dafür
- Modulverträge, Provider-State und Versionswechsel verlangen Disziplin; selbst eine kleine Ausnahme muss modelliert werden, statt unbemerkt von Hand korrigiert zu werden.
Helm zur Paketierung der Kubernetes-Workloads
- Warum
- Helm lieferte eine Releaseeinheit für zusammengehörige Kubernetes-Ressourcen und einen kontrollierten Ort für Umgebungswerte, ohne die vollständige Workload-Definition für jeden Slot zu kopieren.
- Was ich ausgeschlossen habe
- Direkte Kubernetes-Manifeste wären für ein einzelnes Deployment einfacher gewesen. Kopien über Umgebungen und Blue/Red-Slots hinweg hätten gemeinsame Änderungen und beabsichtigte Unterschiede jedoch schwerer unterscheidbar gemacht.
- Der Preis dafür
- Templates und Werte schaffen eine zusätzliche Ebene; die gerenderte Ausgabe muss geprüft und jede Chart-Änderung so sorgfältig versioniert werden wie Anwendungscode.
Getrennte Verantwortlichkeiten für Cloud Build und GitLab CI
- Warum
- Cloud Build erzeugte die Images im Google-Cloud-Pfad, während GitLab CI Produktionsorchestrierung, Prüfung und die ausdrückliche Trafficentscheidung behielt. Die Trennung entsprach den unterschiedlichen Folgen von Artefakterstellung und Release.
- Was ich ausgeschlossen habe
- Eine einzige undifferenzierte Deploy-Pipeline wäre leichter zu beschreiben gewesen, hätte aber Demo- und Produktionskontrollen vermischt und Build, Rollout und Trafficwechsel zu einer gekoppelten Aktion gemacht.
- Der Preis dafür
- Zwei Systeme benötigen Zugangsdaten, Artefaktübergaben und Fehleranalyse über eine Grenze hinweg; ihre Verträge müssen aufeinander abgestimmt bleiben.
Betriebsregeln für ein umkehrbares Release.
Der Stack definiert den Weg; diese Regeln klären, wem State gehört, was als Nachweis gilt und wie Produktion ohne unumkehrbaren Sprung verändert wird.
Umgebungsunterschiede überprüfbar machen
Vor einem Release sind umgebungsspezifische Werte und Verantwortung für State gemeinsam sichtbar, einschliesslich Daten, Backup und Recovery. Ein Unterschied wird zum ausdrücklichen Input oder Übergabepunkt, nicht zur unsichtbaren Korrektur in einer laufenden Umgebung.
Der ZielkonfliktUnterschiede und Verantwortung zu prüfen, braucht Vorbereitung, verhindert aber, dass Konfigurationsdrift oder ungeklärte Recovery-Aufgaben erst beim Cutover auftauchen.
Den Kandidaten durchgängig prüfen
Ein Release wird vom gebauten Image bis in die inaktive Umgebung verfolgt und dort mit Readiness, Infrastruktursignalen und einem Smoke-Test geprüft. Kein einzelnes grünes Signal steht für den gesamten Weg.
Der ZielkonfliktDas dauert länger, als einen erfolgreichen Build als Beweis zu akzeptieren; der Smoke-Test bleibt bewusst begrenzt und beansprucht nicht, jeden Geschäftsablauf abzudecken.
Artefaktnachweis und Traffic-Hoheit trennen
Ein erfolgreicher Build erzeugt einen Kandidaten, gewährt ihm aber keinen Produktionszugang. Dasselbe Artefakt wird im inaktiven Blue/Red-Slot deployt und erprobt, während die Traffic-Umschaltung eine separate Aktion des Operators bleibt.
Der ZielkonfliktDiese Governance schafft Übergaben und verlangt, dass beide Slots bereit bleiben, verhindert aber, dass Build-Erfolg mit Release-Freigabe verwechselt wird.
Den Cutover ausdrücklich und umkehrbar machen
Traffic wechselt erst, wenn die Prüfungen sichtbar sind und ein Operator die Umschaltung freigibt. Der vorherige Slot bleibt der klare Rückweg, statt direkt überschrieben zu werden.
Der ZielkonfliktDas Gate schafft eine bewusste Pause, hält aber die letzte Produktionshoheit und den Rückweg sichtbar, wenn die Nachweise unvollständig sind.
Delivery und Prüfung.
Ich ordnete die Arbeit nach Abhängigkeit und Reversibilität: Google-Cloud-Fundament, Workload-Paketierung, ausgelagerte Umgebungswerte, Verlagerung der Datenverantwortung und danach der vollständige Releaseweg vor dem Produktionswechsel.
Demo und Produktion bleiben getrennt. Produktion läuft von GitLab CI über Cloud Build und Artifact Registry in den inaktiven GKE-Slot, statt die aktive Umgebung zu überschreiben.
Kubernetes-Readiness, Google-Cloud-Warnungen und Infrastruktursignale werden mit einem Smoke-Test vor dem Wechsel kombiniert. Das beweist nicht jeden Geschäftsablauf. Es zeigt, dass der Kandidat gesund genug für einen kontrollierten Cutover ist.
Das gelieferte Ergebnis.
Die Migration ersetzte einen umgebungsspezifischen On-Premise-Weg durch wiederverwendbare Infrastrukturmodule, paketierte Workloads, verwaltete Datendienste und zwei kontrollierte Produktionsslots.
Der nützliche Ausgang ist nicht einfach „läuft auf Google Cloud“. Es ist ein Releaseweg, der vor dem Deployment geprüft, vor dem Trafficwechsel verifiziert und für die nächste Umgebung wiederholt werden kann.
Ich versehe dieses Ergebnis nicht mit einer erfundenen Geschwindigkeits- oder Zuverlässigkeitszahl. Die belegbare Änderung ist strukturell: weniger umgebungsspezifische Annahmen, klare Betriebsverantwortung und eine reversible Produktionsentscheidung.
Organisation, Produkt, Endpunkte, Storage-Konfiguration, Kosten, Volumen und Liefertermine sind weggelassen. Komponenten und Releasesequenz stammen aus der Projektdokumentation.