DEV Community

Cover image for Deploy Premium Linux  Function App with ARM template
Tsuyoshi Ushio
Tsuyoshi Ushio

Posted on

Deploy Premium Linux Function App with ARM template

I wanted to automate the deployment of the Premium Linux and AppService plan for Java application. I'd like to share what I learned. This repo is the repo I leave the samples.

Premimu Linux

There is an official document however, I can't find Premium Linux configuration.

Serverfarms

targetWorkerCount and targetWorkerSizeId are something we can't find on the official documentation. That is int properties. Important point is, kind as elastic and reserved as true.

        {
            "apiVersion": "2018-02-01",
            "name": "[parameters('hostingPlanName')]",
            "type": "Microsoft.Web/serverfarms",
            "location": "[parameters('location')]",
            "kind": "elastic",
            "tags": {},
            "dependsOn": [],
            "properties": {
                "targetWorkerCount": "[parameters('targetWorkerCount')]",
                "targetWorkerSizeId": "[parameters('targetWorkerSizeId')]",
                "reserved": true,
                "maximumElasticWorkerCount": "[parameters('maximumElasticWorkerCount')]"
            },
            "sku": {
                "tier": "[parameters('sku')]",
                "name": "[parameters('skuCode')]"
            }
        },

We have a several resouces, however, the reference looks the latest.

targetWorkerSizeId

Probably, these meaning.

Small = 0,
Medium = 1,
Large = 2,
D1 = 3,
D2 = 4,
D3 = 5,
SmallV3 = 6,
MediumV3 = 7,
LargeV3 = 8,
NestedSmall = 9,

Web/sites

kind as functionapp,linux. For specifying languages, I set FUNCTIONS_WORKER_RUNTIME as java, linuxFxVersion as Java|8. The linuxFxVersion requires only on linux. It represents docker images that you found azure functions docker. You can find some possible value in here. It can be specify the generic one like Java|8 but also you can specify specific docker image version like DOCKER|mcr.microsoft.com/azure-functions/python:2.0.13351-python3.6-appservice. You can find it on azure functions docker repo.

For the premium and consumption plan, we need WEBSITE_CONTENTAZUREFILECONNECTIONSTRING and WEBSITE_CONTENTSHARE.

        {
            "apiVersion": "2018-11-01",
            "name": "[parameters('name')]",
            "type": "Microsoft.Web/sites",
            "kind": "functionapp,linux",
            "location": "[parameters('location')]",
            "tags": {},
            "dependsOn": [
                "[resourceId('microsoft.insights/components', parameters('appInsightsName'))]",
                "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
            ],
            "properties": {
                "name": "[parameters('name')]",
                "siteConfig": {
                    "appSettings": [
                        {
                            "name": "FUNCTIONS_EXTENSION_VERSION",
                            "value": "~3"
                        },
                        {
                            "name": "FUNCTIONS_WORKER_RUNTIME",
                            "value": "[parameters('functionWorkerRuntime')]"
                        },
                        {
                            "name": "APPINSIGHTS_INSTRUMENTATIONKEY",
                            "value": "[reference(concat('microsoft.insights/components/', parameters('appInsightsName')), '2015-05-01').InstrumentationKey]"
                        },
                        {
                            "name": "APPLICATIONINSIGHTS_CONNECTION_STRING",
                            "value": "[reference(concat('microsoft.insights/components/', parameters('appInsightsName')), '2015-05-01').ConnectionString]"
                        },
                        {
                            "name": "AzureWebJobsStorage",
                            "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
                        },
                        {
                            "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
                            "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
                        },
                        {
                            "name": "WEBSITE_CONTENTSHARE",
                            "value": "[concat(toLower(parameters('name')), '94ed')]"
                        }
                    ],
                    "linuxFxVersion": "[parameters('linuxFxVersion')]"
                },
                "serverFarmId": "[concat('/subscriptions/', parameters('subscriptionId'),'/resourcegroups/', parameters('serverFarmResourceGroup'), '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
                "clientAffinityEnabled": false
            }
        },

One of the question is Why do I need both APPINSIGHTS_INSTRUMENTATIONKEY and APPLICATIONINSIGHTS_CONNECTION_STRING in my Azure Function configuration?. You can find the answer on the link.

What did I google it?

Deployed not supported region

{
    "Code": "BadRequest",
    "Message": "Requested features are not supported in region. Please try another region.",
    "Target": null,
    "Details": [
        {
            "Message": "Requested features are not supported in region. Please try another region."
        },
        {
            "Code": "BadRequest"
        },
        {
            "ErrorEntity": {
                "ExtendedCode": "59911",
                "MessageTemplate": "Requested features are not supported in region. Please try another region.",
                "Parameters": [],
                "Code": "BadRequest",
                "Message": "Requested features are not supported in region. Please try another region."
            }
        }
    ],
    "Innererror": null
}

These command shows you the location that available to you for each resources.

az provider show --namespace Microsoft.Web | jq ".resourceTypes[] | select(.resourceType == \"serverFarms\") | .locations" 

The serverFarm property has an incorrect value for App Service Plan

The error message was very confusing. However, it was an issue of this part. It was not the serverfarms resource. I forget to add value to serverFarmResourceGroup.

"serverFarmId": "[concat('/subscriptions/', parameters('subscriptionId'),'/resourcegroups/', parameters('serverFarmResourceGroup'), '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",

The way I identify issue is portal. Even if I deploy from my local machine, if you go to portal and see the deployment history, then you can find which resources causes an issue.

Alt Text

Deployment failed. Correlation ID: 95b838bf-3c0d-45f0-9457-0b10c916109f. {
  "Code": "BadRequest",
  "Message": "The serverFarm property has an incorrect value for App Service Plan. Valid values are a plan name as string or of format  subscriptions/subscriptionId/resourceGroups/resourceGroupName/providers/Microsoft.web/serverfarms/planName where the subscription is the same as the site's subscription.",
  "Target": null,

serverframs can not found

I encounter the issue. The reason was, the template that I've got from donwload automated script was wrong. It has a section like this.

            "dependsOn": [
                "microsoft.insights/components/tsushijava8trace",
                "[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
                "[concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]"
            ],

dependsOn section requires resourceId function.

            "dependsOn": [
                "[resourceId('microsoft.insights/components', parameters('appInsightsName'))]",
                "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
            ],

Lessons Learned

This time, I have no sample, so I can't identify how we can deploy Premium Functions.

  1. Deploy Premium Linux functions from portal and download automated script
  2. Deploy Premium Linux functions from portal and see Export template
  3. Offical Doc Automate resource deployment for your function app in Azure Functions
  4. References Microsoft.Web serverfarms template reference, Microsoft.Web sites/config template reference

When I look back, the best way might be...

  1. Learn the basic with the official document.
  2. Deploy Premimu Linux functions from portal and see Export template
  3. Understand the meaning of the parameters with Reference

The download automated script is something I used to use frequently, however, this time, the template does not work. Understand the proper format and check with the Export template is the truth.

I hope this helps.

Top comments (0)