Azure ARM Templates Explored - Netwoven
Blog

Azure ARM Templates Explored

By Pratibha Krishnan  |  Published on August 12, 2021

Azure ARM Templates Explored

Deployment of artifacts to Azure portal can be achieved in multiple ways like Azure CI/CD Pipeline, and zip deployment, but when it comes to infrastructure deployment to Azure portal, the Azure Resource Manager (ARM) Templates are the obvious way of doing it, in a simple and repeated manner. These are simple JSON files which can be understood by the ARM APIs.

Why ARM templates?

The main benefit of this approach is that we can deploy several resources together as a single unit. Also, the Azure resources mentioned in the JSON file, if absent in Azure, will be created newly or else if existing, will be updated with the new set of configurations mentioned in the file.

What ARM template cannot do?

Using ARM templates, we can deploy resources to Azure, but it does not deploy code onto those resources. We must use CI/CD pipelines or zip package deployments to do the code deployment.

Template sample

Let us have a look at this simple example of an ARM template which will create a storage account.

We have divided the template into 2 files-

  1. Template.json
  2. Parameters.json

1.Templates.json:

This file mainly consists of 4 main properties-

  • schema– version of the ARM API.
  • parameters– name of the resources
  • variables – direct parameters or calculated variables can be set here
  • resources – Azure resources details which are to be deployed
{
    "$schema": https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#,
    "contentVersion": "1.0.0.0",
    "parameters": {
      "appName": {
        "type": "string",
        "metadata": {
          "description": "The name of the function app that you wish to create."
        }
      },
      "storageAccountType": {
        "type": "string",
        "defaultValue": "Standard_LRS",
        "allowedValues": [
          "Standard_LRS",
          "Standard_GRS",
          "Standard_RAGRS"
        ],
        "metadata": {
          "description": "Storage Account type"
        }
      }
    },
    "variables": {
      "functionAppName": "[parameters('appName')]",
      "hostingPlanName": "[concat(uniquestring(resourceGroup().id),parameters('appName'))]",
      "storageAccountName": "[parameters('storageAccountName')]",
      "storageAccountid": "[concat(resourceGroup().id,'/providers/','Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
       "applicationInsightsName": "[parameters('appName')]",
        "functionWorkerRuntime": "[parameters('runtime')]"
    },
    "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2019-06-01",
      "name": "[variables('storageAccountName')]",
      "location": "[parameters('storagelocation')]",
      "sku": {
        "name": "[parameters('storageAccountType')]"
      },
      "kind": "Storage"
    },
     {
            "type": "Microsoft.Web/serverfarms",
            "apiVersion": "2018-02-01",
            "name": "[parameters('hostingPlanName')]",
            "location": "[parameters('location')]",
            "sku": {
                "name": "EP1",
                "tier": "ElasticPremium",
  • schema: It is used to inform the resource manager regarding which API version of ARM REST API must be used
  • parameters: This section defines the values which must be provided as a configuration value while creating the Azure resources. A sample is given below-
  "parameters": {
      "appName": {
        "type": "string",
        "metadata": {
          "description": "The name of the function app that you wish to create."
        }
      },
      "storageAccountType": {
        "type": "string",
        "defaultValue": "Standard_LRS",
        "allowedValues": [
          "Standard_LRS",
          "Standard_GRS",
          "Standard_RAGRS"
        ],
        "metadata": {
          "description": "Storage Account type"
        }
      },
      "location": {
        "type": "string",
        "defaultValue": "[resourceGroup().location]",
        "metadata": {
          "description": "Location for all resources."
        }
      },

Internally the Azure REST API goes through the parameters and reads storageAccountType, location etc., and goes ahead with the deployment of the storage account resource (refer the resources section of the json above). “type”: “Microsoft.Storage/storageAccounts”,

In case any of the property values are wrong, the deployment gets cancelled.

Here, the location is determined from the function resourceGroup() which returns a list of properties, one of which is the location. Any value which is given within […] is evaluated as code. The full list of template functions can be referred here.

  • variables: This section is optional. If there is any requirement to perform some calculation and deriving the variable based on a property of an Azure resource which will be created as part of the current deployment, we can provide it in this section.
  • resources: In this section, the resources (here in our example, the storage account) which are to be deployed to the Azure, the details of them are provided. In case resource A is dependent on resource B, then we need to provide the details of both the resources.

2.Parameters.json:

Azure ARM Templates Explored

This file is used to provide the user defined variable values to the parameters in the Template.json.

For example, the name of the Function App, name of the storage account and name of the app service etc. In this case, my storage account will be of name storageaccountrg0019e22.I n our Template json file, we have given the storageAccountName as below:

 "storageAccountName":{
     "type": "string",
        "defaultValue": "[concat(uniquestring(resourceGroup().id), 'azfunctions')]",
        "metadata": {
          "description": "existing storage account"
        }
    },

So, in case of not providing a value in parameters.json file, it will evaluate the code from the defaultValue field.

I think I have covered the very basics of the ARM template. Now lets have a look at some specific scenarios.

Scenario 1: Deploy function app to a particular app service plan.
Azure ARM Templates Explored

We need to provide the serverfarms resource (App service plan) and in the resource ‘Microsoft.web/sites, the server farms resource id in the dependsOn property must be mentioned.

Scenario 2: Deploy application insights for a function app.
Azure ARM Templates Explored

In Fig. 2 above, we have provided the app insights resource id in the dependsOn section under the functionapp resource.

 "dependsOn": [
                "[resourceId('Microsoft.Web/serverFarms/', parameters('hostingPlanName'))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
            ],
Scenario 3: Add a condition whether to deploy a resource or not.

This is a recently added property in ARM template. While handling different environments, we might have a requirement to decide whether to deploy a particular resource in that environment. The template doesn’t have to be changed for that, instead a j parameter ca be kept, which can be set to true or false based on the environment.

Azure ARM Templates Explored

Conclusion

Hope this blog article helped in understanding the basic concepts of ARM template, how to design it for different types of resources, how to use it to create dependent resources with dynamic names and how to conditionally deploy same ARM template to multiple environments.

Leave a comment

Your email address will not be published. Required fields are marked *

Unravel The Complex
Stay Connected

Subscribe and receive the latest insights

Netwoven Inc. - Microsoft Solutions Partner

Get involved by tagging Netwoven experiences using our official hashtag #UnravelTheComplex