Posted in:

This is the second part in a series about how we can build a serverless workflow using Azure Durable Functions, but implement some of the activities in that workflow using containers with Azure Container Instances. Today we'll look at creating the necessary infrastructure using the Azure CLI.

Current table of contents:

We'll create a resource group for the Function App containing:

  • A Storage Account for Durable Functions to use as well as a File Share for our containers to use
  • An Application Insights instance for monitoring and diagnostics
  • A Function App (running on the consumption plan) with a system assigned managed identity

We'll also create another resource group that will be used to host our ACI containers. Then we'll grant contributor access to our managed identity so that our Function App is allowed to create resources in that resource group.

Create Storage Account

As usual, I've chosen to automate this with the Azure CLI in PowerShell. First, we create a resource group for our Storage Account and Function App:

$resourceGroup = "DurableFunctionsAci"
$location = "westeurope"
az group create -n $resourceGroup -l $location

In my demo code, I'm using a random number as part of the Storage Account name, but this means my script isn't idempotent unless I first check whether the Storage Account already exists and use the same random number.

$existingName = az storage account list -g $resourceGroup `
  --query "[].name" -o tsv
$prefix = "durablefuncsaci"
if ($existingName) {
    $rand = $existingName.SubString($prefix.Length)
}
else
{ $rand = Get-Random -Minimum 10000 -Maximum 99999 }
$storageAccountName = "$prefix$rand"

Now we know the Storage Account name we want to use, we can create it with az storage account create which is idempotent if the Storage Account already exists. Then we can get the Storage Account key with az storage account keys list which we need for later.

az storage account create `
  -n $storageAccountName `
  -l $location `
  -g $resourceGroup `
  --sku Standard_LRS

$storageAccountKey = az storage account keys list -n $storageAccountName `
  --query [0].value -o tsv

Create a File Share

We want a File Share that we can mount to our ACI containers later. So I'll create one with az storage share create

$shareName = "acishare"
az storage share create `
  -n $shareName `
  --account-key $storageAccountKey `
  --account-name $storageAccountName

Create an Application Insights instance

I've blogged before about creating an Application Insights instance with the Azure CLI, but I've since found a slightly less cumbersome way to do it. Here's how to create the App Insights instance.

$appInsightsName = "$prefix$rand"
az resource create `
  -g $resourceGroup -n $appInsightsName `
  --resource-type "Microsoft.Insights/components" `
  --properties '{\"Application_Type\":\"web\"}'

Create a Function App

We also need a Function App to host our Durable Functions workflow, and connect it to the Storage Account and App Insights instance we just created. The az functionapp create command conveniently has flags that lets us connect everything together and with the --consumption-plan-location flag we can indicate that we want to use the consumption App Service Plan without explicitly needing to create one first.

$functionAppName = "$prefix$rand"
az functionapp create `
    -n $functionAppName `
    --storage-account $storageAccountName `
    --consumption-plan-location $location `
    --app-insights $appInsightsName `
    --runtime dotnet `
    -g $resourceGroup

Give the Function App a Managed Identity

We need to give our Function App a "system assigned" managed identity, and we can use az functionapp identity assign to do that, which again is idempotent, returning the existing identity if one has already been created. I also need to get hold of the principal and tenant ids for use later.

az functionapp identity assign -n $functionAppName -g $resourceGroup

$principalId = az functionapp identity show -n $functionAppName `
  -g $resourceGroup --query principalId -o tsv
$tenantId = az functionapp identity show -n $functionAppName `
  -g $resourceGroup --query tenantId -o tsv

Grant Contributor Rights to the Managed Identity

We want our Function App to have permissions to create new ACI container groups, so we're going to put the managed identity we just created into the "contributor" role for a resource group that will hold all the ACI container groups. Let's create the resource group first:

$aciResourceGroup = "DurableFunctionsAciContainers"
az group create -n $aciResourceGroup -l $location

Now we can assign the contributor role to the managed identity but scope it to only have rights to the resource group we just created.

$subscriptionId = az account show --query "id" -o tsv
az role assignment create --role "Contributor" `
    --assignee-object-id $principalId `
    --scope "/subscriptions/$subscriptionId/resourceGroups/$aciResourceGroup"

Summary

We've created most of the Azure resources we need for this demo. The only missing thing is the Event Grid subscription, which is a bit more complex to set up so we'll look at that in part 3

Want to learn more about the Azure CLI? Be sure to check out my Pluralsight course Azure CLI: Getting Started.