Introduction to Azure ARM Template

 ARM Template

ARM  stands for Azure Resource Manager. We use ARM templates to deploy resources to Azure. We can automate deployments and use the infrastructure as code. In code, we define the infrastructure that needs to be deployed. The infrastructure code becomes part of our project. Like the application code, we store the infrastructure code in a repository and version it. We use this approach because anyone on the team can run the code and deploy similar environments.

To implement infrastructure as code for Azure solutions, we use Azure Resource Manager (ARM) templates. The template is a JSON file that defines the infrastructure and configuration. In the template, we specify the resources to deploy and the properties for those resources. The template uses declarative syntax, which lets you deploy without having to write the sequence of programming commands to create it.

Template file

The template has the following sections,

  • Parameters- We can provide values during deployment that allow the same template to be used for different Environments.
  • Variables- These values can be reused in templated and can be formed from parameter values.
  • User-defined functions- Create functions that simplify our template.
  • Resources- Resources that are to be deployed
  • Outputs- Return values from the deployed resources.

Below is a sample template file that creates a Storage Account, Azure App Service Plan & Web App.

{  
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",  
  "contentVersion": "1.0.0.0",  
  "parameters":{  
    "storagePrefixForArm":{  
        "type": "string",  
        "minLength": 3,  
        "maxLength": 24  
    },  
      "appServicePlanName": {  
          "type": "string",  
          "defaultValue": "exampleplan1"  
      },  
      "location":{  
        "type": "string",  
        "defaultValue": "[resourceGroup().location]"  
      },  
       "webAppName": {  
           "type": "string",  
           "metadata": {  
               "description": "web app name and app service plan "  
           },  
           "minLength": 2  
       },  
       "linuxFxVersion": {  
           "type": "string",  
           "defaultValue": "php|7.0",  
           "metadata": {  
               "description": "Current Web App"  
           }  
       },  
    "storageSKU":{  
        "type":"string",  
        "defaultValue": "Standard_LRS",  
        "allowedValues": [  
              "Standard_LRS",  
              "Standard_GRS",  
              "Standard_RAGRS",  
              "Standard_ZRS",  
              "Premium_LRS",  
              "Premium_ZRS",  
              "Standard_GZRS",  
              "Standard_RAGZRS"  
        ]  
    },  
    "resourceTags": {  
        "type": "object",  
        "defaultValue": {  
            "Environment": "Dev",  
            "Project": "ARMTemp"  
        }  
    }      
  },  
  "variables":{  
      "uniqueStorageName":"[concat(parameters('storagePrefixForArm'),uniqueString(resourceGroup().id))]",  
       "webAppPortalName": "[concat(parameters('webAppName'), uniqueString(resourceGroup().id))]"  
  
  },  
  "resources": [{  
      "type": "Microsoft.Storage/storageAccounts",  
      "apiVersion": "2019-04-01",  
      "name": "[variables('uniqueStorageName')]",  
      "location": "[parameters('location')]",  
      "tags": "[parameters('resourceTags')]",  
      "sku": {  
          "name": "[parameters('storageSKU')]"  
      },  
      "kind": "StorageV2",  
      "properties": {  
          "supportsHttpsTrafficOnly": true  
      }  
  }, {  
      "type": "Microsoft.Web/serverfarms",  
      "apiVersion": "2016-09-01",  
      "name": "[parameters('appServicePlanName')]",  
      "location": "[parameters('location')]",  
      "sku": {  
          "name": "B1",  
          "tier": "Basic",  
          "size": "B1",  
          "family": "B",  
          "capacity": 1  
      },  
      "kind": "linux",  
      "properties": {  
          "perSiteScaling": false,  
          "reserved": true,  
          "targetWorkerCount": 0,  
          "targetWorkerSizeId": 0  
      }  
  }, {  
      "type": "Microsoft.Web/sites",  
      "apiVersion": "2018-11-01",  
      "name": "[variables('webAppPortalName')]",  
      "location": "[parameters('location')]",  
      "dependsOn": [  
          "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]"  
      ],  
      "kind": "app",  
      "properties": {  
          "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]",  
          "siteConfig": {  
              "linuxFxVersion": "[parameters('linuxFxVersion')]"  
          }  
      }  
  }],  
  "outputs": {  
      "storageEndpoint": {  
          "type": "object",  
          "value": "[reference(variables('uniqueStorageName')).primaryEndpoints]"  
      }  
  }  
}  

Let's Deep dive into the template file for each section.

$schema

Specifies the location of the JSON schema file. The schema file describes the properties that are available within a template.

contentVersion

Specifies the version of the template you are creating, and value is used for versioning for the significant changes of your template.

"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",  
"contentVersion": "1.0.0.0",  

Resources

This section specifies the resources which you are deploying. In the below example, we are creating an Azure Storage account using ARM Template. 

  • type- refers to the Azure Resource we are creating, which in the example below is "Microsoft.Storage/storageAccounts" 
  • apiVersion- refers to the REST API version we use to create the Azure resource using the ARM Template, and apiVersion is specific to the Azure resource we are creating. 
  • location- location refers to the location we want to create the Azure resource. (Central US or Central India) 

The other properties are specific to the resource which we are creating. If we consider Azure Storage Account, we have kind and properties.

"resources": [{    
     "type": "Microsoft.Storage/storageAccounts",    
     "apiVersion": "2019-04-01",    
     "name": "[variables('uniqueStorageName')]",    
     "location": "[parameters('location')]",    
     "tags": "[parameters('resourceTags')]",    
     "sku": {    
         "name": "[parameters('storageSKU')]"    
     },    
     "kind": "StorageV2",    
     "properties": {    
         "supportsHttpsTrafficOnly": true    
     }    
 }  

Parameters

These are the i/p values that can be provided while executing the arm template. Parameters help us provide values at runtime and help us reuse the arm template for many purposes.

If we consider storagePrefix, it has type(dataType), minLength, and maxLength properties. Similarly, we can use the defaultValue property for assigning the default value when no value is not supplied at run time. Below are the parameters which are defined in the arm template. 

We can also use some predefined template functions in the parameters. For Example, if we consider the location parameter, it has defaultValue, which is [resourceGroup().location], which means we have to create the storage account in the same location as the Azure resource group. We call these functions template functions.

We also have the allowedValues property, which provides only the values from the set of values. At runtime, if a value is provided which is not from allowedValues, an exception will raise.

 "parameters":{  
    "storagePrefixForARM":{  
        "type": "string",  
        "minLength": 3,  
        "maxLength": 24  
    },  
      "storageSKU":{  
        "type":"string",  
        "defaultValue": "Standard_LRS",  
        "allowedValues": [  
              "Standard_LRS",  
              "Standard_GRS",  
              "Standard_RAGRS",  
              "Standard_ZRS",  
              "Premium_LRS",  
              "Premium_ZRS",  
              "Standard_GZRS",  
              "Standard_RAGZRS"  
        ]  
    },  
      "location":{  
        "type": "string",  
        "defaultValue": "[resourceGroup().location]"  
      }  
}  

 Now let's see how to retrieve values from the parameters and use them in the resources objects. We can use the parameters function by sending the parameter name to access the parameter value.

"location": "[parameters('location')]",  

Variables

We can use variables to reuse the values within the ARM Template. We define the Variables section below. We add the variables section by defining the variable and value. Considering the example below, we are creating a uniqueStorageName by accessing the parameter storagePrefix value and uniqueString function, which generates a 13-character unique string from the resource group id we are using.

"variables":{  
     "uniqueStorageName":"[concat(parameters('storagePrefix'),uniqueString(resourceGroup().id))]",  
      "webAppPortalName": "[concat(parameters('webAppName'), uniqueString(resourceGroup().id))]"  
  
 }  

We can access the variables similarly to the parameters.

"name": "[variables('uniqueStorageName')]"  

 Outputs

Outputs are the values of the deployed resource. We use outputs when you need a value from a deployed resource.

In the below example, a return type is an object, and we are using a template function reference to get the runtime state of the deployed Azure resource by passing the name of the deployed resource. In the below example, we are getting primaryEndpoints of the storage account.

"outputs": {  
      "storageEndpoint": {  
          "type": "object",  
          "value": "[reference(variables('uniqueStorageName')).primaryEndpoints]"  
      }  
  }  

Tags

We can add the tags to the Azure resource we are creating by defining the tags in the parameters section and then using the parameter value in the resource template. 

"resourceTags": {  
       "type": "object",  
       "defaultValue": {  
           "Environment": "Dev",  
           "Project": "Tutorial"  
       }  

Defining tags property for the resource.

"tags": "[parameters('resourceTags')]",  

We can deploy the arm template from the Azure CLI cmd prompt. Upload the arm.json file to the Azure cloud shell and execute the below command for execution.

 Azure ARM Template

 If we check the Azure resource group and deployment tab, we can see the arm template with the template name.

 Azure ARM Template

Summary

The declarative syntax of ARM templates includes sections describing outputs, user-defined functions, parameter values, and resources to deploy. Infrastructure as code for Azure solutions can be implemented with the help of the template. The material includes a sample template file for setting up a storage account, an app service plan for Azure, and a web app.

That's it from this article; please provide your feedback.