CloudTrips benötigt eine vollständige wiederholbare Umgebung? Mit Bicep erstellen

Veröffentlicht am:

CloudTrips kann einen Speicher-Workload bereitstellen. Eine nutzbare Anwendungsgrundlage benötigt jedoch zusätzlich einen sicheren Ort für Geheimnisse und ein gemeinsames Monitoringziel. Würden diese Ressourcen manuell erstellt, hätten DEV, TEST und PROD unterschiedliche Namen, Tags, Einstellungen und Bereitstellungsverläufe.

Erstelle die vollständige Grundlage über einen einzigen Bicep-Einstiegspunkt auf Abonnementebene. In diesem Lernpfad bedeutet „vollständige Umgebung“:

  • eine Ressourcengruppe
  • ein Speicherkonto mit umgebungsspezifischen Containern
  • einen Key Vault mit Azure RBAC
  • einen Log-Analytics-Arbeitsbereich
  • eine arbeitsbereichsbasierte Application-Insights-Ressource
  • einheitliche Tags für Besitzer, Kosten, Umgebung und Verwaltung

Anwendungscompute und Netzwerk liegen außerhalb dieses Labs. Sie können später als weitere Module ergänzt werden, ohne die hier aufgebaute Struktur zu ändern.

Dieses Abschluss-Lab baut auf folgenden Trips auf: Bereitstellungsbereiche verwenden und Azure Verified Modules verwenden. Schließe sie zuerst ab, da dieses Lab deren Einstiegspunkt auf Abonnementebene, Parameterdateien, modularen Workload und Storage-Wrapper erweitert. Der Trip zu Deployment Stacks ist ein separates Lebenszyklus-Lab und nicht erforderlich.

Das Key-Vault-Modul hinzufügen

Erstelle cloudtrips-bicep/modules/key-vault.bicep. Der Name ist deterministisch und zugleich global eindeutig, weil er die Umgebung mit einem Hash der Ressourcengruppen-ID kombiniert:

param environment string
param location string
param tags object

var keyVaultName = 'kvct${toLower(environment)}${uniqueString(resourceGroup().id)}'

resource keyVault 'Microsoft.KeyVault/vaults@2026-02-01' = {
  name: keyVaultName
  location: location
  tags: tags
  properties: {
    accessPolicies: []
    enablePurgeProtection: true
    enableRbacAuthorization: true
    enableSoftDelete: true
    enabledForDeployment: false
    enabledForDiskEncryption: false
    enabledForTemplateDeployment: false
    networkAcls: {
      bypass: 'AzureServices'
      defaultAction: 'Allow'
      ipRules: []
      virtualNetworkRules: []
    }
    publicNetworkAccess: 'Enabled'
    sku: {
      family: 'A'
      name: 'standard'
    }
    softDeleteRetentionInDays: 7
    tenantId: tenant().tenantId
  }
}

output keyVaultName string = keyVault.name
output keyVaultId string = keyVault.id
output keyVaultUri string = keyVault.properties.vaultUri

Das Modul erstellt die Vault-Grenze, aber keine Geheimnisse. Geheimniswerte dürfen nicht in das Repository geschrieben werden. enableRbacAuthorization: true bedeutet, dass der Zugriff über Azure-Rollen und nicht über ältere Key-Vault-Zugriffsrichtlinien vergeben wird.

Purge Protection ist aktiviert und kann später nicht mehr deaktiviert werden. Der öffentliche Netzwerkzugriff hält die Lernbereitstellung ohne virtuelles Netzwerk nutzbar. In einem Produktionsdesign kann der Vault zusätzlich hinter einem Private Endpoint liegen.

Das Monitoringmodul hinzufügen

Erstelle cloudtrips-bicep/modules/monitoring.bicep. Es stellt zuerst den Log-Analytics-Arbeitsbereich bereit und verbindet Application Insights damit:

param environment string
param location string
param tags object

var resourceSuffix = uniqueString(resourceGroup().id)
var logAnalyticsWorkspaceName = 'log-ct-${toLower(environment)}-${resourceSuffix}'
var applicationInsightsName = 'appi-ct-${toLower(environment)}-${resourceSuffix}'

resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2025-07-01' = {
  name: logAnalyticsWorkspaceName
  location: location
  tags: tags
  properties: {
    features: {
      disableLocalAuth: false
      enableLogAccessUsingOnlyResourcePermissions: true
    }
    publicNetworkAccessForIngestion: 'Enabled'
    publicNetworkAccessForQuery: 'Enabled'
    retentionInDays: 30
    sku: {
      name: 'PerGB2018'
    }
    workspaceCapping: {
      dailyQuotaGb: 1
    }
  }
}

resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: applicationInsightsName
  location: location
  tags: tags
  kind: 'web'
  properties: {
    Application_Type: 'web'
    DisableIpMasking: false
    DisableLocalAuth: false
    Flow_Type: 'Bluefield'
    IngestionMode: 'LogAnalytics'
    RetentionInDays: 90
    SamplingPercentage: 100
    WorkspaceResourceId: logAnalyticsWorkspace.id
    publicNetworkAccessForIngestion: 'Enabled'
    publicNetworkAccessForQuery: 'Enabled'
  }
}

output logAnalyticsWorkspaceName string = logAnalyticsWorkspace.name
output logAnalyticsWorkspaceId string = logAnalyticsWorkspace.id
output applicationInsightsName string = applicationInsights.name
output applicationInsightsId string = applicationInsights.id

WorkspaceResourceId: logAnalyticsWorkspace.id ist eine symbolische Referenz. Bicep leitet daraus ab, dass Application Insights auf den Arbeitsbereich warten muss.

Das tägliche Limit von einem Gigabyte begrenzt versehentliche Datenaufnahme in der Lernumgebung. Monitoringressourcen können dennoch Azure-Kosten verursachen.

Den Einstiegspunkt zum Umgebungsorchestrator machen

Behalte die vorhandenen Parameter in cloudtrips-bicep/main.bicep. Ergänze ein gemeinsames Tagobjekt, damit jedes neue Modul dieselben Geschäftsdaten erhält:

var commonTags = {
  Application: applicationName
  CostCenter: costCenter
  Environment: toUpper(environment)
  ManagedBy: 'Bicep'
  Owner: owner
}

Behalte das vorhandene Modul storage und ergänze:

module keyVault './modules/key-vault.bicep' = {
  name: '${deployment().name}-key-vault'
  params: {
    environment: environment
    location: location
    tags: commonTags
  }
}

module monitoring './modules/monitoring.bicep' = {
  name: '${deployment().name}-monitoring'
  params: {
    environment: environment
    location: location
    tags: commonTags
  }
}

Gib die wichtigen Modulergebnisse und eine kompakte Bereitstellungszusammenfassung aus:

output keyVaultName string = keyVault.outputs.keyVaultName
output keyVaultId string = keyVault.outputs.keyVaultId
output keyVaultUri string = keyVault.outputs.keyVaultUri
output logAnalyticsWorkspaceName string = monitoring.outputs.logAnalyticsWorkspaceName
output logAnalyticsWorkspaceId string = monitoring.outputs.logAnalyticsWorkspaceId
output applicationInsightsName string = monitoring.outputs.applicationInsightsName
output applicationInsightsId string = monitoring.outputs.applicationInsightsId
output environmentSummary object = {
  applicationInsightsName: monitoring.outputs.applicationInsightsName
  keyVaultName: keyVault.outputs.keyVaultName
  logAnalyticsWorkspaceName: monitoring.outputs.logAnalyticsWorkspaceName
  resourceGroupName: resourceGroup().name
  storageAccountName: storage.outputs.storageAccountName
}

Reiche diese Outputs durch subscription.bicep weiter. Diese Datei bleibt der einzige Befehlseinstiegspunkt, der die Ressourcengruppe erstellt und darin anschließend main.bicep ausführt.

Die Parameterdateien der Umgebungen vervollständigen

Die vorhandenen Parameterdateien auf Ressourcengruppenebene funktionieren weiter, weil sich der Eingabevertrag nicht geändert hat. Ergänze neben der vorhandenen TEST-Datei Abonnementdateien für DEV und PROD:

  • environments/dev.subscription.bicepparam
  • environments/test.subscription.bicepparam
  • environments/prod.subscription.bicepparam

Jede Datei verweist auf subscription.bicep und liefert einen eigenen Ressourcengruppennamen, eine Redundanzstufe, eine Kostenstelle, eine Containerliste und die Entscheidung zum Audit-Container. PROD verwendet zum Beispiel Standard_ZRS, drei Anwendungscontainer und den Audit-Container. DEV bleibt bei Standard_LRS und nur uploads.

Die vollständige Lösung validieren

Prüfe im Stammverzeichnis des Repositorys jeden Einstiegspunkt und jedes neue Modul:

az bicep lint \
  --file cloudtrips-bicep/modules/key-vault.bicep

az bicep lint \
  --file cloudtrips-bicep/modules/monitoring.bicep

az bicep lint \
  --file cloudtrips-bicep/main.bicep

az bicep lint \
  --file cloudtrips-bicep/subscription.bicep

Kompiliere die Verträge aller drei Umgebungen:

az bicep build-params \
  --file cloudtrips-bicep/environments/dev.subscription.bicepparam \
  --stdout > /dev/null

az bicep build-params \
  --file cloudtrips-bicep/environments/test.subscription.bicepparam \
  --stdout > /dev/null

az bicep build-params \
  --file cloudtrips-bicep/environments/prod.subscription.bicepparam \
  --stdout > /dev/null

Fahre fort, wenn alle Befehle ohne Diagnosemeldungen abgeschlossen werden.

Der freigegebene TEST-Snapshot muss sich jetzt ändern, weil Key Vault und Monitoring beabsichtigte Ergänzungen sind. Prüfe die kompilierte Änderung und erzeuge danach mit demselben deterministischen Kontext wie zuvor die neue Baseline:

"$HOME/.azure/bin/bicep" snapshot cloudtrips-bicep/environments/test.bicepparam \
  --mode overwrite \
  --subscription-id 00000000-0000-0000-0000-000000000000 \
  --resource-group rg-cloudtrips-bicep-test-weu \
  --location westeurope \
  --deployment-name deploy-cloudtrips-storage-test

"$HOME/.azure/bin/bicep" snapshot cloudtrips-bicep/environments/test.bicepparam \
  --mode validate \
  --subscription-id 00000000-0000-0000-0000-000000000000 \
  --resource-group rg-cloudtrips-bicep-test-weu \
  --location westeurope \
  --deployment-name deploy-cloudtrips-storage-test

Die vollständige TEST-Umgebung in der Vorschau prüfen

Wähle das TEST-Abonnement aus und führe die Azure-Preflightvalidierung aus:

az account set \
  --subscription "<Name oder ID des CloudTrips-TEST-Abonnements>"

az deployment sub validate \
  --name validate-cloudtrips-complete-test \
  --location westeurope \
  --parameters cloudtrips-bicep/environments/test.subscription.bicepparam \
  --validation-level Provider \
  --query "properties.provisioningState" \
  --output tsv

Das Ergebnis sollte Succeeded sein. Prüfe nun die Liveänderung:

az deployment sub what-if \
  --name preview-cloudtrips-complete-test \
  --location westeurope \
  --parameters cloudtrips-bicep/environments/test.subscription.bicepparam \
  --validation-level Provider

Die Vorschau sollte den Key Vault, den Log-Analytics-Arbeitsbereich, Application Insights und deren Modulbereitstellungen erstellen. Sie darf das vorhandene Speicherkonto oder seine Container nicht neu erstellen. Bereits bekannte Standardwerte der Provider können weiterhin als Modify erscheinen.

Abonnementvorschau mit neuem CloudTrips Key Vault und Monitoring ohne Austausch des Speichers

Die Umgebung bereitstellen und prüfen

Stelle die vollständige TEST-Grundlage bereit:

az deployment sub create \
  --name deploy-cloudtrips-complete-test \
  --location westeurope \
  --parameters cloudtrips-bicep/environments/test.subscription.bicepparam \
  --query "properties.outputs.environmentSummary.value" \
  --output yaml

Die Zusammenfassung sollte die TEST-Ressourcengruppe und die deterministischen Namen des Speicherkontos, des Key Vaults, des Log-Analytics-Arbeitsbereichs und von Application Insights enthalten.

Erfolgreiche vollständige CloudTrips-TEST-Bereitstellung mit den zusammengefassten Umgebungsoutputs

Liste die bereitgestellten Ressourcen der obersten Ebene auf:

az resource list \
  --resource-group rg-cloudtrips-bicep-test-weu \
  --query "[].{name:name,type:type,location:location}" \
  --output table

Bestätige, dass die Ressourcengruppe das Speicherkonto, den Key Vault, den Log-Analytics-Arbeitsbereich und Application Insights enthält. Öffne die Ressourcengruppe im Azure-Portal und prüfe die erwarteten Werte für TEST, Besitzer und Kostenstelle in den gemeinsamen Tags.

CloudTrips-TEST-Ressourcengruppe mit Speicher, Key Vault, Log Analytics und Application Insights sowie gemeinsamen Tags

Azure-Portal mit der vollständigen CloudTrips-TEST-Umgebung und ihren bereitgestellten Ressourcen

Die Wiederholbarkeit der Bereitstellung beweisen

Führe nach der Bereitstellung denselben az deployment sub what-if-Befehl erneut aus. Es dürfen keine neuen Ressourcennamen, Ersetzungen oder unerwarteten Löschungen erscheinen. Standardwerte der Azure-Provider können weiterhin als Modify angezeigt werden, die vier Ressourcen der obersten Ebene müssen jedoch dieselben bleiben.

Das Ergebnis ist wiederholbar, weil Umgebungsunterschiede in Parameterdateien liegen, die Benennung deterministisch ist, Dienste in Module getrennt sind, Abhängigkeiten aus symbolischen Referenzen entstehen und der Einstiegspunkt auf Abonnementebene den Bereichswechsel verwaltet. CloudTrips kann dieselbe Anwendungsgrundlage nun konsistent prüfen und erneut erstellen, anstatt sie manuell zusammenzubauen.