Deploying Azure Functions with the Azure CLI
In this post we'll explore how we can use the Azure CLI to deploy an Azure Function App running on the "consumption plan" along with all the associated resources such as a Storage Account and an Application Insights instance.
I'll be using PowerShell as my command prompt, but most of these commands translate very straightforwardly to a Bash shell if you prefer.
Step 1 - Create a Resource Group
As always with the Azure CLI, once we've logged in (with az login
) and chosen the correct subscription (with az account set -s "MySub"
), we should create a resource group to hold the various resources we're going to create.
$resourceGroup = "AzureFunctionsDemo"
$location = "westeurope"
az group create -n $resourceGroup -l $location
Step 2 - Create a Storage Account
A number of features of Azure Functions work with a Storage Account, so it's a good idea to create a dedicated Storage Account to partner with a function app. Storage Accounts do require unique names as it will form part of their domain name, so I'm using a random number to help pick a suitable name, before creating the storage account using the standard LRS pricing tier.
$rand = Get-Random -Minimum 10000 -Maximum 99999
$storageAccountName = "funcsdemo$rand"
az storage account create `
-n $storageAccountName `
-l $location `
-g $resourceGroup `
--sku Standard_LRS
Step 3 - Create an Application Insights instance
Azure Functions offers excellent monitoring via Application Insights, so it makes sense to turn this on for all deployments. Unfortunately, the Azure CLI currently does not support creating Application Insights directly, but we can create one with the az resource create
command.
$appInsightsName = "funcsmsi$rand"
az resource create `
-g $resourceGroup -n $appInsightsName `
--resource-type "Microsoft.Insights/components" `
--properties '{\"Application_Type\":\"web\"}'
Step 4 - Create a Function App
Normally at this point we'd need to create an App Service Plan, but when we're using the consumption pricing tier there's a shortcut we can use, which is to set the --consumption-plan-location
parameter when we create the Function App, and we'll automatically get a consumption App Service Plan created for us (with a name like "WestEuropePlan") in our resource group.
We're going to be using V2 of the Azure Functions Runtime, and so I'll specify that I'm using the dotnet
runtime, but you can also set this to node
or java
.
We're also pointing it at the Application Insights instance we just created with the --app-insights
switch.
$functionAppName = "funcs-demo-$rand"
az functionapp create `
-n $functionAppName `
--storage-account $storageAccountName `
--consumption-plan-location $location `
--app-insights $appInsightsName `
--runtime dotnet `
-g $resourceGroup
Step 5 - Deploy our Function App Code
Obviously I'm assuming that we have some functions to deploy to the Function App. If we've created a C# Azure Functions project, we can package it up for release by running a dotnet publish
, zipping up the resulting folder, and using az functionapp deployment source config-zip
to deploy it.
# publish the code
dotnet publish -c Release
$publishFolder = "FunctionsDemo/bin/Release/netcoreapp2.1/publish"
# create the zip
$publishZip = "publish.zip"
if(Test-path $publishZip) {Remove-item $publishZip}
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($publishFolder, $publishZip)
# deploy the zipped package
az functionapp deployment source config-zip `
-g $resourceGroup -n $functionAppName --src $publishZip
Step 6 - Configure Application Settings
Optionally at this point, we may wish to configure some application settings, such as connection strings to other services. These can be configured with the az functionapp config appsettings set
command (although watch out for some nasty escaping gotchas if your setting values contain certain characters).
az functionapp config appsettings set -n $functionAppName -g $resourceGroup `
--settings "MySetting1=Hello" "MySetting2=World"
Step 7 - Configure a Daily Use Quota
Another optional feature you might want to consider setting up is a daily usage quota. One of the great things about the serverless Azure Functions consumption plan is that it offers near-infinite scale to handle huge spikes in load. But that does also leave you open to a "denial of wallet attack" where due to an external DoS attack or a coding mistake, you end up with a huge bill because your function app scaled out to hundreds of instances. The daily quota allows you to set a limit in terms of "Gigabyte seconds" (GB-s), which you might want to set just to be on the safe side when you're experimenting. For a production system, I'd probably rather leave this quota off (or set very high), and configure alerts instead to tell me when my usage is much higher than normal.
Here's the command that sets the daily usage quota to 50000 GB-s:
az functionapp update -g $resourceGroup -n $functionAppName `
--set dailyMemoryTimeQuota=50000
Summary
The Azure CLI provides us with an easy way to deploy and manage our Azure Function apps. Of course, you can also create an ARM template that contains the same resources, and deploy that with the CLI. Personally I find the CLI great when I'm experimenting and prototyping, and when I've got an application that's a bit more stable and ready for production, I might create an ARM template to allow deploying the whole thing in one go.
Comments
Step 6 how do you set connection strings? https://docs.microsoft.com/... there is no az functionapp config connection-string
Tory BerraI just use app settings for connection strings
Mark HeathHI Mark, good approach to deploy azure function. Thank you for your article.
Máximo CaleroI have a question about "az functionapp deployment source config-zip".
Can we avoid to delete the existing azure functions that they are already deployed in the azure function app?
In Azure Functions, the unit of deployment is a whole Function app. So you should put the whole thing in a single source control repository and always deploy it in one go. That way existing functions will remain when you add a new one.
Mark HeathAll right that's great info. I would integrate the Azure CLI into my TFS Release pipeline as a task. But what I want to do is configure the proxies that Azure function apps support. Can i programmatically setup proxies using the Azure CLI? Is it an app setting?
McLovinProxies are configured as a proxies.json file that is part of your function app. So you don't configure them from outside with the Azure CLI. They can however reference application settings if you need them to be customizable dependent on environment (e.g. to point to a different domain).
Mark Heath