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.

Befehlshell
stacktoit assess . ./stacktoit-out --offline --no-validate
Konsolenzusammenfassung (ausgewählte Zeilen)terminal output
Source        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.

Antwortvorlage (Auszug)review/inputs.yaml
  # 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 above
Zweiter Befehlshell
stacktoit assess . ./stacktoit-out2 --offline --no-validate \
  --var-file ./vars.tfvars \
  --inputs ./inputs.yaml
Variablendateivars.tfvars
db_password = "demo-only-not-a-real-secret"
Konsolenzusammenfassung (ausgewählte Zeilen)terminal output
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 requests
  • Quelle 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-RessourceSTACKIT-ZielKlasse
google_compute_networkKeine Ressource: jedes Subnetz wird zu einem Netzwerk im ProjektRekonfigurieren
google_compute_subnetworkstackit_network mit demselben IPv4-PräfixRekonfigurieren
google_compute_firewallstackit_security_group mit einer Regel pro Allow-RegelRekonfigurieren
google_compute_instancestackit_server mit NetzwerkschnittstelleRekonfigurieren
google_sql_database_instance mit Benutzerstackit_postgresflex_instance und stackit_postgresflex_userReplatforming
google_storage_bucketstackit_objectstorage_bucketRekonfigurieren

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.

Beispiel-Eingabemain.tf
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
  }
}
STACKIT: Netzwerkterraform/network.tf
resource "stackit_network" "app" {
  project_id       = var.project_id
  name             = "app"
  ipv4_prefix      = "10.20.0.0/24"
  ipv4_nameservers = var.default_ipv4_nameservers
}
STACKIT: Security Group und Regelterraform/security.tf
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"
  }
}
STACKIT: Serverterraform/compute.tf
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

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.