Deploy Azure Function .NET 7 in the isolated worker model
    • Dark
      Light
    • PDF

    Deploy Azure Function .NET 7 in the isolated worker model

    • Dark
      Light
    • PDF

    Article Summary

    #ServerlessTips - Azure Bicep
    Author: Dave Rendon Microsoft MVP

    This article aims to help you deploy an Azure Function .NET 7 in the isolated worker model in your environment using Infrastructure-as-Code with Azure Bicep.

    Azure Bicep is a domain-specific language (DSL) that uses a declarative syntax to deploy Azure resources.

    The Bicep is an abstraction on top of Azure Resource Manager (ARM) templates to define Azure resources using declarative Infrastructure as Code.

    Prerequisites

    • An Active Azure account: You can create an account for free.
    Azure Bicep is installed on your local machine.
    • Azure PowerShell. See: Install Azure PowerShell.
    • A resource group in your Azure subscription

    Let's get started!

    1. Solution Overview

    We will author a Bicep template that creates an Azure Function .NET 7 in the isolated worker model.

    The solution will include the following files:

    • 📄 main.bicep: This is the Bicep template
    • 📄 azuredeploy.parameters.json: This parameter file contains the values to use for deploying your Bicep template.
    • 📁.zip file: This folder will contain the Azure Function.

    2. Azure Bicep Template — parameters

    Create a new file in your working directory and name it main. Bicep. We will define the following parameters:

    @description('The name of the Azure Function app.')
    param functionAppName string = 'func-${uniqueString(resourceGroup().id)}'
    
    @description('Storage Account type')
    @allowed([
      'Standard_LRS'
      'Standard_GRS'
      'Standard_RAGRS'
    ])
    param storageAccountType string = 'Standard_LRS'
    
    @description('Location for all resources.')
    param location string = resourceGroup().location
    
    @description('Location for Application Insights')
    param appInsightsLocation string = resourceGroup().location
    
    @description('The language worker runtime to load in the function app.')
    @allowed([
      'dotnet'
      'node'
      'python'
      'java'
      'dotnet-isolated'
    ])
    param functionWorkerRuntime string = 'dotnet-isolated'
    
    @description('Specifies the OS used for the Azure Function hosting plan.')
    @allowed([
      'Windows'
      'Linux'
    ])
    param functionPlanOS string = 'Windows'
    
    @description('Specifies the Azure Function hosting plan SKU.')
    @allowed([
      'S1'
      'S2'
      'S3'
    ])
    param functionAppPlanSku string = 'S1'
    
    @description('The zip content url.')
    param packageUri string
    
    @description('Only required for Linux app to represent runtime stack in the format of \'runtime|runtimeVersion\'. For example: \'python|3.9\'')
    param linuxFxVersion string = ''
    
    param netFrameworkVersion string = '7.0'
    
    

    3. Azure Bicep Template — variables

    We will define the following variables:

    var hostingPlanName = functionAppName
    var applicationInsightsName = functionAppName
    var storageAccountName = '${uniqueString(resourceGroup().id)}azfunctions'
    var isReserved = ((functionPlanOS == 'Linux') ? true : false)
    
    

    4. Azure Bicep Template — resources

    We will define the following resources:

    resource storageAccount 'Microsoft.Storage/storageAccounts@2021-02-01' = {
      name: storageAccountName
      location: location
      sku: {
        name: storageAccountType
      }
      kind: 'Storage'
    }
    
    resource hostingPlan 'Microsoft.Web/serverfarms@2021-02-01' = {
      name: hostingPlanName
      location: location
      sku: {
        tier: 'Standard'
    
    name: functionAppPlanSku
        family: 'S'
        capacity: 1
      }
      properties: {
        reserved: isReserved
      }
    }
    
    resource applicationInsights 'microsoft.insights/components@2020-02-02' = {
      name: applicationInsightsName
      location: appInsightsLocation
      tags: {
        'hidden-link:${resourceId('Microsoft.Web/sites', applicationInsightsName)}': 'Resource'
      }
      properties: {
        Application_Type: 'web'
      }
      kind: 'web'
    }
    
    resource functionApp 'Microsoft.Web/sites@2021-02-01' = {
      name: functionAppName
      location: location
      kind: (isReserved ? 'functionapp,linux' : 'functionapp')
      properties: {
        reserved: isReserved
        serverFarmId: hostingPlan.id
        siteConfig: {
          alwaysOn: true
          linuxFxVersion: (isReserved ? linuxFxVersion : json('null'))
          appSettings: [
            {
              name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
              value: reference(applicationInsights.id, '2015-05-01').InstrumentationKey
            }
            {
              name: 'AzureWebJobsStorage'
              value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(storageAccount.id, '2019-06-01').keys[0].value}'
            }
            {
              name: 'FUNCTIONS_EXTENSION_VERSION'
              value: '~4'
    
            }
            {
              name: 'FUNCTIONS_WORKER_RUNTIME'
              value: functionWorkerRuntime
            }          
            {
              name: 'WEBSITE_RUN_FROM_PACKAGE'
              value: '0'
            }
          ]
          netFrameworkVersion:netFrameworkVersion
        }
      }
    }
    
    resource zipDeploy 'Microsoft.Web/sites/extensions@2021-02-01' = {
      parent: functionApp
      name: 'MSDeploy'
      properties: {
        packageUri: packageUri
      }
    }
    
    

    Note we use an extension to deploy the Azure Function code.

    5. Parameters file

    Create a new file named azuredeploy.parameters.json. The code below shows the definition of the parameters file:

    {
        "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
        "contentVersion": "1.0.0.0",
        "parameters": {
            "location": {
                "value": "eastus"
            },
            "functionAppName": {
                "value": "azinsider"
            },
            "packageUri": {
                "value": "https://github.com/daveRendon/azinsider/raw/main/application-workloads/azure-functions-dotnet-worker/azFunctionNetWorker.zip"
            },
            "netFrameworkVersion": {
                "value": "v7.0"
            } 
        }
    
    }
    
    

    6. Azure Bicep Template — Deployment

    We will use the command below to deploy our Bicep template:

    $date = Get-Date -Format "MM-dd-yyyy"
    $rand = Get-Random -Maximum 1000
    $deploymentName = "AzInsiderDeployment-"+"$date"+"-"+"$rand"
    
    New-AzResourceGroupDeployment -Name $deploymentName -ResourceGroupName azinsider_demo -TemplateFile .\main.bicep -TemplateParameterFile .\azuredeploy.parameters.json -c
    
    

    The image below shows the preview of the deployment:
    Picture133

    Then we will execute the deployment. The image below shows the deployment output:
    Picture232

    Verify also the configuration using the Azure Portal as shown below:
    Picture327

    Then, verify the configuration of the Azure Function in the Azure Portal:
    Picture422

    You can find the code of this solution in the following URL; feel free to contribute!

    https://github.com/daveRendon/azinsider/tree/main/application-workloads/azure-functions-dotnet-worker


    Was this article helpful?