Mastering Azure Serverless Computing
上QQ阅读APP看书,第一时间看更新

Creating the Azure function app

The first step you have to take when you deploy your Azure Function is creating the host environment that keeps your function alive. This environment is a function app.

You can imagine the function app as the serverless view of an App Service: it hosts your code and gives you a bunch of features that you can use to deploy, monitor, and configure your Azure Function.

When you decide to create a function app, you need the following resources:

  • The function app itself.
  • A storage account that stores your code. This is mandatory because your code needs a place to be saved.
  • An Application Insight component. This isn't mandatory; you will need it only if you want to monitor your code. We will talk more deeply about monitoring in one of the following chapters.
  • A hosting plan. This is mandatory when you choose to host your function in a Premium plan or in an App Service plan, but you don't need it if you are creating a function app that runs in the Consumption plan. We will talk more deeply about hosting a plan in one of the following chapters.

Furthermore, in order to maintain all the resources and ensure that they are logically connected, it is appropriate to create a resource group that contains them.

The best way you have to create a function app in Azure is by using an ARM template. An ARM template is a JSON file that contains the definition of your infrastructure in Azure. Using the ARM templates, you can deploy your infrastructure repeatedly and create a test environment on the fly.

For more information about ARM templates, their structure, and their syntax, read the article at https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-authoring-templates.

When using an ARM template, you can think of your infrastructure definition like a programming language's snippet of code. You can version it, store it in a source-control management system (for example, Git), validate it before executing it, and evolve it during the project life cycle.

Generally, when you use an ARM template, you create a template file and a parameter file, and then you can push them on Azure using a PowerShell command.

The first resource you need in your ARM template is the storage account that hosts your function code. So, in the resources section of the JSON template, you can put the following:

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

As you can see in the previous snippet, variables and parameters appear in the storage definition. Variables are placeholders that you can use inside your ARM template to store information for use within resource definition properties (they are similar to the variables in a programming language). Parameters are pieces of information that the ARM template receives from the outside.

The ARM template has special sections to define the parameters and variables:

{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [ "Standard_LRS", "Standard_GRS", "Standard_RAGRS" ],
"metadata": {
"description": "Storage Account type"
}
},
...
},
"variables": {
....
"storageAccountName": "[concat(parameters('appName'), 'storage')]",
...
},
"resources": [
...
],
}

Every parameter has a type, can have a default value, and can support a set of values.

A variable can be calculated using parameters or other variables (for example, the concat() function in the storageAccountName variable).

The second resource that you need to deploy an Azure Function is the function app, and if you want, you can choose to use a Consumption plan, an App Service plan, or a Premium plan.

We will talk more deeply about the types of plan later in this book, but whether you decide to use the Consumption plan, App Service plan, or Premium plan, you need to configure it, and you can do this with the following snippets.

When you want to run your Azure Functions in a Consumption plan, you simply have to choose it. The Consumption plan, in fact, doesn't need to be defined in terms of server size or operating system type, as shown in the following code:

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

When you want to use an App Service plan to host your functions, you have to define some server farm properties, as follows:

{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2015-04-01",
"name": "[variables('hostingPlanName')]",
"location": "[parameters('location')]",
"properties": {
"name": "[variables('hostingPlanName')]",
"sku": "[parameters('sku')]",
"workerSize": "[parameters('workerSize')]",
"hostingEnvironment": "",
"numberOfWorkers": 1
}
}

The properties can have the following values:

  • The workerSize property defines the size of the hosting plan, and it can be 0, 1, or 2 (small, medium, or large).
  •  The sku property defines the pricing tier of the plan, and you can choose between Free, Shared, Basic, and Standard.

As you saw in the previous chapters, you can host your functions in a Linux environment. If you want to do this, you have to set "kind"="Linux" in the farm definition. 

Finally, if you choose the Premium plan to host your function, the sku properties may be one of the following values: EP1, EP2, or EP3:

{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2015-04-01",
"name": "[variables('hostingPlanName')]",
"location": "[parameters('location')]",
"properties": {
"name": "[variables('hostingPlanName')]",
"sku": "EP1"
}
}

Once you define the host for your function, you need to define the function app with a template that looks like the following:

{
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
"name": "[variables('functionAppName')]",
"location": "[parameters('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": {
...
}
}
}

As you can see, the function app is a Microsoft.Web/sites resource of the "functionapp" type (function app is a special type of website hosting) and it depends on (as shown by the dependsOn property) the storage account and the server farm. Thanks to the dependsOn property, you can be sure that the function app resource will not be deployed if the other two resources are not present.

In the function app template, you can also set the configuration using appSettings (in particular, the siteConfig section). For example, the next snippet shows how to set the function's runtime version:

"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]",
"siteConfig": {
"appSettings": [
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~2"
},
....
]
}
}

When you complete your ARM template, you can deploy it using the following PowerShell script:

$resourceGroupName = Read-Host -Prompt "Enter the Resource Group name"
$location = Read-Host -Prompt "Enter the location (i.e. centralus)"
$appName = Read-Host -Prompt "Enter the app name "

Connect-AzAccount

if ((Get-AzResourceGroup -Name $resourceGroupName -Location $location -ErrorAction SilentlyContinue) -eq $null) {
New-AzResourceGroup -Name $resourceGroupName -Location $location -Force -ErrorAction Stop
}

New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName `
-TemplateFile C:\MasteringServerless\ConsumptionPlanDeploy.json `
-Force `
-appName $appName `
-ErrorVariable ErrorMessages

if ($ErrorMessages) {
Write-Output '', 'Template deployment returned the following errors:', @(@($ErrorMessages) | ForEach-Object { $_.Exception.Message.TrimEnd("`r`n") })
}

The previous script creates the resource group (if it doesn't exist), then calls the New-AzResourceGroupDeployment cmdlet to create a new deployment in the resource group and starts it.

The following screenshot shows the PowerShell output:

If you use Visual Studio or Visual Studio Code, there is a special type of project available that allows you to manage and create ARM templates. In Visual Studio, this project is called the Azure Resource Group project and you can create it in the same way you create a standard code project:

When you choose this kind of project, you can start to write your ARM template from scratch by selecting one of the templates offered by Visual Studio or choosing one of the open-source templates created by the community:

In the next section, we will be looking at deploying the app into the cloud.