---
title: "Spring Boot mit Terraform und Ansible rehosten"
description: "Ausführbare Rehost-Automatisierung für ein Spring-Boot-JAR auf einer STACKIT VM mit lokalem PostgreSQL, geprobtem Cutover, Rollback-Nachweisen, Observability und Server Backup."
sidebar:
  badge:
    text: "STACKIT"
    variant: success
scfAsset:
  managed: false
  category: "runbook"
  external: false
  tags: ["design-and-mobilize", "design", "runnable-example", "rehost", "automation", "terraform", "ansible", "spring-boot"]
  maintainers:
    - user: "lukas.weberruss"
      role: true
      website: true
source_url: "https://framework.stackit.cloud/de/migration/assetcontainer/stackit/rehost-automation-spring-boot-terraform-ansible/"
source_file: "docs/de/migration/assetcontainer/stackit/rehost-automation-spring-boot-terraform-ansible.mdx"
---

## Referenzimplementierung

Das Migration Framework definiert Strategie, Design, Landing Zone, Migration und Betriebsprinzipien
für Rehost-Workloads. Dieses Asset wendet diese Prinzipien auf eine konkrete, ausführbare Spring-Boot-
und PostgreSQL-Implementierung auf STACKIT an.

Das gepflegte Repository ist die Source of Truth für Terraform, Ansible, Applikationsartefakte,
Migrationsskripte, Validierung und Laufzeitkonfiguration. Dieses Asset beschreibt die Nutzung der
Implementierung, ohne ihren vollständigen Quellcode zu duplizieren.

<LinkCard
  title="STACKIT CMF Rehost Spring Boot Repository"
  description="Öffnen Sie die ausführbare Terraform- und Ansible-Referenzimplementierung für den Rehost-Pfad von Spring Boot und PostgreSQL."
  href="https://github.com/stackitcloud/stackit-cmf-Rehost-springboot"
/>

## Migrationskontext und Umfang

Dieses Beispiel bildet einen Application-Rehost-Pfad für einen Spring-Boot-Workload ab, konkret das
Spring-Music-Beispiel. Der Fokus liegt auf der Verlagerung der Laufzeit nach STACKIT:

- **Infrastruktur-Rehost**: Terraform stellt eine STACKIT VM, Boot Volume, Netzwerk, Public IP,
  Security Group, SSH-Key, Observability-Ressourcen und optional einen Server-Backup-Zeitplan bereit.
- **Application-Rehost**: Ansible installiert Java, deployt das Spring-Boot-JAR und verwaltet es mit
  `systemd`, ohne das Laufzeitmodell der Anwendung zu ändern.
- **Stateful Rehost**: Ansible installiert selbstverwaltetes PostgreSQL auf derselben VM. Der
  Datenbank-Layer wird in diesem Pfad nicht auf einen Managed Service umgestellt.
- **Kontrollierte Migration**: Das Repository enthält getrennte Workflows für Probe, Cutover,
  Validierung und Rollback mit maschinenlesbaren Nachweisen.

Die validierte Baseline enthält bewusst keinen Application Load Balancer, DNS-Switch, mehrere VMs,
Kubernetes, Cloud Foundry oder PostgreSQL Flex. Ergänzen Sie diese nur als separat entworfene und
getestete Erweiterungen; sie sind nicht impliziter Bestandteil dieses Rehost-Beispiels.

## Inhalt des Repositories

- **Provisioning**: Terraform-Ressourcen für Netzwerk, Security, eine VM, Boot Volume, SSH-Key und Public IP.
- **Configuration Bridge**: Terraform stößt Ansible nach dem Infrastruktur-Provisioning an.
- **Application Deployment**: Ansible deployt ein konkretes Spring-Boot-Artefakt und konfiguriert einen `systemd`-Service.
- **VM-lokaler Datenbankpfad**: PostgreSQL-Installation, Bootstrap von Application Role und Datenbank
  sowie Dump-basierter Restore mit Ownership- und Datenintegritätsprüfungen.
- **Operations-Baseline**: STACKIT Observability erfasst Node-Exporter-Metriken; Terraform kann ein
  tägliches Server Backup für das Boot Volume der VM aktivieren.
- **Migrationskontrollen**: Erzeugung des Quelldumps, unabhängige Restore-Validierung, Probe, Cutover,
  Rollback-Prüfung, Rollback-Ausführung und Nachweiserfassung.
- **Bereitstellbares Sample-Artefakt**: Das Repository enthält ein ausführbares JAR, das die
  Standardkonfiguration verwendet.

## Einheitliche Automatisierungs-Flags

Nutzen Sie dieses gemeinsame Flag-Modell in den Terraform-Variablen, um das Verhalten über CMF-Beispiele
hinweg konsistent zu halten:

- **`setup_project`**: Projektkontext erstellen oder verwenden.
- **`setup_observability`**: Observability-Ressourcen aktivieren oder deaktivieren.
- **`setup_database`**: Optionales VM-lokales PostgreSQL aktivieren oder deaktivieren.
- **`setup_workload`**: Workload-Installation auf der VM aktivieren oder deaktivieren.
- **`setup_loadgen`**: Optionale synthetische Lastgenerierung aktivieren oder deaktivieren.
- **`setup_dns`**: Wird vom gemeinsamen Wrapper akzeptiert, ist in dieser Baseline aber nicht unterstützt.

Im aktuellen Rehost-Repository werden diese auf bestehende Schalter wie `create_project`,
`enable_observability`, `enable_local_postgresql` und die Flags zur Lastgenerierung abgebildet.

## Validierte Zielarchitektur

Das folgende Diagramm zeigt das implementierte und getestete Ziel, nicht eine zukünftige
High-Availability-Variante.

```d2
direction: right

Operator: "Freigegebene Operator-Quelle" {
  icon: ../../../../../../../public/stackit-icons/networking/ip.svg
}

TargetProject: "STACKIT Projekt" {
  VM: "Ubuntu VM" {
    icon: ../../../../../../../public/stackit-icons/computing/virtual-machine.svg
    link: https://docs.stackit.cloud/products/compute-engine/server/
    App: "Spring Boot JAR + systemd"
    PostgreSQL: "Selbstverwaltetes PostgreSQL"
  }
  Obs: "Observability" {
    icon: ../../../../../../../public/stackit-icons/logging-monitoring/observability.svg
    link: https://docs.stackit.cloud/products/logging-and-monitoring/observability/
  }
  Backup: "Backup Archive" {
    icon: ../../../../../../../public/stackit-icons/computing/archive.svg
    link: https://docs.stackit.cloud/products/compute-engine/server-backup-management/
  }
}

Operator -> TargetProject.VM.App: "eingeschränktes HTTP/SSH"
TargetProject.VM.App -> TargetProject.VM.PostgreSQL: "lokales SQL"
TargetProject.Obs -> TargetProject.VM: "eingeschränkter Metrics Scrape"
TargetProject.VM -> TargetProject.Backup: "Boot-Volume-Backup"
```

## Arbeitsumgebung für den Walkthrough vorbereiten

Verwenden Sie ein isoliertes Linux-Labor mit Git, Terraform, Ansible, ShellCheck, SSH/SCP, curl, jq
und PostgreSQL-Server-/Client-Werkzeugen einschließlich `pg_config`. Die Sample-Dump-Skripte nutzen
`runuser` und den lokalen OS-Account `postgres` und benötigen Root-Rechte in diesem Labor.
Bei aktiviertem Server Backup braucht der Cutover zusätzlich eine authentifizierte STACKIT CLI.
Verwenden Sie für vorhandene gespeicherte Pläne die Terraform-Version, die sie erzeugt hat;
Plandateien sind versionsgebunden.

Beginnen Sie in einem übergeordneten Verzeichnis ohne bereits vorhandenen gleichnamigen Checkout.
Dieser Stand enthält die Migrationsworkflows und die deklarative Observability-Verwaltung. Seine JAR
ist gegenüber dem in der Replatform-Referenz fixierten Artefakt unverändert:

```bash
umask 077 &&
  git clone https://github.com/stackitcloud/stackit-cmf-Rehost-springboot.git &&
  git -C stackit-cmf-Rehost-springboot checkout --detach b9225eb35c64b9ef4761c208fadb9a2356431793 &&
  test -f stackit-cmf-Rehost-springboot/scripts/run_cutover.sh &&
  cd stackit-cmf-Rehost-springboot &&
  printf '%s\n' "Workspace ready. Continue from this Rehost checkout." || {
    printf '%s\n' "Preparation failed. Resolve the error before continuing." >&2
    false
  }
```

Führen Sie die folgenden Schritte erst nach erfolgreicher Vorbereitung aus diesem Checkout aus.
Bewahren Sie vorhandene Checkouts, State und Nachweise, statt sie zu ersetzen. Halten Sie Credentials,
Pläne, State, Dumps, Inventory und Nachweise privat und außerhalb der Versionsverwaltung;
aktivieren Sie kein Shell-Tracing.

## Zielparameter konfigurieren

Erstellen Sie die private Variablendatei nur, wenn sie noch nicht existiert:

```bash
umask 077
test -e env.tfvars || cp env.tfvars.example env.tfvars
chmod 600 env.tfvars
```

Bearbeiten Sie die Datei vor dem Plan. Konfigurieren Sie das freigegebene bestehende Projekt oder den
Scope für die Projekterstellung, Service-Account-Key-Pfad, SSH-Schlüsselpaar, verfügbares Image,
Availability Zone, VM-Flavor und Storage. Beschränken Sie SSH- und Applikations-Ingress auf die
Quell-CIDRs, die am Zielpfad tatsächlich ankommen. Verifizieren Sie den SSH-Host-Key über einen
vertrauenswürdigen Kanal, bevor Migrationsskripte die strikte Host-Prüfung verwenden.
Setzen Sie für diese Skripte `SSH_KEY` und `SSH_USER`, falls sie von `~/.ssh/id_rsa` und `ubuntu`
abweichen; halten Sie sie konsistent zu `private_ssh_key_path` und `ssh_user` in Terraform.

Aktivieren Sie VM-lokales PostgreSQL, Observability und Server Backup für diesen Walkthrough.
Lassen Sie für das erste Runtime-Deployment `postgresql_restore_after_copy = false` und den
Quelldump-Pfad leer: Provisioning darf die Quelle nicht vor Probe und Cutover-Freigabe importieren.
Übergeben Sie das Datenbankpasswort über den freigegebenen Secret-Mechanismus als
`TF_VAR_postgresql_app_password` und bewahren Sie es für spätere Pläne sicher auf;
schreiben Sie es nicht in Variablendatei, Shell-History oder Dokumentation.

Bestätigen Sie Berechtigungen, Quota, Kostenfreigabe und das private Terraform-Backend vor der
Initialisierung. Dieser Ablauf setzt einen vorbereiteten Ausführungshost voraus und ist keine
vollständige Installationsanleitung für das Labor.

## Nachweise an der Quelle vorbereiten

Erstellen Sie einen Quelldump im Custom Format und erfassen Sie SHA-256-Prüfsumme, erwartete
Datensatzanzahl und einen Workload-spezifischen deterministischen Fingerprint. Das Repository enthält
ein reproduzierbares Beispiel mit acht Datensätzen:

```bash
./scripts/create_source_dump.sh
./scripts/validate_source_dump.sh
```

Das Validierungsskript stellt den Dump in einem separaten lokalen PostgreSQL-Cluster wieder her,
bevor er in eine Migrationsprobe eingehen darf. Die Skripte erzeugen das mitgelieferte Sample in
temporären lokalen Clustern; sie exportieren weder eine laufende Anwendung noch die STACKIT VM.
Verwenden Sie ein frisches Artefaktverzeichnis und überschreiben Sie keinen bereits freigegebenen
Migrationsdump. Exportieren Sie eine reale Quelle unter dem vereinbarten Write Freeze und erfassen
Sie gleichwertige Nachweise für Prüfsumme, Anzahl und Fingerprint.

## Ziel bereitstellen

Konfigurieren Sie ein bestehendes STACKIT Projekt oder die Projekterstellung, beschränken Sie SSH-
und Applikations-Ingress auf freigegebene Quell-CIDRs und übergeben Sie das Datenbankpasswort über
`TF_VAR_postgresql_app_password` statt über eine Variablendatei. Prüfen Sie vor dem Apply einen
gespeicherten Plan.

```bash
terraform init &&
  ./scripts/check.sh &&
  terraform plan -input=false -var-file=env.tfvars -out=tfplan
```

Stoppen Sie bei Fehlern in Initialisierung, Checks oder Plan. Prüfen Sie Ressourcenänderungen,
Zielprojekt, Ingress, Kosten und den deaktivierten initialen Restore, bevor Sie den gespeicherten
Plan ausdrücklich anwenden:

```bash
terraform apply tfplan
```

Terraform führt nach dem Provisioning Ansible aus. Ein erfolgreicher Apply belegt den Abschluss
dieser Orchestrierung, nicht die Abnahme migrierter Daten. Prüfen Sie die Laufzeit vor der Probe:

```bash
./scripts/validate_deployment.sh
```

## Migration proben

Führen Sie die Probe gegen eine temporäre Datenbank auf der Ziel-VM aus:

```bash
./scripts/run_migration_rehearsal.sh
```

Die Probe prüft die Quelldaten, stellt den Dump wieder her, vergleicht Datensatzanzahl und Fingerprint
und entfernt die temporäre Datenbank, ohne die produktive `springmusic`-Datenbank zu verändern.

## Cutover ausführen

Hinterlegen Sie die erwarteten Quelldaten in `env.tfvars`:

```hcl
enable_local_postgresql                  = true
postgresql_source_dump_local_path        = "artifacts/source-postgresql.dump"
postgresql_restore_after_copy            = true
postgresql_expected_album_count          = 8
postgresql_expected_album_fingerprint    = "<source-fingerprint>"
```

Führen Sie anschließend das explizite Freigabe-Gate aus:

```bash
./scripts/run_cutover.sh --confirm
```

Das Skript verlangt ein vollständig verfügbares Server Backup, das höchstens 24 Stunden alt ist. Es
erzeugt einen gespeicherten Terraform-Plan, der ausschließlich die Ansible-Orchestrierungsressource
ersetzt, weist andere Infrastrukturänderungen zurück, führt den Restore aus, validiert Daten und
Laufzeitverhalten und verlangt abschließend einen Terraform-No-op-Plan. Wiederholungen mit demselben
Quelldump-Hash bewahren den ursprünglichen Datenbank-Rollback-Punkt.

## Validieren und zurückrollen

Die Validierung prüft Datensatzanzahl und Fingerprint der Quelle, Tabellen-Ownership, einen
transaktional zurückgerollten Schreibvorgang als Application Role, Erreichbarkeit der Anwendung,
Services und den geschützten Rollback-Dump.

```bash
./scripts/validate_migration.sh
./scripts/validate_deployment.sh
./scripts/verify_rollback.sh
```

Wenn innerhalb des Rollback-Fensters ein freigegebener Rollback-Trigger eintritt, bewahren Sie die
aktuelle Zieldatenbank und stellen den ursprünglichen Dump von vor dem Cutover wieder her:

```bash
./scripts/rollback_postgresql.sh --confirm
```

## Grenze zwischen Backup und Recovery

Mit `enable_server_backup = true` aktiviert Terraform STACKIT Server Backup und einen täglichen
Zeitplan für das Boot Volume der VM. Die Standardaufbewahrung beträgt 14 Tage. Der Cutover verlangt
ein vollständig verfügbares Backup, das höchstens 24 Stunden alt ist. Erstellung und Status des
Backups wurden am realen Ziel validiert; ein In-place-Restore mit Server Backup bleibt eine
disruptive Disaster-Recovery-Operation und muss in einer separaten Recovery-Umgebung geprobt werden.

Server Backup ergänzt den PostgreSQL-Dump von vor dem Restore. Es ersetzt weder die
Datenbank-Konsistenzprüfungen noch das Application-Rollback-Verfahren.

## Nutzung

Folgen Sie Arbeitsumgebung, privater Zielkonfiguration, Quellnachweisen und geprüftem Provisioning
in dieser Reihenfolge. Proben Sie vor dem freigegebenen Cutover und bewahren Sie anschließend die
Abnahmenachweise auf. Die Repository-Skripte rufen ausdrücklich `terraform` auf; ein Ausführungshost
mit ausschließlich OpenTofu benötigt eine separat geprüfte Anpassung, nicht nur ersetzte Befehle
auf dieser Seite.

## Monitoring und Dashboard

Die Implementierung stellt STACKIT Observability bereit und erfasst den Node Exporter. Der Grafana-Provider
verwaltet das enthaltene Dashboard im Ordner `SCF Rehost` mit der vorhandenen `Thanos`-Datenquelle.
Er wartet auf die Bereitschaft der Instanz, statt die Dashboard-Erstellung stillschweigend zu überspringen.

Prüfen Sie über `grafana_dashboard_url` aktuelle VM-, Spring-Boot- und PostgreSQL-Metriken und verlangen
Sie anschließend einen No-op-Plan. Sieben Panels bilden die aktive Basis ab; das Panel für synthetische
Anfragen erscheint nur bei aktiviertem lokalem Lastgenerator. Diese Anfragen bilden nicht den gesamten
Application-Traffic ab. Die Deployment-Validierung prüft außerdem Exporter-Metriken und Service Health
nach dem Apply und nach dem Datenbank-Restore.

Die initialen Grafana-Admin-Zugangsdaten bleiben eine temporäre Authentifizierungsabhängigkeit. Schützen
Sie State und gespeicherte Pläne. Benachrichtigungsempfänger, Zuständigkeit für Alarm-Routing,
Application-Logs und Distributed Tracing benötigen vor Produktionseinsatz eine separate Konfiguration
und Abnahme.

## Ausrichtung an der Application Landing Zone

Dieses Beispiel kann in zwei zulässigen Setup-Modi eingesetzt werden.

- **Mit bestehender Application Landing Zone**: Verwenden Sie den bereits definierten Projektkontext
  und Service Account Ihrer Landing-Zone-Implementierung. Nutzen Sie die bekannte Projekt-ID als
  Deployment-Ziel, zum Beispiel mit `create_project = false` und `project_id = "..."`, sowie die für
  diesen Landing-Zone-Scope konfigurierte Service-Account-JSON.
- **Eigenständig ohne bestehendes Landing-Zone-Projekt**: Lassen Sie das Beispiel ein dediziertes
  Projekt erstellen. Setzen Sie `create_project = true` und geben Sie über `parent_container_id` einen
  bestehenden Folder oder Container an, in dem der Service Account ausreichende Berechtigungen hat.

Hinweise zum Landing-Zone-Design finden Sie unter [Application Landing Zone](/de/migration/design-and-mobilize/landing-zones/application-landing-zone/).

## Minimales Konfigurationsbeispiel

Nutzen Sie dieses Beispiel als Ausgangspunkt in `env.tfvars`.

```hcl
create_project              = true
target_project_name         = "cmf-rehost-springboot"
target_project_owner_email  = "owner@example.com"
parent_container_id         = "cmf-xxxxxxxx"
service_account_key_path    = "~/.ssh/cmf-sa.json"
public_ssh_key_path         = "~/.ssh/id_rsa.pub"
private_ssh_key_path        = "~/.ssh/id_rsa"
availability_zone           = "eu01-1"
machine_type                = "g2i.2"
ssh_allowed_cidr            = "203.0.113.10/32"
app_allowed_cidr            = "203.0.113.10/32"
enable_local_postgresql     = true
enable_observability       = true
enable_server_backup       = true
```

## Verhalten des Deployment-Artefakts

- **Standard-Artefaktpfad**: `ansible/files/springboot-app.jar`
- **Standardvariable**: `jar_local_path` verweist auf dieselbe Datei.
- **Alternatives Artefakt**: Ersetzen Sie die Datei oder überschreiben Sie `jar_local_path`.

Wenn sich das Artefakt ändert, erkennt Terraform die geänderte Prüfsumme und führt den
Ansible-Deployment-Schritt erneut aus.

## Nachweise und Abnahme

Jede Probe, jeder Cutover und jedes Rollback schreibt eine `evidence.env`-Datei unter
`artifacts/evidence/<timestamp>-<mode>/`. Akzeptieren Sie einen Cutover nur, wenn der Nachweis die
erwartete Prüfsumme, Datensatzanzahl, den Fingerprint, die Ziel-VM, eine erfolgreiche
Laufzeitvalidierung und den abschließenden Terraform-No-op dokumentiert.

```bash
./scripts/validate_migration.sh
./scripts/validate_deployment.sh
terraform plan -var-file=env.tfvars -detailed-exitcode
```

Verwenden Sie denselben freigegebenen Quellpfad, Restore-Schalter, Erwartungswert und Fingerprint
wie beim abgeschlossenen Cutover. Exit-Code `0` bedeutet keine Änderungen, `2` vorgeschlagene
Änderungen und `1` einen Fehler. Ein Plan allein belegt keinen Apply. Der Cutover-Workflow setzt
`status=passed` und `terraform_noop=true` erst nach Anwendung seines gespeicherten Plans und
erfolgreicher Daten- und Laufzeitvalidierung.

## Entscheidungs- und Freigabepunkte der Migration

- **Vorbereiten**: Zieldesign, Zugangswege, Quellnachweise und Recovery-Verantwortung freigeben.
- **Bereitstellen**: Infrastrukturplan prüfen und anwenden, danach die VM-Laufzeit unabhängig verifizieren.
- **Proben**: In einer isolierten Datenbank wiederherstellen und Integrität prüfen, ohne die Anwendungsdatenbank zu verändern.
- **Umschalten**: Schreibzugriffe an der Quelle einfrieren, finalen Dump freigeben und ausschließlich die vorgesehene Orchestrierungsänderung zulassen.
- **Abnehmen oder wiederherstellen**: Daten-, Laufzeit- und No-op-Nachweise verlangen; bei fehlgeschlagener Abnahme das vereinbarte Rollback vor der Deadline auslösen.
- **Übergeben**: Monitoring, Backup-Ownership, Nachweise und Entscheidungen zur Quellenaufbewahrung vor Optimize übergeben.

## Als Replatform-Basis weiterverwenden

Die Replatform-Referenz verwendet das fixierte Spring-Music-JAR und den Sample-Datengenerator dieses
Repositories weiter. Ihr Sample-Walkthrough benötigt deshalb diesen Checkout und validierte
Dump-Artefakte, aber keine neu bereitgestellte Rehost-VM. Erstellen Sie keine zusätzliche VM allein
zur Erzeugung des lokalen Samples.

Für eine tatsächliche Migration von der Rehost-VM zu SKE und PostgreSQL Flex müssen Sie den aktuellen
VM-Zustand prüfen, Schreibzugriffe der Anwendung einfrieren, die reale PostgreSQL-Datenbank exportieren
und diesen Export qualifizieren. Ein historisch erfolgreicher Rehost-Apply belegt weder aktuelle
Erreichbarkeit noch die Gleichwertigkeit des lokalen Samples mit den VM-Daten. Quellexport, Abnahme
und Source Failback benötigen ein eigenes freigegebenes Verfahren.

## Hinweise

- Stimmen Sie Betriebsverfahren mit Runbook und Migration Governance ab.
- Passen Sie für den Produktionseinsatz Sicherheitskontrollen, Sizing, Image-Auswahl und
  Lifecycle-Automatisierung an.
