Understanding an ARM Template: A Beginner's Guide

A guide about ARM Template structure and options available!

Anders Moth Falk

Understanding an ARM Template: A Beginner's Guide

An ARM (Azure Resource Manager) template is a JSON file that defines the infrastructure and configuration needed to deploy resources in Microsoft Azure. These templates allow you to automate resource deployment, making infrastructure-as-code a key practice in DevOps workflows.

In this post, we will walk through a simple ARM template and explain what each section does. Here’s the basic template:

{
	"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
	"contentVersion": "1.0.0.0",
	"parameters": {},
	"functions": [],
	"variables": {},
	"resources": [],
	"outputs": {}
}

Let’s break it down line by line and explore the options you have when customizing your templates.

$Schema

"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
The $schema property defines the location of the JSON schema that describes the structure of an ARM template. This schema helps validate the syntax of your template.
What it does: Ensures the structure of your template is correct.
Options:
  • Versioning: The schema URL can change depending on the version of the ARM schema. In this example, we are using version 2019-04-01. You can update this to a newer version by adjusting the date in the URL, such as 2021-04-01, to take advantage of new features in later versions.
  • Template Types: The schema URL can also vary depending on the type of deployment you're working with. Here are some examples:
    • For a resource group deployment:
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"
    • For a subscription-level deployment:
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/subscriptionDeploymentTemplate.json#"
    • For a management group deployment:
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/managementGroupDeploymentTemplate.json#"
    • For a tenant-level deployment:
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/tenantDeploymentTemplate.json#"
  • By choosing the appropriate schema, you ensure your template targets the correct scope (resource group, subscription, management group, or tenant).

contentVersion

"contentVersion": "1.0.0.0",
The contentVersion is a user-defined version number for the template.
This can be helpful when you update your templates and want to track versions.
What it does: Specifies the version of the template you are working with.
Options: You can change the version as needed, using a versioning scheme such as 1.0.0.1, 2.0.0.0, etc.

parameters

"parameters": {},
The parameters section allows you to define dynamic input values that can be passed into the template during deployment. This helps make the template reusable.
What it does: Defines user-provided inputs such as resource names, sizes, and locations.
Options:
  • You can define various types of parameters, including strings, integers, booleans, and secure strings.
  • Example:

  • "parameters": {
    	"storageAccountName": {
    		"type": "string",
    		"defaultValue": "mystorageaccount",
    		"metadata": {
    			"description": "Name of the storage account."
    		}
    	}
    }

functions

The functions section allows you to define custom user functions that can be reused within the template. This is useful for complex logic or calculations that need to be performed multiple times.
What it does: Provides a place for reuseable custom logic with the template
Options:
  • This is genrally optional. You can leave it empty or add user-defined functions as needed.
  • Example:
  • "functions": [
    	{
    		"namespace": "myNamespace",
    		"members": {
    			"calculateValue": {
    				"parameters": ["input"],
    				"output": "[mul(parameters('input'), 10)]"
    			}
    		}
    	}
    ]

Variables

"variables": {},
The variables section allows you to define values that can be reused throughout the template. Unlike parameters, variables are not user-defined and are set by the template author.
In some scenarios, I have used the Company Name as a parameter and then reused it in variables for different resources created.
  • What it does: Stores reusable values or expressions within the template.
  • Options:
    • You can define simple values or more complex expressions.
    • Example:
    • "variables": {
      	"storageAccountType": "Standard_LRS"
      }

Resources

The resources section is where the actual Azure resources to be deployed are defined. This could include VMs, storage accounts, databases, and more.
  • What it does: Defines the Azure resources that will be created or updated.
  • Options:
    • You can define multiple resources, set dependencies between resources, and configure properties.
    • Example:
    • "resources": [
      {
        "type": "Microsoft.Storage/storageAccounts",
        "apiVersion": "2021-01-01",
        "name": "[parameters('storageAccountName')]",
        "location": "[resourceGroup().location]",
        "sku": {
      	"name": "[variables('storageAccountType')]"
        },
        "kind": "StorageV2",
        "properties": {}
      	}
      ]

Outputs

"outputs": {}
The outputs section defines any values that should be returned once the deployment is complete. This could include resource IDs, connection strings, or other useful deployment-related information.
  • What it does: Returns useful data after the deployment process.
  • Options:
    • You can output simple values, references to resources, or complex expressions.
    • Example
    • "outputs": {
      	"storageAccountId": {
      		"type": "string",
      		"value": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
      	}
        }

When building out your templates, keep these sections in mind:

  • Use Parameters to make your templates flexible.
  • Leverage variables and functions to simplify and reuse values or logic.
  • Define your resources carefully, and make use of outputs to gather important deployment information.