GOOGLE CLOUD → STACKIT · TUTORIAL
GCP-Terraform zu STACKIT: der Migrationsablauf
StackToIT liest Ihr Terraform mit dem Google-Provider offline und ohne Google-Cloud-Konto und schreibt einen STACKIT-Entwurf samt der Liste der Entscheidungen, die es Ihnen nicht abnehmen kann. Dieses Tutorial lässt eine Demo-Umgebung zweimal durchlaufen: zuerst unverändert, dann mit der fehlenden Variable und der ersten Antwort. Sie sehen, was die Konsole meldet, welche Dateien Sie öffnen, welche Blöcke der Lauf schreibt und was vor einem Plan noch eine Person tun muss.
Erster Lauf: ein Befehl, eine Zusammenfassung
Eine für diese Seite geschriebene Demo-Umgebung, am 4. November 2026 mit StackToIT bewertet, Google-Provider auf 8.4.0 festgelegt: ein Netzwerk mit einem Subnetz, eine Firewall-Regel, eine virtuelle Maschine, ein Bucket und eine Cloud-SQL-Instanz mit Benutzer. Oben der Befehl mit gekürztem Ausgabepfad, unten ausgewählte Zeilen der Konsolenzusammenfassung, wörtlich. Der Lauf erfolgte ohne die optionale Quellvalidierung, weil kein Provider-Mirror vorlag.
stacktoit assess . ./stacktoit-out --offline --no-validateSource 7 resources · 6 units · visibility: Variable unresolved
Migration 5 drafted · 1 need no resource (of 6 units the draft considered)
Attention 3 decisions to make (1 of them with the draft's DEFAULT to confirm or change, 1 of the 3 holds plan steps) · 5 units to review · 6 open requests (2 block the draft, marked in inputs-template.yaml)Sieben Ressourcen, sechs Einheiten
Die Umgebung enthält sieben Terraform-Ressourcen. Der Lauf fasst sie zu sechs Einheiten zusammen, weil der Cloud-SQL-Benutzer zur Einheit seiner Instanz gehört. Jede Einheit wird einzeln klassifiziert; der Plan wird also pro Einheit gelesen, nicht pro Datei.
Keine Verbindung zu Google Cloud
Laut StackToIT-Dokumentation wird die Google-Cloud-Eingabe aus Terraform- und OpenTofu-Root-Modulen gelesen; das Werkzeug verbindet sich nicht mit einem Google-Cloud-Projekt. Der Lauf braucht Ihren Code und die Variablenwerte, keine Zugangsdaten.
Die Variable ohne Wert
db_password ist sensibel und hat keinen Standardwert, deshalb meldet der Lauf die Quelle als „Variable unresolved“. Er hält fest, dass dies die Bewertung nicht stoppt und nie ein Wert abgefragt wird. Die Einheit, die die Variable liest, lässt sich erst vollständig bewerten, wenn eine Variablendatei sie liefert.
Warum alle Einheiten bei mittlerer Konfidenz stehen
Der Demo-Umgebung fehlt eine Lock-Datei; daher kann der Lauf nicht belegen, welche Version des google-Providers ein Plan verwenden würde. Er sagt das einmal für die ganze Umgebung und deckelt die Konfidenz aller sechs Einheiten auf mittel. Laut Lauf gilt die Deckelung, bis eine eingecheckte .terraform.lock.hcl die genaue Version festlegt.
Zweiter Lauf: Variable und erste Antwort ergänzen
Der erste Lauf hat review/inputs.yaml geschrieben. Die erste Gruppe enthält die Anfragen, die den Entwurf ändern, sobald sie beantwortet sind. Links die Anfrage nach der Zielregion, wie die Vorlage sie schreibt, mit leerem Wert. Danach der Befehl des zweiten Laufs (Ausgabepfad gekürzt), die gelesene Variablendatei und dieselben zwei Konsolenzeilen danach. Die Antwort eu01 wurde in eine Kopie der Datei eingetragen; die Variablendatei enthält einen Platzhalter, kein echtes Geheimnis.
# target.region (TARGET_SELECTION, request state OPEN)
# needed: The STACKIT region the migrated estate is built in.
- id: INP-TSE-1eaf5b60fa62
kind: TARGET_SELECTION
topic: target.region
scope:
profile: default
# options: eu01 | eu02
value: "" # pick one of the options abovestacktoit assess . ./stacktoit-out2 --offline --no-validate \
--var-file ./vars.tfvars \
--inputs ./inputs.yamldb_password = "demo-only-not-a-real-secret"Source 7 resources · 6 units · visibility: Complete
Attention 3 decisions to make (1 of them with the draft's DEFAULT to confirm or change, 1 of the 3 holds plan steps) · 5 units to review · 4 open requestsQuelle vollständig, offene Anfragen von sechs auf vier
Mit der Variablendatei gilt die Quelle als vollständig. Die beiden Anfragen, die den Entwurf blockierten, Region und Variable, sind geschlossen; vier offene Anfragen bleiben. Die Vorlage bindet jede Antwort über Felder, die Sie nicht ändern dürfen, an diese Quelle; ein leer gelassener Platzhalter wird nie als Standardwert gewertet.
Das Terraform blieb gleich
Der Vergleich der terraform-Ordner beider Läufe zeigt genau einen Unterschied: Lauf-Kennung und Quell-Digest in terraform/README.md. Die Variable region hatte ohnehin den Standardwert eu01. Antworten schreiben den Entwurf nicht immer um; hier haben sie den Stand des Plans verändert.
Antworten gehören außerhalb des Lauf-Ordners
Die Dokumentation rät, fertige Antworten außerhalb des erzeugten Berichtsordners zu pflegen und beim nächsten Lauf mit --inputs zu übergeben. Laut Dokumentation verschiebt ein erneuter Lauf mit demselben Ausgabeordner den früheren Lauf standardmäßig in einen Ordner previous-<Lauf-ID>. Für diese Seite lief der zweite Durchgang in einen eigenen Ordner, ./stacktoit-out2, damit sich beide Läufe nebeneinander vergleichen lassen.
Welche Datei welche Frage beantwortet
Pfade im Ausgabeordner des zweiten Laufs. Alle existieren im Demo-Lauf; öffnen Sie sie in dieser Reihenfolge.
- index.html
- Zusammenfassung und die zu treffenden Entscheidungen. Hier beginnen.
- assessment.json
- Pro Einheit: Klasse, Konfidenz, Zielservice, Begründung und Befunde.
- terraform/
- Der STACKIT-Terraform-Entwurf, eine Datei pro Bereich (Netzwerk, Sicherheit, Compute, Daten, Storage) sowie variables.tf und terraform.tf.
- terraform/README.md
- Was der Entwurf enthält, welche Dienste zuerst zu aktivieren sind, die Sicherheits-Checkliste des Ziels und was nicht übernommen wird.
- engineering/not-carried.csv
- Jede Quelleigenschaft, die der Entwurf nicht übernimmt, Eigenschaft für Eigenschaft.
- migration/technical-sequencing.md
- Wellen, berechnet aus den Abhängigkeiten zwischen den Einheiten.
- execution/
- Dateien für den Betrieb: manuelle Schritte, OpenTofu-Schritte und Prüfungen.
- review/
- Die Antwortvorlagen: inputs.yaml, decisions.yaml und die Datei mit den Zielwerten.
So wurde die Demo-Umgebung klassifiziert
| Google-Cloud-Ressource | STACKIT-Ziel | Klasse |
|---|---|---|
| google_compute_network | Keine Ressource: jedes Subnetz wird zu einem Netzwerk im Projekt | Rekonfigurieren |
| google_compute_subnetwork | stackit_network mit demselben IPv4-Präfix | Rekonfigurieren |
| google_compute_firewall | stackit_security_group mit einer Regel pro Allow-Regel | Rekonfigurieren |
| google_compute_instance | stackit_server mit Netzwerkschnittstelle | Rekonfigurieren |
| google_sql_database_instance mit Benutzer | stackit_postgresflex_instance und stackit_postgresflex_user | Replatforming |
| google_storage_bucket | stackit_objectstorage_bucket | Rekonfigurieren |
Klassen, wie der Lauf sie entschieden hat, durchgehend mit mittlerer Konfidenz. Der Netzwerk-Container braucht keine STACKIT-Ressource; der Entwurf sagt das und zählt ihn als eine Einheit ohne Ressource.
Netzwerk, Firewall und Server, umgesetzt
Erster Ausschnitt: Firewall-Regel und virtuelle Maschine aus der Eingabe. Danach die Blöcke, die die Engine für Netzwerk, Security Group mit Regel und Server geschrieben hat, ein Ausschnitt je Datei; die Prüfkommentare über jedem Block in der Datei sind hier weggelassen, ebenso der Interface-Block und die Datenbank.
resource "google_compute_firewall" "web" {
name = "allow-web"
network = google_compute_network.portal.name
direction = "INGRESS"
allow {
protocol = "tcp"
ports = ["443"]
}
source_ranges = ["0.0.0.0/0"]
target_tags = ["web"]
}
resource "google_compute_instance" "web" {
name = "portal-web-1"
machine_type = "e2-standard-4"
zone = "europe-west3-a"
tags = ["web"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-12"
size = 50
}
}
network_interface {
subnetwork = google_compute_subnetwork.app.id
}
}resource "stackit_network" "app" {
project_id = var.project_id
name = "app"
ipv4_prefix = "10.20.0.0/24"
ipv4_nameservers = var.default_ipv4_nameservers
}resource "stackit_security_group" "web" {
project_id = var.project_id
name = "allow-web"
}
resource "stackit_security_group_rule" "web_allow_web" {
project_id = var.project_id
security_group_id = stackit_security_group.web.security_group_id
direction = "ingress"
ether_type = "IPv4"
ip_range = "0.0.0.0/0"
port_range = {
max = 443
min = 443
}
protocol = {
name = "tcp"
}
}resource "stackit_server" "web" {
project_id = var.project_id
name = "portal-web-1"
machine_type = var.web_machine_type
availability_zone = var.availability_zone
boot_volume = {
source_type = "image"
source_id = var.web_image_id
size = 50
delete_on_termination = true
}
network_interfaces = [stackit_network_interface.web_1.network_interface_id]
}Tags werden zu einer ausdrücklichen Entscheidung
Die Firewall-Regel wählt Server über das Netzwerk-Tag web aus. STACKIT-Security-Groups kennen keinen Tag-Selektor; der Entwurf legt daher Gruppe und Regel an und lässt die Zuordnung offen: Sie entscheiden, welche Netzwerkschnittstellen die Gruppe führen. Der Lauf nennt das als erste nächste Aktion und weist sie dem Security Architect zu.
Priorität und Richtlinienebenen werden nicht übernommen
STACKIT kennt keine Regelpriorität, und der Scan sieht keine Organisations- oder Ordnerrichtlinie, die die Quelle zusätzlich einschränken könnte. Die Kommentare im Entwurf halten fest, dass die geschriebenen Regeln das erlauben, was die gescannten Regeln erlauben, und mehr erlauben können, als die Quelle tatsächlich zulässt.
Zone und Image liegen bei Ihnen
Die Quellzone wird nicht übernommen. Der Server liegt in einer Zonenvariable; Maschinentyp und Image sind Variablen ohne Standardwert, in deren Beschreibung die Quellwerte stehen.
Der Ablauf der Reihe nach
Provider festlegen, Lock-Datei einchecken
Deklarieren Sie die google-Version in required_providers und halten Sie .terraform.lock.hcl beim Code. Ohne Lock-Eintrag warnt der Lauf, die Version sei nicht belegt, und deckelt die Konfidenz auf mittel.
Offline bewerten
Führen Sie den Befehl im Ordner mit dem Root-Modul aus, nicht in einem Unterordner einer größeren Konfiguration. Mit der Offline-Option nutzt der Lauf nur lokale Dateien und Caches und stellt keine ausgehenden Anfragen.
Variablen und Antworten liefern
Geben Sie für jede sensible Eingabe eine Variablendatei an, zum Beispiel mit der Option var-file, und füllen Sie die value-Zeilen der Inputs-Datei. Ein leer gelassener Platzhalter bleibt eine offene Anfrage und ist kein Fehler.
Die erste nächste Aktion lesen
Die Konsole endet mit einer nächsten Aktion und einer verantwortlichen Rolle. Hier soll der Security Architect benennen, für welche Server eine Security Group gedacht ist.
Den Entwurf mit den Verantwortlichen prüfen
Öffnen Sie terraform/ und engineering/not-carried.csv mit den Verantwortlichen für Plattform, Netzwerk und Sicherheit. Jeder Block trägt einen kurzen Kommentar zu Herkunft, Werten und Nicht-Übernommenem.
In einem Testprojekt planen
Führen Sie tofu init, validate und plan gegen ein Testprojekt aus. Laut README des Entwurfs führt StackToIT nie apply aus.
Was Sie vor dem ersten Plan ändern
Vier Variablen ohne Standardwert
postgresflex_storage_class, project_id, web_image_id und web_machine_type haben keinen Standardwert. Die Zielwerte-Datei in review/ führt sie mit ihren Beschreibungen auf.
Datenbankzugriff
Die Cloud-SQL-Instanz ist öffentlich erreichbar und hat ein autorisiertes Netzwerk. Der Entwurf beschränkt die STACKIT-Instanz über eine Zugriffsliste mit demselben CIDR, eine Variable, die Sie ändern können. Das Passwort des Benutzers wird nicht kopiert: STACKIT erzeugt es, und Sie geben das neue an die Anwendung weiter.
Rollen des Datenbankbenutzers
Cloud-SQL-Benutzer sind Mitglied einer Superuser-Rolle, die der Entwurf nicht übernimmt. Die Rollenvariable steht standardmäßig nur auf login; wählen Sie die Rollen pro Benutzer.
Egress und DNS
Der Lauf kann nicht belegen, ob das Quell-Subnetz eine Internetroute hatte, behält das STACKIT-Standard-Gateway bei und benennt den Zweifel. Als Nameserver gelten standardmäßig die Adressen des STACKIT-Resolvers; private Namen brauchen einen eigenen DNS-Server.
Zugangsdaten und State
Die README des Entwurfs empfiehlt Workload Identity Federation für den Provider und weist darauf hin, dass State-Locking über ein S3-Backend auf STACKIT Object Storage ohne Wirkung ist; führen Sie apply immer nur aus einem Job gleichzeitig aus oder nutzen Sie das PostgreSQL-Backend, auf das der Provider verweist.
Bucket mit Versionierung
Der Bucket hat Versionierung aktiv. Die Bucket-Ressource hat kein Versionierungsattribut; Sie aktivieren sie über die S3-API, sobald der Bucket existiert.
Fragen von Plattformteams
Brauchen wir Google-Cloud-Zugangsdaten für den Lauf?
Nein. Laut StackToIT-Dokumentation wird die Google-Cloud-Eingabe aus Terraform- und OpenTofu-Root-Modulen mit Google-Provider gelesen; eine Verbindung zu einem Google-Cloud-Projekt gibt es nicht.
Warum meldet der Lauf die Quelle als nicht aufgelöst?
Eine sensible Variable ohne Standardwert und ohne Wert lässt sich nicht lesen. Der Lauf nennt Variable sowie Datei und Zeile, die sie liest, bewertet weiter und bittet um eine Variablendatei; den Wert selbst fragt er nie ab.
Verändern die Antworten das Terraform?
Manchmal. In dieser Demo hat die Regionsantwort eine blockierende Anfrage geschlossen, ohne eine Zeile des Entwurfs zu ändern, weil der Standardwert schon passte. Antworten, die einen vom Entwurf verwendeten Wert festlegen, schreiben die betroffenen Blöcke beim nächsten Lauf um.
Können wir den Entwurf direkt anwenden?
Nein. Er ist ein Vorschlag zur Prüfung. Füllen Sie die Variablen, entscheiden Sie, welche Schnittstellen die Security Group erhalten, planen Sie in einem Testprojekt und lassen Sie die offenen Entscheidungen zuerst von einem Architekten klären.
Quellen
Ihr nächster Schritt: STACKIT.
Erzählen Sie uns von Ihrer Umgebung. Wir zeigen Ihnen, was StackToIT dafür liefert: Zielarchitektur, Terraform-Artefakte und einen strukturierten Migrationsplan.