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.
| Kennzahl | Wert | Bedeutung |
|---|---|---|
| Quellressourcen und Einheiten | 15 Ressourcen, 8 Einheiten | Die 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. |
| Klassen | 5 RECONFIGURE, 3 REPLATFORM | Kein REDESIGN und kein MANUAL_REVIEW in dieser Umgebung. Der Aufwand liegt in Einstellungen, nicht in Dienstklassen. |
| Entworfen | 7 Einheiten entworfen, 1 braucht keine Ressource | Das virtuelle Netzwerk braucht keine Ressource, weil seine Subnetze zu STACKIT-Netzwerken werden. |
| OpenTofu-Schritte | 8 Ressourcenblöcke | Zwei Netzwerke, eine Security Group mit einer Regel, eine PostgreSQL-Flex-Instanz, ein Bucket, eine Secrets-Manager-Instanz und eine Cloud-Foundry-Organisation. |
| Manuelle Schritte | 30 Schritte in 18 Arbeitspaketen | Jeder hat eine verantwortliche Rolle und ein Abschlusskriterium. |
| Offene kritische Einstellungen | 33 Einstellungen von 8 Quellressourcen | Einstellungen, die der Entwurf nicht übernimmt, Eigenschaft für Eigenschaft aufgeführt. |
| Abgelehnt | 2 Schritte | Das Ziel hat kein Gegenstück: Löschschutz des Key Vault und die Regelpriorität der Security Group. |
| Zu treffende Entscheidungen | 7, davon hält eine Schritte zurück | Die 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.
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"
}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.
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
}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.
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 = "*"
}
}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.
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/)"
}
}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-Ressource | STACKIT-Ziel | Migrationsklasse |
|---|---|---|
| Key Vault mit Secret | Secrets-Manager-Instanz (Schlüssel gehen zu STACKIT KMS) | Rekonfigurieren |
| Storage Account mit Container | Object-Storage-Bucket | Replatforming |
| Virtuelles Netzwerk | Keine Ressource; Network Area, wenn Netzwerke sich erreichen müssen | Rekonfigurieren |
| Zwei Subnetze | Zwei STACKIT-Netzwerke mit denselben IPv4-Präfixen | Rekonfigurieren |
| Network Security Group | Security Group und eine Regel | Rekonfigurieren |
| PostgreSQL Flexible Server mit Datenbank | PostgreSQL-Flex-Instanz | Replatforming |
| Linux-Web-App | Cloud-Foundry-Organisation | Replatforming |
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.
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)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
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.
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.
Identity Architect: Identitäten
Entscheiden, wie sich die Web-App am Secrets Manager anmeldet und wie die Datenbankbenutzer mit stackit_postgresflex_user angelegt werden.
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.
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.