Skip to content

erwinkramer/azure-functions-flex-consumption-migration-guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 

Repository files navigation

Azure Functions Flex Consumption - Migration Guide

CC BY-NC-SA 4.0 GitHub commit activity

A guide to migrate to Azure Functions Flex Consumption plan hosting. Contains specific steps for secure, identity based, C# Functions with VNet integration. With continuous deployment via Azure DevOps.

A fully working Bicep sample is available at Azure Functions Flex Consumption Samples.

Generic settings

Many app settings and properties are moved to a different place in an Flex Consumption plan or simply depreciated entirely, for a complete overview, see Flex Consumption plan deprecations.

A big change is the introduction of the properties.functionAppConfig element in Microsoft.Web/sites, available from versions @2023-12-01 and up.

Of course, the most obvious change is the SKU, on Microsoft.Web/serverfarms@2023-12-01, the kind and sku will look like this:

kind: 'functionapp'
sku: {
    tier: 'FlexConsumption'
    name: 'FC1'
}

If coming from a premium plan, make sure to remove most properties from the serverfarms resource, you will end up with just this simple configuration:

properties: { 
    reserved: true
}

Scaling settings

Scaling now is set on the sites resource, instead of the serverfarms resource, it might look like this inside the properties element:

@maxValue(1000)
param maximumInstanceCount int = 100
@allowed([2048, 4096])
param instanceMemoryMB int = 2048

...

functionAppConfig: {
    scaleAndConcurrency: {
        maximumInstanceCount: maximumInstanceCount
        instanceMemoryMB: instanceMemoryMB
    }
}

C# app properties

To specify C# properties;

  • change app setting FUNCTIONS_WORKER_RUNTIME_VERSION=8.0 to resource setting properties.functionAppConfig.runtime.version=8.0.
  • change app setting FUNCTIONS_WORKER_RUNTIME=dotnet-isolated to resource setting properties.functionAppConfig.runtime.name=dotnet-isolated.
  • delete properties.siteConfig.netFrameworkVersion=v8.0
  • if on an old linux plan; delete properties.siteConfig.LinuxFxVersion=DOTNET-ISOLATED|8.0.
  • if on an old windows plan; delete properties.siteConfig.windowsFxVersion=DOTNET-ISOLATED|8.0.

Identity-based backend connections

If coming from an identity-based connection for AzureWebJobsStorage (host), this still works with identities, but requires a different setup:

  • delete app setting AzureWebJobsStorage__blobServiceUri
  • delete app setting AzureWebJobsStorage__queueServiceUri
  • delete app setting AzureWebJobsStorage__tableServiceUri
  • add app setting AzureWebJobsStorage__accountName and point to the storage account name of the backend storage.
  • add authentication.type property on the deployment element, as specified under Deployment, this will make sure the connection to the backend uses a managed identity.

Network behavior

If using VNet integration:

  • remove the WEBSITE_VNET_ROUTE_ALL app setting
  • remove properties.vnetImagePullEnabled
  • remove properties.vnetRouteAllEnabled
  • remove properties.vnetContentShareEnabled
  • remove properties.vnetBackupRestoreEnabled
  • remove the Microsoft.Web/sites/networkConfig resource entirely, it might have looked like this:
resource networkConfig 'Microsoft.Web/sites/networkConfig@2023-01-01' = {
  parent: functionApp
  name: 'virtualNetwork'
  properties: {
    subnetResourceId: appServicePlanSubnetId
    swiftSupported: true
  }
}
  • add properties.virtualNetworkSubnetId=appServicePlanSubnetId to Microsoft.Web/sites
  • change delegation of the subnet, so for the resource Microsoft.Network/virtualNetworks/subnets; properties.delegations.properties.serviceName used to be Microsoft.Web/serverFarms, now it is Microsoft.App/environments.

VNet-based backend connections

If coming from a secure VNet integrated connection for AzureWebJobsStorage (host), this still works with VNet integration, but requires a different setup:

  • delete app setting WEBSITE_CONTENTOVERVNET

That's all there is to it! You can isolate your storage account completely with private endpoints, and block all public access.

Deployment

To deploy a C# app, or any other language app, it's completely different to what you are used to, zip deploy isn't what it used to be anymore. You will still deploy to the Function App, but without building and zipping your project fist. The app will manage all deployments in a storage account using a container. In a Premium plan, managing deployments used to be within a file share:

  • delete app setting WEBSITE_RUN_FROM_PACKAGE.
  • if coming from a premium plan: delete app setting WEBSITE_CONTENTSHARE.
  • add a deployment element to your properties.functionAppConfig element, it might look like this:
deployment: {
    storage: {
        type: 'blobContainer'
        value: '${storage.properties.primaryEndpoints.blob}${deploymentStorageContainerName}'
        authentication: {
            type: 'SystemAssignedIdentity'
        }
    }
}

This setup, with authentication.type=SystemAssignedIdentity, assumes the Function App has data permissions on the deploymentStorageContainerName.

  • add a deployment container to your backend storage account, and use as specified in the deploymentStorageContainerName variable, it might look like this on a Microsoft.Storage/storageAccounts/blobServices@2023-04-01 resource:
resource container 'containers' = [
    for container in containers: {
        name: container.name
        properties: {
            publicAccess: 'None'
        }
    }
]

C# Deployment

To deploy your actual code, inside an Azure DevOps environment, build and deploy steps differ greatly.

Build steps

  • optionally: remove the DotNetCoreCLI build task, i would recommend still building your project inside your CI/CD, to keep sanity checks and tests in place.
  • remove the DotNetCoreCLI publish task, it might have looked like this:
- task: DotNetCoreCLI@2
  displayName: "dotnet publish"
  inputs:
    command: publish
    ...
  • remove any zip task you might had, your build artifact should be made like this:
- task: CopyFiles@2
  displayName: copy to staging dir
  inputs:
    sourceFolder: "$(System.DefaultWorkingDirectory)/${{ parameters.projectFolderName }}"
    contents: "*"
    targetFolder: "$(Build.ArtifactStagingDirectory)/dotnet"
    overWrite: true # optional

Deploy steps

Deployment makes use of the Azure Functions Core Tools instead of the Azure Functions Deploy task.

  • remove the AzureFunctionApp@2 task.
  • add deploy tasks that looks like this:
- task: FuncToolsInstaller@0
  inputs:
    version: 'latest'

- task: AzurePowerShell@5
  displayName: Azure Function App Deploy
  inputs:
    azureSubscription: SC-Sandbox
    azurePowerShellVersion: LatestVersion
    ScriptType: "InlineScript"
    Inline: |
    cd "$(Pipeline.Workspace)/drop/dotnet"
    func azure functionapp publish "func-hello-001" --dotnet-isolated

License

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

CC BY-NC-SA 4.0

About

This guide outlines how to migrate to Azure Functions Flex Consumption plan hosting

Topics

Resources

License

Stars

Watchers

Forks