AZURE → STACKIT · FALLSTUDIE

Azure Web-App, Datenbank und Key Vault auf STACKIT

Eine Umgebung aus 15 Azure-Ressourcen: eine Node.js-Web-App auf App Service, ein privater PostgreSQL-Server, ein Key Vault, ein Storage Account für Uploads und ein Netzwerk mit Security Group. StackToIT hat sie am 4. November 2026 bewertet und 7 von 8 Einheiten entworfen. Diese Fallstudie zeigt die Zahlen, die wichtigen Auszüge und die Entscheidungen, die bei Ihren Architekten liegen.

Der Lauf in Zahlen

Eine kleine, für diese Seite geschriebene Umgebung, offline bewertet. Die Zahlen stammen aus der Konsolenzusammenfassung, aus assessment.json und aus dem Ausführungspaket des Laufs.

KennzahlWertBedeutung
Quellressourcen und Einheiten15 Ressourcen, 8 EinheitenDie Subnetz-Zuordnung der Security Group, die Datenbank, das Secret und der Blob-Container gehen in der Einheit auf, zu der sie gehören; jedes Subnetz ist eine eigene Einheit. Ressourcengruppe, Rollenzuweisung und App-Service-Plan werden als unterstützende Einstellungen geprüft.
Klassen5 RECONFIGURE, 3 REPLATFORMKein REDESIGN und kein MANUAL_REVIEW in dieser Umgebung. Der Aufwand liegt in Einstellungen, nicht in Dienstklassen.
Entworfen7 Einheiten entworfen, 1 braucht keine RessourceDas virtuelle Netzwerk braucht keine Ressource, weil seine Subnetze zu STACKIT-Netzwerken werden.
OpenTofu-Schritte8 RessourcenblöckeZwei Netzwerke, eine Security Group mit einer Regel, eine PostgreSQL-Flex-Instanz, ein Bucket, eine Secrets-Manager-Instanz und eine Cloud-Foundry-Organisation.
Manuelle Schritte30 Schritte in 18 ArbeitspaketenJeder hat eine verantwortliche Rolle und ein Abschlusskriterium.
Offene kritische Einstellungen33 Einstellungen von 8 QuellressourcenEinstellungen, die der Entwurf nicht übernimmt, Eigenschaft für Eigenschaft aufgeführt.
Abgelehnt2 SchritteDas Ziel hat kein Gegenstück: Löschschutz des Key Vault und die Regelpriorität der Security Group.
Zu treffende Entscheidungen7, davon hält eine Schritte zurückDie IPv4-Standard-Egress-Regel der neuen Security Group.

Das Migrationspaket ist teilweise ausführbar und nicht freigegeben: Der Lauf selbst sagt, dass kein OpenTofu-Schritt wie geschrieben laufen kann, weil Werte wie project_id und die Zugriffsliste der Datenbank noch fehlen.

Die Datenbank: Aus dem privaten Server wird eine Zugriffsliste

Links der PostgreSQL Flexible Server der Eingabe, privat über ein delegiertes Subnetz. Rechts der Instanzblock, den die Engine geschrieben hat. Die Prüfkommentare über dem Block sind hier ausgelassen.

Beispieleingabemain.tf
resource "azurerm_postgresql_flexible_server" "shop" {
  name                          = "psql-shop-gwc"
  resource_group_name           = azurerm_resource_group.shop.name
  location                      = azurerm_resource_group.shop.location
  version                       = "16"
  sku_name                      = "GP_Standard_D4s_v3"
  storage_mb                    = 131072
  backup_retention_days         = 14
  administrator_login           = "shopadmin"
  administrator_password        = var.db_admin_password
  delegated_subnet_id           = azurerm_subnet.data.id
  public_network_access_enabled = false
  zone                          = "1"
}
STACKIT-Terraform von StackToITterraform/data.tf
resource "stackit_postgresflex_instance" "shop" {
  project_id = var.project_id
  name       = "psql-shop-gwc"
  version    = "16"
  flavor_id  = "4.32"
  storage = {
    class = var.postgresflex_storage_class
    size  = 128
  }
  backup_schedule = "0 2 * * *"
  network = {
    acl = var.shop_allowed_cidrs
  }
  retention_days = 32
}
  • Flavor aus der Quellgröße

    Die Quell-SKU hat 4 vCPU und 16 GiB. Der Entwurf nimmt das Flavor 4.32, das kleinste Single-Node-PostgreSQL-Flex-Flavor in eu01, das sie abdeckt, mit 4 vCPU und 32 GiB. Bemessen Sie es anhand gemessener Last neu, wenn der Arbeitsspeicher für die Kosten ins Gewicht fällt.

  • Backups

    Die Quelle bewahrt Backups 14 Tage auf. Der Entwurf setzt retention_days auf 32, was der Lauf als TRANSFORMED festhält, und ein tägliches Backup um 02:00 Uhr als zu bestätigenden Standard.

  • Privat wird zur Zugriffsliste

    Das delegierte Subnetz, der Schalter für öffentlichen Zugriff, die Zone und der Administrator-Login werden nicht übernommen. Clients erreichen die Instanz über ihre ACL, aufgeführt in der Variable shop_allowed_cidrs, die keinen Standardwert hat. Die Netzwerkexposition ist ein REVIEW-Punkt: Legen Sie den Endpunkt-Scope vor dem Apply fest.

Der Tresor: Secrets ziehen um, das Zugriffsmodell ändert sich

Links der Key Vault mit seinem Secret. Rechts die Secrets-Manager-Instanz, die die Engine geschrieben hat. Das Secret selbst steht nicht im Entwurf.

Beispieleingabemain.tf
resource "azurerm_key_vault" "shop" {
  name                       = "kv-shop-gwc"
  location                   = azurerm_resource_group.shop.location
  resource_group_name        = azurerm_resource_group.shop.name
  tenant_id                  = var.tenant_id
  sku_name                   = "standard"
  rbac_authorization_enabled = true
  purge_protection_enabled   = true
  soft_delete_retention_days = 30
}

resource "azurerm_key_vault_secret" "db_password" {
  name         = "db-password"
  value        = var.db_admin_password
  key_vault_id = azurerm_key_vault.shop.id
}
STACKIT-Terraform von StackToITterraform/security.tf
resource "stackit_secretsmanager_instance" "migrated_secrets" {
  project_id = var.project_id
  name       = "migrated-secrets"
}
  • Eine Instanz hält alle Secrets

    Sie legen jedes Secret als Schlüssel in der Instanz neu an. Name, Tenant, SKU, Zugriffsrichtlinien, Netzwerkregeln und Aufbewahrung des Tresors werden nicht erzeugt.

  • Jeder Verbraucher bekommt neue Zugangsdaten

    Key Vault vergibt Zugriff an Microsoft-Entra-Prinzipale über Zugriffsrichtlinien oder Azure RBAC. Bei STACKIT geht der Zugriff an Secrets-Manager-Benutzer oder Service Accounts; die Web-App braucht daher neue Zugangsdaten und eine Codeänderung.

  • Löschschutz wird abgelehnt

    Der Tresor hat Purge Protection und 30 Tage Soft Delete. Der Lauf zitiert die STACKIT-Aussage, dass einzelne Secrets nicht wiederhergestellt werden können, und hält die Einstellung als abgelehnt fest. Planen Sie eigenen Schutz, etwa versionierte Secrets und eine Sicherungsroutine.

Die Netzwerkregel: nur Allow-Regeln und offener Egress

Links die Security Group des Datensubnetzes mit einer Regel. Rechts Gruppe und Regel, die die Engine geschrieben hat. Die Kommentare in der Datei führen auf, was Azure stillschweigend ergänzt hatte.

Beispieleingabemain.tf
resource "azurerm_network_security_group" "data" {
  name                = "nsg-data"
  location            = azurerm_resource_group.shop.location
  resource_group_name = azurerm_resource_group.shop.name

  security_rule {
    name                       = "allow-postgres-from-app"
    priority                   = 100
    direction                  = "Inbound"
    access                     = "Allow"
    protocol                   = "Tcp"
    source_port_range          = "*"
    destination_port_range     = "5432"
    source_address_prefix      = "10.40.1.0/24"
    destination_address_prefix = "*"
  }
}
STACKIT-Terraform von StackToITterraform/security.tf
resource "stackit_security_group" "data" {
  project_id = var.project_id
  name       = "nsg-data"
}

resource "stackit_security_group_rule" "data_allow_postgres_from_app" {
  project_id        = var.project_id
  security_group_id = stackit_security_group.data.security_group_id
  direction         = "ingress"
  ether_type        = "IPv4"
  ip_range          = "10.40.1.0/24"
  port_range = {
    max = 5432
    min = 5432
  }
  protocol = {
    name = "tcp"
  }
}
  • Prioritäten entfallen

    STACKIT-Security-Groups erlauben nur, und die Regeln werden gemeinsam ausgewertet. Die Priorität der Quellregel wird nicht übernommen; der Lauf lehnt sie ab. Keine Deny-Regel der gescannten Umgebung hatte Vorrang vor dieser Allow-Regel; eine Regel außerhalb des Scans könnte ihn aber gehabt haben.

  • Azure-Standardregeln werden zu eigener Arbeit

    Azure ergänzt Standardregeln für Verkehr im virtuellen Netzwerk, vom Load Balancer und ins Internet. Laut Lauf kennt eine neue STACKIT-Gruppe keine dieser Standardregeln; jede, die Sie weiter brauchen, schreiben Sie also selbst als Regel.

  • Egress ist weiter als in der Quelle

    STACKIT legt für jede neue Gruppe eine Allow-all-IPv4-Egress-Regel an, die der Entwurf nicht verwaltet. Der Security Architect entscheidet, ob sie nach dem Apply gelöscht wird. Das ist die eine Entscheidung, die Schritte des Plans zurückhält.

Die Web-App: eine Cloud-Foundry-Organisation

Links die Linux-Web-App mit systemseitig zugewiesener Identität, Key-Vault-Referenz und VNet-Integration. Rechts der Organisationsblock. Die App selbst wird mit cf push ausgerollt.

Beispieleingabemain.tf
resource "azurerm_linux_web_app" "shop" {
  name                      = "app-shop-gwc"
  resource_group_name       = azurerm_resource_group.shop.name
  location                  = azurerm_resource_group.shop.location
  service_plan_id           = azurerm_service_plan.shop.id
  https_only                = true
  virtual_network_subnet_id = azurerm_subnet.app.id

  identity {
    type = "SystemAssigned"
  }

  site_config {
    always_on = true

    application_stack {
      node_version = "20-lts"
    }
  }

  app_settings = {
    "DB_HOST"     = azurerm_postgresql_flexible_server.shop.fqdn
    "DB_NAME"     = "shop"
    "DB_PASSWORD" = "@Microsoft.KeyVault(SecretUri=https://kv-shop-gwc.vault.azure.net/secrets/db-password/)"
  }
}
STACKIT-Terraform von StackToITterraform/apps.tf
resource "stackit_scf_organization" "migrated_apps" {
  project_id = var.project_id
  name       = "migrated-apps"
}
  • Aus Einstellungen werden Manifest und Bindings

    App-Einstellungen, Nur-HTTPS, Runtime-Version und Plan werden nicht erzeugt. Sie wandern in das Cloud-Foundry-Manifest und die Service Bindings, die Sie schreiben.

  • Identität ist eine Entscheidung

    Die Managed Identity, mit der die App den Tresor las, wird zu expliziten Zugangsdaten. Der Lauf fragt den Identity Architect, wie die App ihre Identität bekommt; der Entwurf hängt keinen Service Account an.

  • Die Datenbank erreichen

    Die VNet-Integration erreichte die private Datenbank. Auf STACKIT erreicht die App die PostgreSQL-Instanz über deren ACL oder, wo freigeschaltet, über eine Network Area; Sie entscheiden, welcher Weg es wird.

So wird die Umgebung zugeordnet

Azure-RessourceSTACKIT-ZielMigrationsklasse
Key Vault mit SecretSecrets-Manager-Instanz (Schlüssel gehen zu STACKIT KMS)Rekonfigurieren
Storage Account mit ContainerObject-Storage-BucketReplatforming
Virtuelles NetzwerkKeine Ressource; Network Area, wenn Netzwerke sich erreichen müssenRekonfigurieren
Zwei SubnetzeZwei STACKIT-Netzwerke mit denselben IPv4-PräfixenRekonfigurieren
Network Security GroupSecurity Group und eine RegelRekonfigurieren
PostgreSQL Flexible Server mit DatenbankPostgreSQL-Flex-InstanzReplatforming
Linux-Web-AppCloud-Foundry-OrganisationReplatforming

Klassen so, wie der Lauf sie entschieden hat. Der Lauf legt Key Vault, Storage und virtuelles Netzwerk in Welle 1, die Subnetze in Welle 2, Security Group und Datenbank in Welle 3 und die Web-App in Welle 4.

Was eine fehlende Variable bewirkt

Der erste Lauf ließ terraform.tfvars weg; var.tenant_id des Key Vault hatte daher keinen Wert. Der zweite Lauf lieferte ihn. Beide Konsolenzusammenfassungen sind aus den Läufen kopiert.

Erster Lauf, ohne tfvarsconsole
Source        15 resources · 8 units · visibility: Required input missing
Migration     6 drafted · 1 need no resource · 1 has no draft because an input the source needs is not in the package (of 8 units: 7 the draft considered, 1 has no draft)
Attention     1 variable without a value (var.tenant_id) · 7 decisions to make (1 of the 7 holds plan steps) · 8 units to review · 8 open requests (3 block the draft, marked in inputs-template.yaml)
Zweiter Lauf, tenant_id geliefertconsole
Source        15 resources · 8 units · visibility: Variable unresolved
Migration     7 drafted · 1 need no resource (of 8 units the draft considered)
Attention     7 decisions to make (1 of the 7 holds plan steps) · 8 units to review · 7 open requests (2 block the draft, marked in inputs-template.yaml)
  • Der Lauf nennt, was er braucht

    Ohne den Wert hatte der Key Vault keinen Entwurf, und die Zusammenfassung meldete, dass eine Eingabe, die die Quelle braucht, nicht im Paket war. Mit ihm wurden 7 Einheiten entworfen.

  • Eine Variable bleibt bewusst offen

    Auch der zweite Lauf meldet „Variable unresolved“. Sein Architekturbericht nennt die Variable: db_admin_password, sensibel und ohne Standardwert; die terraform.tfvars der Demo liefert nur tenant_id. Einen Entwurf blockiert sie hier nicht; übergeben Sie sie mit --var-file, wenn die Einheiten, die sie lesen, vollständig bewertet werden sollen.

  • Variablendateien mitgeben

    Der zweite Lauf las terraform.tfvars ohne weitere Option aus dem Eingabeordner; zusätzliche Dateien übergeben Sie mit --var-file. Geben Sie der Engine dieselben Variablendateien, die Ihre Pipeline nutzt, damit keine Einheit mangels Wert ohne Entwurf bleibt.

Die Entscheidungen Ihrer Architekten

  1. Security Architect: Standard-Egress

    Die Allow-all-IPv4-Egress-Regel der Security Group nach dem Apply löschen oder akzeptieren. Diese Entscheidung hält Schritte des Plans zurück.

  2. Network Architect: Datenbank-Exposition

    Den Endpunkt-Scope wählen und die Client-Präfixe in shop_allowed_cidrs eintragen. Bleibt er ungesetzt, macht die STACKIT-API den Endpunkt öffentlich.

  3. Identity Architect: Identitäten

    Entscheiden, wie sich die Web-App am Secrets Manager anmeldet und wie die Datenbankbenutzer mit stackit_postgresflex_user angelegt werden.

  4. Platform Architect: Daten und Cutover

    Ein Verfahren für den Datenumzug von Datenbank und Bucket wählen. Der Lauf führt beide mit dem Mechanismus UNKNOWN und ohne Größe, Rate oder tolerierte Downtime auf, weil die Quelle sie nicht nennt. Für die Datenbank sind pg_dump mit pg_restore oder logische Replikation die üblichen Wege.

  5. Alle: Verantwortung für die offenen Einstellungen

    Die 33 offenen Einstellungen über die Review-Datei schließen oder akzeptieren, ein Vermerk je verantwortlicher Rolle.

Fragen von Architekten zu dieser Umgebung

Warum entwarf der Lauf zunächst nur 7 von 8 Einheiten?

Der Key Vault nutzte eine Variable, tenant_id, ohne Wert im Paket. Die Einheit hatte dann keinen Entwurf, und die Zusammenfassung nannte die fehlende Eingabe. Mit dem Wert wurde sie entworfen.

Zieht der Entwurf die Secrets um?

Nein. Er legt nur die Secrets-Manager-Instanz an. Sie legen jedes Secret darin neu an und geben der Web-App Zugangsdaten zum Lesen.

Ist die private Datenbank weiterhin privat?

Nicht auf dieselbe Weise. Der Entwurf beschränkt die Instanz mit einer Zugriffsliste; ob der Endpunkt öffentlich ist oder auf eine Network Area beschränkt wird, entscheiden Sie, und zwar vor dem Apply.

Lässt sich der Entwurf so anwenden?

Nein. Der Lauf sagt, dass kein Schritt wie geschrieben laufen kann, weil Werte wie project_id und die erlaubten CIDRs fehlen und Entscheidungen offen sind. Er ist ein Ausgangspunkt für die Prüfung, kein freigegebener Plan.

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.