Skip to content

Files

Latest commit

 

History

History
963 lines (828 loc) · 41 KB

functions-infrastructure-as-code.md

File metadata and controls

963 lines (828 loc) · 41 KB
title description ms.assetid ms.topic ms.date ms.custom
Automate function app resource deployment to Azure
Learn how to build an Azure Resource Manager template that deploys your function app.
d20743e3-aab6-442c-a836-9bcea09bfd32
conceptual
04/03/2019
fasttrack-edit, devx-track-azurepowershell

Automate resource deployment for your function app in Azure Functions

You can use an Azure Resource Manager template to deploy a function app. This article outlines the required resources and parameters for doing so. You might need to deploy other resources, depending on the triggers and bindings in your function app.

For more information about creating templates, see Authoring Azure Resource Manager templates.

For sample templates, see:

Required resources

An Azure Functions deployment typically consists of these resources:

Resource Requirement Syntax and properties reference
A function app Required Microsoft.Web/sites
An Azure Storage account Required Microsoft.Storage/storageAccounts
An Application Insights component Optional Microsoft.Insights/components
A hosting plan Optional1 Microsoft.Web/serverfarms

1A hosting plan is only required when you choose to run your function app on a Premium plan or on an App Service plan.

Tip

While not required, it is strongly recommended that you configure Application Insights for your app.

Storage account

An Azure storage account is required for a function app. You need a general purpose account that supports blobs, tables, queues, and files. For more information, see Azure Functions storage account requirements.

{
    "type": "Microsoft.Storage/storageAccounts",
    "name": "[variables('storageAccountName')]",
    "apiVersion": "2019-06-01",
    "location": "[resourceGroup().location]",
    "kind": "StorageV2",
    "sku": {
        "name": "[parameters('storageAccountType')]"
    }
}

You must also specify the AzureWebJobsStorage property as an app setting in the site configuration. If the function app doesn't use Application Insights for monitoring, it should also specify AzureWebJobsDashboard as an app setting.

The Azure Functions runtime uses the AzureWebJobsStorage connection string to create internal queues. When Application Insights is not enabled, the runtime uses the AzureWebJobsDashboard connection string to log to Azure Table storage and power the Monitor tab in the portal.

These properties are specified in the appSettings collection in the siteConfig object:

"appSettings": [
    {
        "name": "AzureWebJobsStorage",
        "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2019-06-01').keys[0].value)]"
    },
    {
        "name": "AzureWebJobsDashboard",
        "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2019-06-01').keys[0].value)]"
    }
]

Application Insights

Application Insights is recommended for monitoring your function apps. The Application Insights resource is defined with the type Microsoft.Insights/components and the kind web:

        {
            "apiVersion": "2015-05-01",
            "name": "[variables('appInsightsName')]",
            "type": "Microsoft.Insights/components",
            "kind": "web",
            "location": "[resourceGroup().location]",
            "tags": {
                "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', variables('functionAppName'))]": "Resource"
            },
            "properties": {
                "Application_Type": "web",
                "ApplicationId": "[variables('appInsightsName')]"
            }
        },

In addition, the instrumentation key needs to be provided to the function app using the APPINSIGHTS_INSTRUMENTATIONKEY application setting. This property is specified in the appSettings collection in the siteConfig object:

"appSettings": [
    {
        "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
        "value": "[reference(resourceId('microsoft.insights/components/', variables('appInsightsName')), '2015-05-01').InstrumentationKey]"
    }
]

Hosting plan

The definition of the hosting plan varies, and can be one of the following:

Function app

The function app resource is defined by using a resource of type Microsoft.Web/sites and kind functionapp:

{
    "apiVersion": "2015-08-01",
    "type": "Microsoft.Web/sites",
    "name": "[variables('functionAppName')]",
    "location": "[resourceGroup().location]",
    "kind": "functionapp",
    "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
        "[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]"
    ]
}

Important

If you are explicitly defining a hosting plan, an additional item would be needed in the dependsOn array: "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"

A function app must include these application settings:

Setting name Description Example values
AzureWebJobsStorage A connection string to a storage account that the Functions runtime uses for internal queueing See Storage account
FUNCTIONS_EXTENSION_VERSION The version of the Azure Functions runtime ~4
FUNCTIONS_WORKER_RUNTIME The language stack to be used for functions in this app dotnet, node, java, python, or powershell
WEBSITE_NODE_DEFAULT_VERSION Only needed if using the node language stack on Windows, specifies the version to use ~14

These properties are specified in the appSettings collection in the siteConfig property:

"properties": {
    "siteConfig": {
        "appSettings": [
            {
                "name": "AzureWebJobsStorage",
                "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2019-06-01').keys[0].value)]"
            },
            {
                "name": "FUNCTIONS_WORKER_RUNTIME",
                "value": "node"
            },
            {
                "name": "WEBSITE_NODE_DEFAULT_VERSION",
                "value": "~14"
            },
            {
                "name": "FUNCTIONS_EXTENSION_VERSION",
                "value": "~4"
            }
        ]
    }
}

Deploy on Consumption plan

The Consumption plan automatically allocates compute power when your code is running, scales out as necessary to handle load, and then scales in when code is not running. You don't have to pay for idle VMs, and you don't have to reserve capacity in advance. To learn more, see Azure Functions scale and hosting.

For a sample Azure Resource Manager template, see Function app on Consumption plan.

Create a Consumption plan

A Consumption plan doesn't need to be defined. When not defined, a plan is automatically be created or selected on a per-region basis when you create the function app resource itself.

The Consumption plan is a special type of serverfarm resource. You can specify it by using the Dynamic value for the computeMode and sku properties, as follows:

{
  "type": "Microsoft.Web/serverfarms",
  "apiVersion": "2021-02-01",
  "name": "[variables('hostingPlanName')]",
  "location": "[parameters('location')]",
  "sku": {
    "name": "Y1",
    "tier": "Dynamic",
    "size": "Y1",
    "family": "Y",
    "capacity":0
  },
  "properties": {
    "name":"[variables('hostingPlanName')]",
    "computeMode": "Dynamic"
  }
}

To run your app on Linux, you must also set the property "reserved": true for the serverfarms resource:

{
  "type": "Microsoft.Web/serverfarms",
  "apiVersion": "2021-02-01",
  "name": "[variables('hostingPlanName')]",
  "location": "[parameters('location')]",
  "sku": {
    "name": "Y1",
    "tier": "Dynamic",
    "size": "Y1",
    "family": "Y",
    "capacity":0
  },
  "properties": {
    "name":"[variables('hostingPlanName')]",
    "computeMode": "Dynamic",
    "reserved": true
  }
}

Create a function app

When you explicitly define your Consumption plan, you must set the serverFarmId property on the app so that it points to the resource ID of the plan. Make sure that the function app has a dependsOn setting that also references the plan.

The settings required by a function app running in Consumption plan differ between Windows and Linux.

On Windows, a Consumption plan requires another two other settings in the site configuration: WEBSITE_CONTENTAZUREFILECONNECTIONSTRING and WEBSITE_CONTENTSHARE. This property configures the storage account where the function app code and configuration are stored.

For a sample Azure Resource Manager template, see Azure Function App Hosted on Windows Consumption Plan.

{
  "type": "Microsoft.Web/sites",
  "apiVersion": "2021-02-01",
  "name": "[parameters('functionAppName')]",
  "location": "[parameters('location')]",
  "kind": "functionapp",
  "dependsOn": [
    "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
    "[resourceId('Microsoft.Insights/components', variables('applicationInsightsName'))]"
  ],
  "properties": {
    "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "siteConfig": {
      "appSettings": [
        {
          "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
          "value": "[reference(resourceId('microsoft.insights/components', variables('applicationInsightsName')), '2015-05-01').InstrumentationKey]"
        },
        {
          "name": "AzureWebJobsStorage",
          "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value)]"
        },
        {
          "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
          "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value)]"
        },
        {
          "name": "WEBSITE_CONTENTSHARE",
          "value": "[toLower(parameters('functionAppName'))]"
        },
        {
          "name": "FUNCTIONS_EXTENSION_VERSION",
          "value": "~4"
        },
        {
          "name": "FUNCTIONS_WORKER_RUNTIME",
          "value": "node"
        },
        {
          "name": "WEBSITE_NODE_DEFAULT_VERSION",
          "value": "~14"
        }
      ]
    }
  }
}

Important

Do not need to set the WEBSITE_CONTENTSHARE setting in a deployment slot. This setting is generated for you when the app is created in the deployment slot.

The function app must have set "kind": "functionapp,linux", and it must have set property "reserved": true. Linux apps should also include a linuxFxVersion property under siteConfig. If you are just deploying code, the value for this is determined by your desired runtime stack in the format of runtime|runtimeVersion. For example: python|3.7, node|14 and dotnet|3.1.

The WEBSITE_CONTENTAZUREFILECONNECTIONSTRING and WEBSITE_CONTENTSHARE settings aren't supported on Linux Consumption plan.

For a sample Azure Resource Manager template, see Azure Function App Hosted on Linux Consumption Plan.

{
  "type": "Microsoft.Web/sites",
  "apiVersion": "2021-02-01",
  "name": "[parameters('functionAppName')]",
  "location": "[parameters('location')]",
  "kind": "functionapp,linux",
  "dependsOn": [
    "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
    "[resourceId('Microsoft.Insights/components', variables('applicationInsightsName'))]"
  ],
  "properties": {
    "reserved": true,
    "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "siteConfig": {          
      "linuxFxVersion": "node|14",
      "appSettings": [
        {
          "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
          "value": "[reference(resourceId('Microsoft.Insights/components', parameters('functionAppName')), '2015-05-01').InstrumentationKey]"
        },
        {
          "name": "AzureWebJobsStorage",
          "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value)]"
        },
        {
          "name": "FUNCTIONS_EXTENSION_VERSION",
          "value": "~4"
        },
        {
          "name": "FUNCTIONS_WORKER_RUNTIME",
          "value": "node"
        }
      ]    
    }
  }
}

Deploy on Premium plan

The Premium plan offers the same scaling as the Consumption plan but includes dedicated resources and extra capabilities. To learn more, see Azure Functions Premium Plan.

Create a Premium plan

A Premium plan is a special type of "serverfarm" resource. You can specify it by using either EP1, EP2, or EP3 for the Name property value in the sku as following:

{
  "type": "Microsoft.Web/serverfarms",
  "apiVersion": "2021-02-01",
  "name": "[variables('hostingPlanName')]",
  "location": "[parameters('location')]",
  "sku": {
    "tier": "ElasticPremium",
    "name": "EP1",
    "family": "EP"
  },
  "properties": {
    "name": "[parameters('hostingPlanName')]",
    "maximumElasticWorkerCount": 20
  },
  "kind": "elastic"
}

To run your app on Linux, you must also set property "reserved": true for the serverfarms resource:

{
  "type": "Microsoft.Web/serverfarms",
  "apiVersion": "2021-02-01",
  "name": "[variables('hostingPlanName')]",
  "location": "[parameters('location')]",
  "sku": {
    "tier": "ElasticPremium",
    "name": "EP1",
    "family": "EP"
  },
  "properties": {
    "name": "[parameters('hostingPlanName')]",
    "maximumElasticWorkerCount": 20,
    "reserved": true
  },
  "kind": "elastic"
}

Create a function app

For function app on a Premium plan, you will need to set the serverFarmId property on the app so that it points to the resource ID of the plan. You should ensure that the function app has a dependsOn setting for the plan as well.

A Premium plan requires another settings in the site configuration: WEBSITE_CONTENTAZUREFILECONNECTIONSTRING and WEBSITE_CONTENTSHARE. This property configures the storage account where the function app code and configuration are stored, which are used for dynamic scale.

For a sample Azure Resource Manager template, see Azure Function App Hosted on Premium Plan.

The settings required by a function app running in Premium plan differ between Windows and Linux.

{
  "type": "Microsoft.Web/sites",
  "apiVersion": "2021-02-01",
  "name": "[parameters('functionAppName')]",
  "location": "[parameters('location')]",
  "kind": "functionapp",
  "dependsOn": [
    "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
    "[resourceId('Microsoft.Insights/components', variables('applicationInsightsName'))]"
  ],
  "properties": {
    "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "siteConfig": {
      "appSettings": [
        {
          "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
          "value": "[reference(resourceId('microsoft.insights/components', variables('applicationInsightsName')), '2015-05-01').InstrumentationKey]"
        },
        {
          "name": "AzureWebJobsStorage",
          "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value)]"
        },
        {
          "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
          "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value)]"
        },
        {
          "name": "WEBSITE_CONTENTSHARE",
          "value": "[toLower(parameters('functionAppName'))]"
        },
        {
          "name": "FUNCTIONS_EXTENSION_VERSION",
          "value": "~4"
        },
        {
          "name": "FUNCTIONS_WORKER_RUNTIME",
          "value": "node"
        },
        {
          "name": "WEBSITE_NODE_DEFAULT_VERSION",
          "value": "~14"
        }
      ]
    }
  }
}

Important

You don't need to set the WEBSITE_CONTENTSHARE setting because it's generated for you when the site is first created.

The function app must have set "kind": "functionapp,linux", and it must have set property "reserved": true. Linux apps should also include a linuxFxVersion property under siteConfig. If you are just deploying code, the value for this is determined by your desired runtime stack in the format of runtime|runtimeVersion. For example: python|3.7, node|14 and dotnet|3.1.

{
  "type": "Microsoft.Web/sites",
  "apiVersion": "2021-02-01",
  "name": "[parameters('functionAppName')]",
  "location": "[parameters('location')]",
  "kind": "functionapp,linux",
  "dependsOn": [
    "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
    "[resourceId('Microsoft.Insights/components', variables('applicationInsightsName'))]"
  ],
  "properties": {
    "reserved": true,
    "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "siteConfig": {
      "linuxFxVersion": "node|14",
      "appSettings": [
        {
          "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
          "value": "[reference(resourceId('microsoft.insights/components', variables('applicationInsightsName')), '2015-05-01').InstrumentationKey]"
        },
        {
          "name": "AzureWebJobsStorage",
          "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value)]"
        },
        {
          "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
          "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value)]"
        },
        {
          "name": "WEBSITE_CONTENTSHARE",
          "value": "[toLower(parameters('functionAppName'))]"
        },
        {
          "name": "FUNCTIONS_EXTENSION_VERSION",
          "value": "~4"
        },
        {
          "name": "FUNCTIONS_WORKER_RUNTIME",
          "value": "node"
        }
      ]
    }
  }
}

Deploy on App Service plan

In the App Service plan, your function app runs on dedicated VMs on Basic, Standard, and Premium SKUs, similar to web apps. For details about how the App Service plan works, see the Azure App Service plans in-depth overview.

For a sample Azure Resource Manager template, see Function app on Azure App Service plan.

Create an App Service plan

An App Service plan is defined by a "serverfarm" resource. You can specify the SKU as follows:

{
  "type": "Microsoft.Web/serverfarms",
  "apiVersion": "2021-02-01",
  "name": "[variables('hostingPlanName')]",
  "location": "[parameters('location')]",
  "sku": {
    "tier": "Standard",
    "name": "S1",
    "size": "S1",
    "family": "S",
    "capacity": 1
  }
}

To run your app on Linux, you must also set property "reserved": true for the serverfarms resource:

{
  "type": "Microsoft.Web/serverfarms",
  "apiVersion": "2021-02-01",
  "name": "[variables('hostingPlanName')]",
  "location": "[parameters('location')]",
  "sku": {
    "tier": "Standard",
    "name": "S1",
    "size": "S1",
    "family": "S",
    "capacity": 1
  },
  "properties": {
    "reserved": true
  }
}

Create a function app

For function app on a Dedicated plan, you must set the serverFarmId property on the app so that it points to the resource ID of the plan. Make sure that the function app has a dependsOn setting that also references the plan.

On App Service plan, you should enable the "alwaysOn": true setting under site config so that your function app runs correctly. On an App Service plan, the functions runtime goes idle after a few minutes of inactivity, so only HTTP triggers will "wake up" your functions.

The WEBSITE_CONTENTAZUREFILECONNECTIONSTRING and WEBSITE_CONTENTSHARE settings aren't supported on Dedicated plan.

For a sample Azure Resource Manager template, see Azure Function App Hosted on Dedicated Plan.

The settings required by a function app running in Dedicated plan differ between Windows and Linux.

{
  "type": "Microsoft.Web/sites",
  "apiVersion": "2021-02-01",
  "name": "[parameters('functionAppName')]",
  "location": "[parameters('location')]",
  "kind": "functionapp",
  "dependsOn": [
    "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
    "[resourceId('Microsoft.Insights/components', variables('applicationInsightsName'))]"
  ],
  "properties": {
    "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "siteConfig": {
      "alwaysOn": true,
      "appSettings": [
        {
          "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
          "value": "[reference(resourceId('microsoft.insights/components', variables('applicationInsightsName')), '2015-05-01').InstrumentationKey]"
        },
        {
          "name": "AzureWebJobsStorage",
          "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value)]"
        },
        {
          "name": "FUNCTIONS_EXTENSION_VERSION",
          "value": "~4"
        },
        {
          "name": "FUNCTIONS_WORKER_RUNTIME",
          "value": "node"
        },
        {
          "name": "WEBSITE_NODE_DEFAULT_VERSION",
          "value": "~14"
        }
      ]
    }
  }
}

The function app must have set "kind": "functionapp,linux", and it must have set property "reserved": true. Linux apps should also include a linuxFxVersion property under siteConfig. If you are just deploying code, the value for this is determined by your desired runtime stack in the format of runtime|runtimeVersion. Examples of linuxFxVersion property include: python|3.7, node|14 and dotnet|3.1.

{
  "type": "Microsoft.Web/sites",
  "apiVersion": "2021-02-01",
  "name": "[parameters('functionAppName')]",
  "location": "[parameters('location')]",
  "kind": "functionapp,linux",
  "dependsOn": [
    "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
    "[resourceId('Microsoft.Insights/components', variables('applicationInsightsName'))]"
  ],
  "properties": {
    "reserved": true,
    "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
    "siteConfig": {
      "alwaysOn": true,
      "linuxFxVersion": "node|14",
      "appSettings": [
        {
          "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
          "value": "[reference(resourceId('microsoft.insights/components', variables('applicationInsightsName')), '2015-05-01').InstrumentationKey]"
        },
        {
          "name": "AzureWebJobsStorage",
          "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';EndpointSuffix=', environment().suffixes.storage, ';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value)]"
        },
        {
          "name": "FUNCTIONS_EXTENSION_VERSION",
          "value": "~4"
        },
        {
          "name": "FUNCTIONS_WORKER_RUNTIME",
          "value": "node"
        }
      ]
    }
  }
}

Custom Container Image

If you are deploying a custom container image, you must specify it with linuxFxVersion and include configuration that allows your image to be pulled, as in Web App for Containers. Also, set WEBSITES_ENABLE_APP_SERVICE_STORAGE to false, since your app content is provided in the container itself:

{
    "apiVersion": "2016-03-01",
    "type": "Microsoft.Web/sites",
    "name": "[variables('functionAppName')]",
    "location": "[resourceGroup().location]",
    "kind": "functionapp",
    "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
    ],
    "properties": {
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
        "siteConfig": {
            "appSettings": [
                {
                    "name": "AzureWebJobsStorage",
                    "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2019-06-01').keys[0].value)]"
                },
                {
                    "name": "FUNCTIONS_WORKER_RUNTIME",
                    "value": "node"
                },
                {
                    "name": "WEBSITE_NODE_DEFAULT_VERSION",
                    "value": "~14"
                },
                {
                    "name": "FUNCTIONS_EXTENSION_VERSION",
                    "value": "~3"
                },
                {
                    "name": "DOCKER_REGISTRY_SERVER_URL",
                    "value": "[parameters('dockerRegistryUrl')]"
                },
                {
                    "name": "DOCKER_REGISTRY_SERVER_USERNAME",
                    "value": "[parameters('dockerRegistryUsername')]"
                },
                {
                    "name": "DOCKER_REGISTRY_SERVER_PASSWORD",
                    "value": "[parameters('dockerRegistryPassword')]"
                },
                {
                    "name": "WEBSITES_ENABLE_APP_SERVICE_STORAGE",
                    "value": "false"
                }
            ],
            "linuxFxVersion": "DOCKER|myacr.azurecr.io/myimage:mytag"
        }
    }
}

Deploy to Azure Arc

Azure Functions can be deployed to Azure Arc-enabled Kubernetes. This process largely follows deploying to an App Service plan, with a few differences to note.

To create the app and plan resources, you must have already created an App Service Kubernetes environment for an Azure Arc-enabled Kubernetes cluster. These examples assume you have the resource ID of the custom location and App Service Kubernetes environment that you are deploying to. For most templates, you can supply these as parameters.

{
    "parameters": {
        "kubeEnvironmentId" : {
            "type": "string"
        },
        "customLocationId" : {
            "type": "string"
        }
    }
}

Both sites and plans must reference the custom location through an extendedLocation field. This block sits outside of properties, peer to kind and location:

{
    "extendedLocation": {
        "type": "customlocation",
        "name": "[parameters('customLocationId')]"
    },
}

The plan resource should use the Kubernetes (K1) SKU, and its kind field should be "linux,kubernetes". Within properties, reserved should be "true", and kubeEnvironmentProfile.id should be set to the App Service Kubernetes environment resource ID. An example plan might look like the following:

{
    "type": "Microsoft.Web/serverfarms",
    "name": "[variables('hostingPlanName')]",
    "location": "[parameters('location')]",
    "apiVersion": "2020-12-01",
    "kind": "linux,kubernetes",
    "sku": {
        "name": "K1",
        "tier": "Kubernetes"
    },
    "extendedLocation": {
        "type": "customlocation",
        "name": "[parameters('customLocationId')]"
    },
    "properties": {
        "name": "[variables('hostingPlanName')]",
        "location": "[parameters('location')]",
        "workerSizeId": "0",
        "numberOfWorkers": "1",
        "kubeEnvironmentProfile": {
            "id": "[parameters('kubeEnvironmentId')]"
        },
        "reserved": true
    }
}

The function app resource should have its kind field set to "functionapp,linux,kubernetes" or "functionapp,linux,kubernetes,container" depending on if you intend to deploy via code or container. An example function app might look like the following:

 {
    "apiVersion": "2018-11-01",
    "type": "Microsoft.Web/sites",
    "name": "[variables('appName')]",
    "kind": "kubernetes,functionapp,linux,container",
    "location": "[parameters('location')]",
    "extendedLocation": {
        "type": "customlocation",
        "name": "[parameters('customLocationId')]"
    },
    "dependsOn": [
        "[resourceId('Microsoft.Insights/components', variables('appInsightsName'))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
        "[variables('hostingPlanId')]"
    ],
    "properties": {
        "serverFarmId": "[variables('hostingPlanId')]",
        "siteConfig": {
            "linuxFxVersion": "DOCKER|mcr.microsoft.com/azure-functions/dotnet:3.0-appservice-quickstart",
            "appSettings": [
                {
                    "name": "FUNCTIONS_EXTENSION_VERSION",
                    "value": "~3"
                },
                {
                    "name": "AzureWebJobsStorage",
                    "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2015-05-01-preview').key1)]"

                },
                {
                    "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
                    "value": "[reference(resourceId('microsoft.insights/components/', variables('appInsightsName')), '2015-05-01').InstrumentationKey]"
                }
            ],
            "alwaysOn": true
        }
    }
}

Customizing a deployment

A function app has many child resources that you can use in your deployment, including app settings and source control options. You also might choose to remove the sourcecontrols child resource, and use a different deployment option instead.

Important

To successfully deploy your application by using Azure Resource Manager, it's important to understand how resources are deployed in Azure. In the following example, top-level configurations are applied by using siteConfig. It's important to set these configurations at a top level, because they convey information to the Functions runtime and deployment engine. Top-level information is required before the child sourcecontrols/web resource is applied. Although it's possible to configure these settings in the child-level config/appSettings resource, in some cases your function app must be deployed before config/appSettings is applied. For example, when you are using functions with Logic Apps, your functions are a dependency of another resource.

{
  "apiVersion": "2015-08-01",
  "name": "[parameters('appName')]",
  "type": "Microsoft.Web/sites",
  "kind": "functionapp",
  "location": "[parameters('location')]",
  "dependsOn": [
    "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
    "[resourceId('Microsoft.Web/serverfarms', parameters('appName'))]"
  ],
  "properties": {
     "serverFarmId": "[variables('appServicePlanName')]",
     "siteConfig": {
        "alwaysOn": true,
        "appSettings": [
            {
                "name": "FUNCTIONS_EXTENSION_VERSION",
                "value": "~3"
            },
            {
                "name": "Project",
                "value": "src"
            }
        ]
     }
  },
  "resources": [
     {
        "apiVersion": "2015-08-01",
        "name": "appsettings",
        "type": "config",
        "dependsOn": [
          "[resourceId('Microsoft.Web/Sites', parameters('appName'))]",
          "[resourceId('Microsoft.Web/Sites/sourcecontrols', parameters('appName'), 'web')]",
          "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
        ],
        "properties": {
          "AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2019-06-01').keys[0].value)]",
          "AzureWebJobsDashboard": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(variables('storageAccountid'),'2019-06-01').keys[0].value)]",
          "FUNCTIONS_EXTENSION_VERSION": "~3",
          "FUNCTIONS_WORKER_RUNTIME": "dotnet",
          "Project": "src"
        }
     },
     {
          "apiVersion": "2015-08-01",
          "name": "web",
          "type": "sourcecontrols",
          "dependsOn": [
            "[resourceId('Microsoft.Web/sites/', parameters('appName'))]"
          ],
          "properties": {
            "RepoUrl": "[parameters('sourceCodeRepositoryURL')]",
            "branch": "[parameters('sourceCodeBranch')]",
            "IsManualIntegration": "[parameters('sourceCodeManualIntegration')]"
          }
     }
  ]
}

Tip

This template uses the Project app settings value, which sets the base directory in which the Functions deployment engine (Kudu) looks for deployable code. In our repository, our functions are in a subfolder of the src folder. So, in the preceding example, we set the app settings value to src. If your functions are in the root of your repository, or if you are not deploying from source control, you can remove this app settings value.

Deploy your template

You can use any of the following ways to deploy your template:

Deploy to Azure button

Replace <url-encoded-path-to-azuredeploy-json> with a URL-encoded version of the raw path of your azuredeploy.json file in GitHub.

Here is an example that uses markdown:

[![Deploy to Azure](https://azuredeploy.net/deploybutton.png)](https://portal.azure.com/#create/Microsoft.Template/uri/<url-encoded-path-to-azuredeploy-json>)

Here is an example that uses HTML:

<a href="https://portal.azure.com/#create/Microsoft.Template/uri/<url-encoded-path-to-azuredeploy-json>" target="_blank"><img src="https://azuredeploy.net/deploybutton.png"></a>

Deploy using PowerShell

The following PowerShell commands create a resource group and deploy a template that creates a function app with its required resources. To run locally, you must have Azure PowerShell installed. Run Connect-AzAccount to sign in.

# Register Resource Providers if they're not already registered
Register-AzResourceProvider -ProviderNamespace "microsoft.web"
Register-AzResourceProvider -ProviderNamespace "microsoft.storage"

# Create a resource group for the function app
New-AzResourceGroup -Name "MyResourceGroup" -Location 'West Europe'

# Create the parameters for the file, which for this template is the function app name.
$TemplateParams = @{"appName" = "<function-app-name>"}

# Deploy the template
New-AzResourceGroupDeployment -ResourceGroupName "MyResourceGroup" -TemplateFile template.json -TemplateParameterObject $TemplateParams -Verbose

To test out this deployment, you can use a template like this one that creates a function app on Windows in a Consumption plan. Replace <function-app-name> with a unique name for your function app.

Next steps

Learn more about how to develop and configure Azure Functions.