Deploying Azure Functions with Application Insights via ARM
Recently I've started playing with Azure Function for real, end-to-end, pushing it to the limits, but that's another conversation. My last mile in mastering them was automatically creating necessary resources in Microsoft Azure via ARM templates. Functions in essence need 4 resources:
Creating AI resource is easy:
{
"apiVersion": "2014-04-01",
"name": "[variables('appInsightsName')]",
"type": "Microsoft.Insights/components",
"location": "[resourceGroup().location]",
"properties": {
"applicationId": "[variables('appInsightsName')]"
}
}
As well as creating a consumption plan in ARM:
{
"comments": "consumption plan for functions",
"type": "Microsoft.Web/serverfarms",
"sku": {
"name": "Y1",
"tier": "Dynamic",
"size": "Y1",
"family": "Y",
"capacity": 0
},
"kind": "functionapp",
"name": "[variables('functionsWebFarmName')]",
"apiVersion": "2016-09-01",
"location": "[resourceGroup().location]",
"scale": null,
"properties": {
"name": "[variables('functionsWebFarmName')]",
"perSiteScaling": false,
"reserved": false,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0
},
"dependsOn": []
}
No surprises in storage account either:
{
"type": "Microsoft.Storage/storageAccounts",
"sku": {
"name": "Standard_LRS",
"tier": "Standard"
},
"kind": "Storage",
"name": "[variables('storageAccountName')]",
"apiVersion": "2018-07-01",
"location": "[resourceGroup().location]",
"properties": {
"networkAcls": {
"bypass": "AzureServices",
"virtualNetworkRules": [],
"ipRules": [],
"defaultAction": "Allow"
},
"supportsHttpsTrafficOnly": false
}
}
The last part, the function app itself, is a bit more tricky, especially if you want to automatically integrate azure functions with application insights. The full template is here, and I'll explain the bits as well.
{
"type": "Microsoft.Web/sites",
"kind": "functionapp",
"name": "[variables('functionsAppName')]",
"apiVersion": "2016-08-01",
"location": "[resourceGroup().location]",
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('functionsWebFarmName'))]",
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
},
{
"name": "AzureWebJobsDashboard",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower(variables('functionsAppName'))]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~2"
},
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(concat('microsoft.insights/components/', variables('appInsightsName'))).InstrumentationKey]"
} ]
}
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('functionsWebFarmName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
]
}
You'll notice that function app ARM resource is not a special resource type after all, it's just a normal web app ("type": "Microsoft.Web/sites"
), so how do you bind AI resource, and storage to it? And this is done via application properties, weirdly enough!
Once deployed, there is no difference between function app created manually via the portal and via arm template.
Thanks for reading. If you would like to follow up with future posts please subscribe to my rss feed and/or follow me on twitter.