From 701b463f78961886206d283d1144a11f01e9b505 Mon Sep 17 00:00:00 2001 From: Federico Arambarri Date: Fri, 7 Nov 2025 15:43:20 -0300 Subject: [PATCH 1/4] Update libraries and and delete kubernetes dependencies --- .../Fabrikam.DroneDelivery.Common.csproj | 2 +- ...DroneDelivery.DeliveryService.Tests.csproj | 12 +++++------ ...rikam.DroneDelivery.DeliveryService.csproj | 7 +++---- .../Startup.cs | 5 ----- ...elivery.DroneSchedulerService.Tests.csproj | 7 +++---- ...DroneDelivery.DroneSchedulerService.csproj | 6 ++---- .../Startup.cs | 5 ----- .../Fabrikam.Workflow.Service.Tests.csproj | 5 ++--- .../Fabrikam.Workflow.Service.csproj | 20 +++++++++---------- .../ServiceStartup.cs | 5 ----- 10 files changed, 26 insertions(+), 48 deletions(-) diff --git a/workload/src/shipping/delivery/Fabrikam.DroneDelivery.Common/Fabrikam.DroneDelivery.Common.csproj b/workload/src/shipping/delivery/Fabrikam.DroneDelivery.Common/Fabrikam.DroneDelivery.Common.csproj index 1eab25c..8be82d3 100644 --- a/workload/src/shipping/delivery/Fabrikam.DroneDelivery.Common/Fabrikam.DroneDelivery.Common.csproj +++ b/workload/src/shipping/delivery/Fabrikam.DroneDelivery.Common/Fabrikam.DroneDelivery.Common.csproj @@ -5,7 +5,7 @@ - + diff --git a/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService.Tests/Fabrikam.DroneDelivery.DeliveryService.Tests.csproj b/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService.Tests/Fabrikam.DroneDelivery.DeliveryService.Tests.csproj index 17c25af..7d79db7 100644 --- a/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService.Tests/Fabrikam.DroneDelivery.DeliveryService.Tests.csproj +++ b/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService.Tests/Fabrikam.DroneDelivery.DeliveryService.Tests.csproj @@ -7,14 +7,14 @@ - - - - + + + + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService/Fabrikam.DroneDelivery.DeliveryService.csproj b/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService/Fabrikam.DroneDelivery.DeliveryService.csproj index 5064347..6f37a56 100644 --- a/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService/Fabrikam.DroneDelivery.DeliveryService.csproj +++ b/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService/Fabrikam.DroneDelivery.DeliveryService.csproj @@ -13,15 +13,14 @@ - + - - - + + diff --git a/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService/Startup.cs b/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService/Startup.cs index 1853796..6ccd82c 100644 --- a/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService/Startup.cs +++ b/workload/src/shipping/delivery/Fabrikam.DroneDelivery.DeliveryService/Startup.cs @@ -51,11 +51,6 @@ public void ConfigureServices(IServiceCollection services) services.AddSingleton(); // Configure AppInsights - var kubernetesEnricher = Configuration["KubernetesEnricher"]; - if (kubernetesEnricher != null && "true".Equals(kubernetesEnricher)) - { - services.AddApplicationInsightsKubernetesEnricher(); - } services.AddApplicationInsightsTelemetry(Configuration); // Add health check diff --git a/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService.Tests/Fabrikam.DroneDelivery.DroneSchedulerService.Tests.csproj b/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService.Tests/Fabrikam.DroneDelivery.DroneSchedulerService.Tests.csproj index 729ac6c..399f7a3 100644 --- a/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService.Tests/Fabrikam.DroneDelivery.DroneSchedulerService.Tests.csproj +++ b/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService.Tests/Fabrikam.DroneDelivery.DroneSchedulerService.Tests.csproj @@ -6,10 +6,9 @@ - - - - + + + diff --git a/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService/Fabrikam.DroneDelivery.DroneSchedulerService.csproj b/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService/Fabrikam.DroneDelivery.DroneSchedulerService.csproj index 8d11338..09c3380 100644 --- a/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService/Fabrikam.DroneDelivery.DroneSchedulerService.csproj +++ b/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService/Fabrikam.DroneDelivery.DroneSchedulerService.csproj @@ -13,17 +13,15 @@ - - - + - + diff --git a/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService/Startup.cs b/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService/Startup.cs index 15b91e0..535416f 100644 --- a/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService/Startup.cs +++ b/workload/src/shipping/dronescheduler/Fabrikam.DroneDelivery.DroneSchedulerService/Startup.cs @@ -37,11 +37,6 @@ public void ConfigureServices(IServiceCollection services) services.AddFeatureManagement(); // Configure AppInsights - var kubernetesEnricher = Configuration["KubernetesEnricher"]; - if (kubernetesEnricher != null && "true".Equals(kubernetesEnricher)) - { - services.AddApplicationInsightsKubernetesEnricher(); - } services.AddApplicationInsightsTelemetry(Configuration); // Add framework services. diff --git a/workload/src/shipping/workflow/Fabrikam.Workflow.Service.Tests/Fabrikam.Workflow.Service.Tests.csproj b/workload/src/shipping/workflow/Fabrikam.Workflow.Service.Tests/Fabrikam.Workflow.Service.Tests.csproj index e2dfda2..c4a6a79 100644 --- a/workload/src/shipping/workflow/Fabrikam.Workflow.Service.Tests/Fabrikam.Workflow.Service.Tests.csproj +++ b/workload/src/shipping/workflow/Fabrikam.Workflow.Service.Tests/Fabrikam.Workflow.Service.Tests.csproj @@ -6,9 +6,8 @@ - - - + + diff --git a/workload/src/shipping/workflow/Fabrikam.Workflow.Service/Fabrikam.Workflow.Service.csproj b/workload/src/shipping/workflow/Fabrikam.Workflow.Service/Fabrikam.Workflow.Service.csproj index 7b3e7bc..f25ace9 100644 --- a/workload/src/shipping/workflow/Fabrikam.Workflow.Service/Fabrikam.Workflow.Service.csproj +++ b/workload/src/shipping/workflow/Fabrikam.Workflow.Service/Fabrikam.Workflow.Service.csproj @@ -10,24 +10,22 @@ - - + - - - - - - - - + + + + + + + - + diff --git a/workload/src/shipping/workflow/Fabrikam.Workflow.Service/ServiceStartup.cs b/workload/src/shipping/workflow/Fabrikam.Workflow.Service/ServiceStartup.cs index 786fd38..a0fd16c 100644 --- a/workload/src/shipping/workflow/Fabrikam.Workflow.Service/ServiceStartup.cs +++ b/workload/src/shipping/workflow/Fabrikam.Workflow.Service/ServiceStartup.cs @@ -23,11 +23,6 @@ public static void ConfigureServices(HostBuilderContext context, IServiceCollect services.AddOptions(); // Configure AppInsights - var kubernetesEnricher = context.Configuration["KubernetesEnricher"]; - if (kubernetesEnricher != null && "true".Equals(kubernetesEnricher)) - { - services.AddApplicationInsightsKubernetesEnricher(); - } services.AddApplicationInsightsTelemetry(context.Configuration); services.Configure(context.Configuration); From 48071dfb4a4cb548730bbe1f75f76a308e6c094c Mon Sep 17 00:00:00 2001 From: Federico Arambarri Date: Fri, 7 Nov 2025 17:21:13 -0300 Subject: [PATCH 2/4] Improvements --- README.md | 20 ++- workload/nested_workload-stamp-prereqs.bicep | 57 --------- workload/workload-stamp-prereqs.bicep | 27 ---- workload/workload-stamp.bicep | 126 +++++++++++++------ 4 files changed, 97 insertions(+), 133 deletions(-) delete mode 100644 workload/nested_workload-stamp-prereqs.bicep delete mode 100644 workload/workload-stamp-prereqs.bicep diff --git a/README.md b/README.md index eb6284e..f0a467f 100644 --- a/README.md +++ b/README.md @@ -93,9 +93,16 @@ Following the steps below will result in the creation of the following Azure res 1. Create a resource group for your deployment. ```bash - export PREREQS_DEPLOYMENT_NAME=workload-stamp-prereqs-${LOCATION} + az group create -n rg-shipping-dronedelivery-${LOCATION} -l ${LOCATION} + ``` + +1. Deploy all the dependencies of the various microservices that comprise the workload. - az deployment sub create --name $PREREQS_DEPLOYMENT_NAME --location ${LOCATION} --template-file ./workload/workload-stamp-prereqs.bicep --parameters resourceGroupLocation=${LOCATION} + > None of these resources are for the application platform hosting the workload, but instead are tied directly to the drone delivery workload. For example, the per-microservice Key Vault, the per-microservice data stores, the message queue, logging sinks, etc. These same resources would exist no matter if the application platform was Azure Container Apps, Kubernetes, or App Service. + + ```bash + # [This takes about 18 minutes.] + az deployment group create -n workload-stamp -g rg-shipping-dronedelivery-${LOCATION} -f ./workload/workload-stamp.bicep ``` 1. Get the user identities. @@ -113,15 +120,6 @@ Following the steps below will result in the creation of the following Azure res until az ad sp show --id $WORKFLOW_PRINCIPAL_ID &> /dev/null ; do echo "Waiting for Microsoft Entra ID propagation" && sleep 5; done until az ad sp show --id $PACKAGE_ID_PRINCIPAL_ID &> /dev/null ; do echo "Waiting for Microsoft Entra ID propagation" && sleep 5; done until az ad sp show --id $INGESTION_ID_PRINCIPAL_ID &> /dev/null ; do echo "Waiting for Microsoft Entra ID propagation" && sleep 5; done - `` - -1. Deploy all the dependencies of the various microservices that comprise the workload. - - > None of these resources are for the application platform hosting the workload, but instead are tied directly to the drone delivery workload. For example, the per-microservice Key Vault, the per-microservice data stores, the message queue, logging sinks, etc. These same resources would exist no matter if the application platform was Azure Container Apps, Kubernetes, or App Service. - - ```bash - # [This takes about 18 minutes.] - az deployment group create -n workload-stamp -g rg-shipping-dronedelivery-${LOCATION} -f ./workload/workload-stamp.bicep -p droneSchedulerPrincipalId=$DRONESCHEDULER_PRINCIPAL_ID -p workflowPrincipalId=$WORKFLOW_PRINCIPAL_ID -p deliveryPrincipalId=$DELIVERY_PRINCIPAL_ID -p ingestionPrincipalId=$INGESTION_ID_PRINCIPAL_ID -p packagePrincipalId=$PACKAGE_ID_PRINCIPAL_ID ``` 1. Build, tag, and host the five microservice container images in ACR. diff --git a/workload/nested_workload-stamp-prereqs.bicep b/workload/nested_workload-stamp-prereqs.bicep deleted file mode 100644 index 73e7430..0000000 --- a/workload/nested_workload-stamp-prereqs.bicep +++ /dev/null @@ -1,57 +0,0 @@ -@description('Azure Container Registry resource group location.') -param location string = resourceGroup().location - -resource workflowManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: 'uid-workflow' - location: location - tags: { - displayName: 'workflow managed identity' - what: 'rbac' - reason: 'aad-workload-identity' - app: 'fabrikam-workflow' - } -} - -resource deliveryManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: 'uid-delivery' - location: location - tags: { - displayName: 'delivery managed identity' - what: 'rbac' - reason: 'aad-workload-identity' - app: 'fabrikam-delivery' - } -} - -resource droneschedulerManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: 'uid-dronescheduler' - location: location - tags: { - displayName: 'dronescheduler managed identity' - what: 'rbac' - reason: 'aad-workload-identity' - app: 'fabrikam-dronescheduler' - } -} - -resource ingestionManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: 'uid-ingestion' - location: location - tags: { - displayName: 'ingestion managed identity' - what: 'rbac' - reason: 'aad-workload-identity' - app: 'fabrikam-ingestion' - } -} - -resource packageManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = { - name: 'uid-package' - location: location - tags: { - displayName: 'package managed identity' - what: 'rbac' - reason: 'aad-workload-identity' - app: 'fabrikam-package' - } -} diff --git a/workload/workload-stamp-prereqs.bicep b/workload/workload-stamp-prereqs.bicep deleted file mode 100644 index b80b2b6..0000000 --- a/workload/workload-stamp-prereqs.bicep +++ /dev/null @@ -1,27 +0,0 @@ -targetScope = 'subscription' - -param resourceGroupLocation string = 'eastus' - -resource resourceGroupShippingDronedelivery 'Microsoft.Resources/resourceGroups@2022-09-01' = { - name: 'rg-shipping-dronedelivery-${resourceGroupLocation}' - location: resourceGroupLocation - tags: { - displayName: 'Resource Group for general purpose' - } -} - -resource resourceGroupShippingDronedeliveryAcr 'Microsoft.Resources/resourceGroups@2022-09-01' = { - name: 'rg-shipping-dronedelivery-${resourceGroupLocation}-acr' - location: resourceGroupLocation - tags: { - displayName: 'Container Registry Resource Group' - } -} - -module workloadStampPrereqsDep './nested_workload-stamp-prereqs.bicep' = { - name: 'workload-stamp-prereqs-dep' - scope: resourceGroupShippingDronedelivery - params: { - location: resourceGroupLocation - } -} diff --git a/workload/workload-stamp.bicep b/workload/workload-stamp.bicep index 373143d..9ea58f4 100644 --- a/workload/workload-stamp.bicep +++ b/workload/workload-stamp.bicep @@ -26,17 +26,13 @@ param location string = resourceGroup().location 'southeastasia' ]) param geoRedundancyLocation string = 'centralus' -param droneSchedulerPrincipalId string -param workflowPrincipalId string -param deliveryPrincipalId string -param ingestionPrincipalId string -param packagePrincipalId string + var prefix = substring(uniqueString(subscription().subscriptionId, resourceGroup().id), 0, 10) var acrName = 'acr${prefix}' var appInsightsName = 'ai-${prefix}' var logAnalyticsWorkspaceName = 'law-${prefix}' -var nestedACRDeploymentName = '${resourceGroup().name}-acr-deployment' +var nestedACRDeploymentName = '${resourceGroup().name}-deployment' var deliveryRedisCacheSKU = 'Basic' var deliveryRedisCacheFamily = 'C' var deliveryRedisCacheCapacity = 0 @@ -58,14 +54,68 @@ var workflowServiceAccessKeyName = 'WorkflowServiceAccessKey' var keyVaultSecretsUserRole = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4633458b-17de-408a-b874-0445c86b69e6') @description('Built-in Role: Reader - https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#reader') -resource builtInReaderRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { +resource builtInReaderRole 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = { name: 'acdd72a7-3385-48ef-bd42-f606fba81ae7' scope: subscription() } +resource workflowManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2025-01-31-preview' = { + name: 'uid-workflow' + location: location + tags: { + displayName: 'workflow managed identity' + what: 'rbac' + reason: 'aad-workload-identity' + app: 'fabrikam-workflow' + } +} + +resource deliveryManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2025-01-31-preview' = { + name: 'uid-delivery' + location: location + tags: { + displayName: 'delivery managed identity' + what: 'rbac' + reason: 'aad-workload-identity' + app: 'fabrikam-delivery' + } +} + +resource droneSchedulerManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2025-01-31-preview' = { + name: 'uid-dronescheduler' + location: location + tags: { + displayName: 'dronescheduler managed identity' + what: 'rbac' + reason: 'aad-workload-identity' + app: 'fabrikam-dronescheduler' + } +} + +resource ingestionManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2025-01-31-preview' = { + name: 'uid-ingestion' + location: location + tags: { + displayName: 'ingestion managed identity' + what: 'rbac' + reason: 'aad-workload-identity' + app: 'fabrikam-ingestion' + } +} + +resource packageManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2025-01-31-preview' = { + name: 'uid-package' + location: location + tags: { + displayName: 'package managed identity' + what: 'rbac' + reason: 'aad-workload-identity' + app: 'fabrikam-package' + } +} + module containerRegistry './nested_workload-stamp.bicep' = { name: nestedACRDeploymentName - scope: resourceGroup('rg-shipping-dronedelivery-${location}-acr') params: { location: location acrName: acrName @@ -92,7 +142,7 @@ resource deliveryRedis 'Microsoft.Cache/Redis@2020-06-01' = { dependsOn: [] } -resource deliveryCosmosDb 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' = { +resource deliveryCosmosDb 'Microsoft.DocumentDB/databaseAccounts@2025-05-01-preview' = { name: deliveryCosmosDbName location: location tags: { @@ -113,7 +163,7 @@ resource deliveryCosmosDb 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' = { dependsOn: [] } -resource packageMongoDb 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' = { +resource packageMongoDb 'Microsoft.DocumentDB/databaseAccounts@2025-05-01-preview' = { name: packageMongoDbName kind: 'MongoDB' location: location @@ -138,7 +188,7 @@ resource packageMongoDb 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' = { dependsOn: [] } -resource packageKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { +resource packageKeyVault 'Microsoft.KeyVault/vaults@2025-05-01' = { name: packageKeyVaultName location: location tags: { @@ -182,15 +232,15 @@ resource packageKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { resource packagePrincipalKeyVaultSecretsUserRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: packageKeyVault - name: guid(packagePrincipalId, packageKeyVault.name, keyVaultSecretsUserRole) + name: guid(packageManagedIdentity.id, packageKeyVault.name, keyVaultSecretsUserRole) properties: { roleDefinitionId: keyVaultSecretsUserRole - principalId: packagePrincipalId + principalId: packageManagedIdentity.properties.principalId principalType: 'ServicePrincipal' } } -resource droneSchedulerCosmosDb 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' = { +resource droneSchedulerCosmosDb 'Microsoft.DocumentDB/databaseAccounts@2025-05-01-preview' = { name: droneSchedulerCosmosDbName location: location tags: { @@ -211,7 +261,7 @@ resource droneSchedulerCosmosDb 'Microsoft.DocumentDB/databaseAccounts@2023-04-1 dependsOn: [] } -resource ingestionSBNamespace 'Microsoft.ServiceBus/namespaces@2022-10-01-preview' = { +resource ingestionSBNamespace 'Microsoft.ServiceBus/namespaces@2025-05-01-preview' = { name: ingestionSBNamespaceName location: location sku: { @@ -226,7 +276,7 @@ resource ingestionSBNamespace 'Microsoft.ServiceBus/namespaces@2022-10-01-previe } } -resource ingestionSBNamespaceIngestionSB 'Microsoft.ServiceBus/namespaces/queues@2022-10-01-preview' = { +resource ingestionSBNamespaceIngestionSB 'Microsoft.ServiceBus/namespaces/queues@2025-05-01-preview' = { parent: ingestionSBNamespace name: ingestionSBName properties: { @@ -235,7 +285,7 @@ resource ingestionSBNamespaceIngestionSB 'Microsoft.ServiceBus/namespaces/queues } } -resource ingestionSBNamespaceIngestionServiceAccessKey 'Microsoft.ServiceBus/namespaces/AuthorizationRules@2022-10-01-preview' = { +resource ingestionSBNamespaceIngestionServiceAccessKey 'Microsoft.ServiceBus/namespaces/AuthorizationRules@2025-05-01-preview' = { parent: ingestionSBNamespace name: ingestionServiceAccessKeyName properties: { @@ -245,7 +295,7 @@ resource ingestionSBNamespaceIngestionServiceAccessKey 'Microsoft.ServiceBus/nam } } -resource ingestionSBNamespaceWorkflowServiceAccessKey 'Microsoft.ServiceBus/namespaces/AuthorizationRules@2022-10-01-preview' = { +resource ingestionSBNamespaceWorkflowServiceAccessKey 'Microsoft.ServiceBus/namespaces/AuthorizationRules@2025-05-01-preview' = { parent: ingestionSBNamespace name: workflowServiceAccessKeyName properties: { @@ -255,7 +305,7 @@ resource ingestionSBNamespaceWorkflowServiceAccessKey 'Microsoft.ServiceBus/name } } -resource deliveryKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { +resource deliveryKeyVault 'Microsoft.KeyVault/vaults@2025-05-01' = { name: deliveryKeyVaultName location: location tags: { @@ -314,10 +364,10 @@ resource deliveryKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { resource deliveryPrincipalKeyVaultSecretsUserRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: deliveryKeyVault - name: guid(deliveryPrincipalId, deliveryKeyVault.name, keyVaultSecretsUserRole) + name: guid(deliveryManagedIdentity.id, deliveryKeyVault.name, keyVaultSecretsUserRole) properties: { roleDefinitionId: keyVaultSecretsUserRole - principalId: deliveryPrincipalId + principalId: deliveryManagedIdentity.properties.principalId principalType: 'ServicePrincipal' } } @@ -360,15 +410,15 @@ resource ingestionKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { resource ingestionPrincipalVaultSecretsUserRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: ingestionKeyVault - name: guid(ingestionPrincipalId, ingestionKeyVault.name, keyVaultSecretsUserRole) + name: guid(ingestionManagedIdentity.id, ingestionKeyVault.name, keyVaultSecretsUserRole) properties: { roleDefinitionId: keyVaultSecretsUserRole - principalId: ingestionPrincipalId + principalId: ingestionManagedIdentity.properties.principalId principalType: 'ServicePrincipal' } } -resource droneSchedulerKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { +resource droneSchedulerKeyVault 'Microsoft.KeyVault/vaults@2025-05-01' = { name: droneSchedulerKeyVaultName location: location tags: { @@ -393,7 +443,7 @@ resource droneSchedulerKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { resource secretApplicationInsights 'secrets' = { name: 'ApplicationInsights--InstrumentationKey' properties: { - value: reference(appInsights.id, '2015-05-01').InstrumentationKey + value: appInsights.properties.InstrumentationKey } } @@ -407,15 +457,15 @@ resource droneSchedulerKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { resource droneSchedulerPrincipalKeyVaultSecretsUserRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: droneSchedulerKeyVault - name: guid(droneSchedulerPrincipalId, droneSchedulerKeyVault.name, keyVaultSecretsUserRole) + name: guid(droneSchedulerManagedIdentity.id, droneSchedulerKeyVault.name, keyVaultSecretsUserRole) properties: { roleDefinitionId: keyVaultSecretsUserRole - principalId: droneSchedulerPrincipalId + principalId: droneSchedulerManagedIdentity.properties.principalId principalType: 'ServicePrincipal' } } -resource workflowKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { +resource workflowKeyVault 'Microsoft.KeyVault/vaults@2025-05-01' = { name: workflowKeyVaultName location: location tags: { @@ -440,29 +490,29 @@ resource workflowKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { resource secretQueueAccessPolicyKey 'secrets' = { name: 'QueueAccessPolicyKey' properties: { - value: listkeys(ingestionSBNamespaceWorkflowServiceAccessKey.id, '2017-04-01').primaryKey + value: ingestionSBNamespaceWorkflowServiceAccessKey.listKeys().primaryKey } } resource secretApplicationInsights 'secrets' = { name: 'ApplicationInsights--InstrumentationKey' properties: { - value: reference(appInsights.id, '2015-05-01').InstrumentationKey + value: appInsights.properties.InstrumentationKey } } } resource workflowPrincipalKeyVaultSecretsUserRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = { scope: workflowKeyVault - name: guid(workflowPrincipalId, workflowKeyVault.name, keyVaultSecretsUserRole) + name: guid(workflowManagedIdentity.id, workflowKeyVault.name, keyVaultSecretsUserRole) properties: { roleDefinitionId: keyVaultSecretsUserRole - principalId: workflowPrincipalId + principalId: workflowManagedIdentity.properties.principalId principalType: 'ServicePrincipal' } } -resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { +resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2025-02-01' = { name: logAnalyticsWorkspaceName location: location properties: { @@ -495,7 +545,7 @@ resource deliveryKeyVaultMicrosoftAuthorizationDeliveryIdNameIdReaderRole 'Micro scope: deliveryKeyVault properties: { roleDefinitionId: builtInReaderRole.id - principalId: deliveryPrincipalId + principalId: deliveryManagedIdentity.properties.principalId principalType: 'ServicePrincipal' } } @@ -505,7 +555,7 @@ resource workflowKeyVaultNameMicrosoftAuthorizationWorkflowIdNameIdReaderRole 'M scope: workflowKeyVault properties: { roleDefinitionId: builtInReaderRole.id - principalId: workflowPrincipalId + principalId: workflowManagedIdentity.properties.principalId principalType: 'ServicePrincipal' } } @@ -515,7 +565,7 @@ resource droneSchedulerKeyVaultNameMicrosoftAuthorizationDroneSchedulerIdNameIdR scope: droneSchedulerKeyVault properties: { roleDefinitionId: builtInReaderRole.id - principalId: droneSchedulerPrincipalId + principalId: droneSchedulerManagedIdentity.properties.principalId principalType: 'ServicePrincipal' } } @@ -525,7 +575,7 @@ resource ingestionKeyVaultNameMicrosoftAuthorizationIngestionIdNameIdReaderRole scope: ingestionKeyVault properties: { roleDefinitionId: builtInReaderRole.id - principalId: ingestionPrincipalId + principalId: ingestionManagedIdentity.properties.principalId principalType: 'ServicePrincipal' } } @@ -535,7 +585,7 @@ resource packageKeyVaultNameMicrosoftAuthorizationPackageIdNameIdReaderRole 'Mic scope: packageKeyVault properties: { roleDefinitionId: builtInReaderRole.id - principalId: packagePrincipalId + principalId: packageManagedIdentity.properties.principalId principalType: 'ServicePrincipal' } } From d512cf66de16a7dbb59d226cedce54d0674637ab Mon Sep 17 00:00:00 2001 From: Federico Arambarri Date: Mon, 10 Nov 2025 14:32:23 -0300 Subject: [PATCH 3/4] Readme Adjustments --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f0a467f..59638b1 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This repo contains the implementation that backs the [Deploy microservices with ## Introduction -Fabrikam inc has created a new operations team, and under its organization is a brownfield application called Drone Delivery. This application been running for a while in Azure Kubernetes Service (AKS), and while they are obtaining the benefits of containers to run microservices and Kubernetes to host them, it has been discovered that they are not making use of any of the advance features of AKS like custom service mesh or autoscaling among others. +Fabrikam inc has created a new operations team, and under its organization is a brownfield application called Drone Delivery. This application has been running for a while in Azure Kubernetes Service (AKS), and while they are obtaining the benefits of containers to run microservices and Kubernetes to host them, it has been discovered that they are not making use of any of the advanced features of AKS like custom service mesh or autoscaling among others. The team has detected an opportunity to simplify and be more efficient at the DevOps level, and this is why they are now looking into Azure Container Apps to evaluate hosting Fabrikam Drone Delivery. This will allow them to publish and run containerized microservices at scale, faster than before, reducing the complexity, saving resources by using scale-to-zero, built-in autoscaling capability, and without losing all the container advantages they love. @@ -21,7 +21,7 @@ This repository guides you through the process of running a single workload comp For more information on how the Container Apps features are being used in this reference implementation, please take a look below: -- [HTTPS ingress, this allows to expose the Ingestion service to internet.](https://learn.microsoft.com/azure/container-apps/ingress-overview) +- [HTTPS ingress, this allows to expose the Ingestion service to the internet.](https://learn.microsoft.com/azure/container-apps/ingress-overview) - [Internal service discovery, Delivery, DroneScheduler and Package services must be internally reachable by Workflow service](https://learn.microsoft.com/azure/container-apps/connect-apps) - [Use user-assigned identities when authenticating into Azure KeyVault from Delivery and DroneScheduler services](https://learn.microsoft.com/azure/container-apps/managed-identity#add-a-user-assigned-identity) - [Securely manage secrets for Package, Ingestion and Workflow services](https://learn.microsoft.com/azure/container-apps/manage-secrets) @@ -37,7 +37,7 @@ Following the steps below will result in the creation of the following Azure res | Object | Purpose | | :------------------------------------- | :------------------------------------------------------ | | An Azure Container App Environment | This is the managed Container App environment where Container Apps are deployed | -| Five Azure Container Apps | These are the Azure resources that represents the five Fabrikam microservices in the Azure Container App environment | +| Five Azure Container Apps | These are the Azure resources that represent the five Fabrikam microservices in the Azure Container App environment | | An Azure Container Registry | This is the private container registry where all Fabrikam workload images are uploaded and later pulled from the different Azure Container Apps | | An Azure Log Analytics Workspace | This is where all the Container Apps logs are sent, along with Azure Diagnostics on all services | | An Azure Application Insights instance | All services are sending trace information to a shared Azure Application Insights instance | @@ -190,7 +190,7 @@ Following the steps below will result in the creation of the following Azure res echo -e "\nIngestion Config:\nINGESTION_NAMESPACE_NAME=${INGESTION_NAMESPACE_NAME}\nINGESTION_NAMESPACE_SAS_NAME=${INGESTION_NAMESPACE_SAS_NAME}\nINGESTION_NAMESPACE_SAS_KEY=${INGESTION_NAMESPACE_SAS_KEY}\nINGESTION_QUEUE_NAME=${INGESTION_QUEUE_NAME}" ``` - If any of the config values were empty above, please stop and troubleshoot before proceeding. + If any of the configuration values above are empty, stop and troubleshoot before proceeding. 1. Deploy the Container Apps ARM template. @@ -304,7 +304,6 @@ az containerapp revision restart -g rg-shipping-dronedelivery --app Date: Mon, 10 Nov 2025 16:08:14 -0300 Subject: [PATCH 4/4] Api updates --- README.md | 2 +- acrpull-roleassignment.bicep | 4 ++-- container-http.bicep | 10 +++++----- environment.bicep | 6 +++--- workload/nested_workload-stamp.bicep | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 59638b1..bed54ab 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ Following the steps below will result in the creation of the following Azure res > None of these resources are for the application platform hosting the workload, but instead are tied directly to the drone delivery workload. For example, the per-microservice Key Vault, the per-microservice data stores, the message queue, logging sinks, etc. These same resources would exist no matter if the application platform was Azure Container Apps, Kubernetes, or App Service. ```bash - # [This takes about 18 minutes.] + # [This takes about 22 minutes.] az deployment group create -n workload-stamp -g rg-shipping-dronedelivery-${LOCATION} -f ./workload/workload-stamp.bicep ``` diff --git a/acrpull-roleassignment.bicep b/acrpull-roleassignment.bicep index 5ede6cd..95bf18e 100644 --- a/acrpull-roleassignment.bicep +++ b/acrpull-roleassignment.bicep @@ -18,12 +18,12 @@ param containerAppName string /*** EXISTING RESOURCE ***/ @description('Existing container registry') -resource existingContainerRegistry 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' existing = { +resource existingContainerRegistry 'Microsoft.ContainerRegistry/registries@2025-05-01-preview' existing = { name: containerRegistryName } @description('Built-in ACR Pull role') -resource builtInAcrPullRole 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { +resource builtInAcrPullRole 'Microsoft.Authorization/roleDefinitions@2022-05-01-preview' existing = { scope: subscription() name: '7f951dda-4ed3-4680-a7ca-43fe172d538d' } diff --git a/container-http.bicep b/container-http.bicep index 2250c29..33bd5ca 100644 --- a/container-http.bicep +++ b/container-http.bicep @@ -64,25 +64,25 @@ var hasIngress = (containerPort == -1) ? false : true /*** EXISTING RESOURCE ***/ @description('Resource group of the existing container registry') -resource containerRegistryResourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' existing = { +resource containerRegistryResourceGroup 'Microsoft.Resources/resourceGroups@2025-04-01' existing = { scope: subscription() name: split(containerRegistryResourceId, '/')[4] } @description('Existing container registry') -resource existingContainerRegistry 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' existing = { +resource existingContainerRegistry 'Microsoft.ContainerRegistry/registries@2025-05-01-preview' existing = { scope: containerRegistryResourceGroup name: split(containerRegistryResourceId, '/')[8] } @description('Resource group of the existing managed identity') -resource managedIdentityResourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' existing = { +resource managedIdentityResourceGroup 'Microsoft.Resources/resourceGroups@2025-04-01' existing = { scope: subscription() name: split(containerAppUserAssignedResourceId, '/')[4] } @description('Existing managed identity for this service') -resource existingManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = { +resource existingManagedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2025-01-31-preview' existing = { scope: managedIdentityResourceGroup name: split(containerAppUserAssignedResourceId, '/')[8] } @@ -100,7 +100,7 @@ module acrPull './acrpull-roleassignment.bicep' = { } } -resource containerApp 'Microsoft.App/containerApps@2022-11-01-preview' = { +resource containerApp 'Microsoft.App/containerApps@2025-02-02-preview' = { name: containerAppName location: location dependsOn: [ diff --git a/environment.bicep b/environment.bicep index 5dbe969..351db61 100644 --- a/environment.bicep +++ b/environment.bicep @@ -13,12 +13,12 @@ param logAnalyticsResourceId string /*** EXISTING RESOURCES ***/ @description('Resource group of the provided log analytics workspace.') -resource laResourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' existing = { +resource laResourceGroup 'Microsoft.Resources/resourceGroups@2025-04-01' existing = { name: split(logAnalyticsResourceId, '/')[4] scope: subscription(split(logAnalyticsResourceId, '/')[2]) } -resource la 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = { +resource la 'Microsoft.OperationalInsights/workspaces@2025-02-01' existing = { name: split(logAnalyticsResourceId, '/')[8] scope: laResourceGroup } @@ -26,7 +26,7 @@ resource la 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = { /*** RESOURCES ***/ @description('The Azure Container Apps Environment') -resource cae 'Microsoft.App/managedEnvironments@2022-11-01-preview' = { +resource cae 'Microsoft.App/managedEnvironments@2025-02-02-preview' = { name: 'cae-shipping-dronedelivery' location: location properties: { diff --git a/workload/nested_workload-stamp.bicep b/workload/nested_workload-stamp.bicep index 9c09e3b..a3b8fae 100644 --- a/workload/nested_workload-stamp.bicep +++ b/workload/nested_workload-stamp.bicep @@ -30,7 +30,7 @@ param geoRedundancyLocation string @description('Azure Container Registry name.') param acrName string -resource acr 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' = { +resource acr 'Microsoft.ContainerRegistry/registries@2025-05-01-preview' = { name: acrName sku: { name: 'Premium' @@ -61,7 +61,7 @@ resource acr 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' = { } } -resource acrGeoRedundancyLocation 'Microsoft.ContainerRegistry/registries/replications@2023-01-01-preview' = { +resource acrGeoRedundancyLocation 'Microsoft.ContainerRegistry/registries/replications@2025-05-01-preview' = { parent: acr name: geoRedundancyLocation location: geoRedundancyLocation