Elevating IaC Workflows with Spacelift Stacks and Dependencies 🛠️

Register for the July 23 demo →

General

What is an Azure ARM Template? Overview, Tutorial & Examples

What is an Azure ARM Template?

In this article, we will explore Azure ARM templates, giving a complete into what they are, why you might use them, and their makeup, before running through some practical examples you can follow along with. Let’s jump straight in!

  1. What is ARM?
  2. What is an ARM template?
  3. ARM templates benefits
  4. ARM template file format
  5. Azure Quickstart templates
  6. How to create an ARM template
  7. Example – How to deploy ARM templates using PowerShell
  8. ARM Deployment Modes
  9. ARM template vs Terraform
  10. ARM template vs Azure Blueprints
  11. ARM templates best practices

What is ARM?

When you deploy resources in Azure, whether through the Azure Portal, Azure CLI, or other tools, you are likely interacting with Azure Resource Manager (ARM) under the hood. ARM provides a consistent way to deploy and manage resources, making it easier to automate deployments, enforce policies, and maintain Infrastructure as Code practices in the Azure ecosystem.

What is an ARM template?

ARM templates describe the desired state of resources in a declarative manner, allowing you to specify what resources should exist and their configurations. ARM templates are written in JSON (JavaScript Object Notation) and are used to define and deploy resources into the Microsoft Azure cloud platform.

Similar to AWS CloudFormation, or multi-cloud capable Infrastructure as Code (IaC) languages such as Terraform or Pulumi, ARM templates are the Azure-specific IaC option.

ARM templates benefits

Using ARM templates to deploy resources into Azure comes with all the generic benefits of using IaC. These include consistent deployments, reusability, modularity, versioning, ability to rollback, automation, and orchestration, to name a few.

In short, using IaC enables you to streamline deployment processes, reduce manual errors, and maintain a high level of consistency and reliability in your Azure environments when compared to using the Azure portal or other deployment methods such as Azure CLI, Azure Powershell, or the Azure API.

ARM resolves dependencies between resources during deployment, regardless of the deployment mode. Resources are deployed in the correct order based on their dependencies.

ARM template file format

ARM templates typically have a file extension of .json. The top-level structure includes various properties, each serving a specific purpose. The schema declaration property is first up and specifies the version of the ARM template schema that the template uses.

For example:

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

The contentVersion property indicates the version of the template. This is typically a string, and it is used for versioning the template.

For example:

"contentVersion": "1.0.0.0"

Comments in ARM templates are written using /* */ for block comments and // for inline comments.

Parameters

ARM templates can include parameters to allow users to input values during deployment. Parameters make templates more flexible and reusable.

For example:

"parameters": {
  "paramName": {
    "type": "string",
    "defaultValue": "defaultValue"
  }
}

Variables

Variables in ARM templates can be used to store and reuse values within the template.

For example:

"variables": {
  "varName": "variableValue"
}

Functions

ARM templates support a variety of functions that you can use to perform operations, create strings, manipulate data, and more. Functions are an integral part of template expressions.

For example, using the concat function:

"variable": "[concat('prefix', parameters('paramName'))]"

Resources

Resources are the entities you want to deploy in Azure, such as virtual machines, storage accounts, or virtual networks. Each type of resource has its own set of properties and configurations.

Resource types are defined by Azure and correspond to specific Azure services. For example, Microsoft.Compute/virtualMachines is a resource type for virtual machines.

For example:

"resources": [
  {
    "type": "resourceType",
    "apiVersion": "apiVersion",
    "name": "resourceName",
    "location": "resourceLocation",
    "properties": {
      // Resource-specific properties
    }
  }
]

Outputs

Outputs in an ARM template allow you to expose information from the deployed resources. These outputs can be used for reference or passed as parameters to other templates.

For example:

"outputs": {
  "outputName": {
    "type": "outputType",
    "value": "outputValue"
  }
}

Pulling all the components together, the below is a simple example of a template to create a Virtual Network with a single subnet:

vnet.json

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [
    {
      "type": "Microsoft.Network/virtualNetworks",
      "apiVersion": "2020-11-01",
      "name": "MyVNet",
      "location": "East US",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "10.0.0.0/16"
          ]
        },
        "subnets": [
          {
            "name": "MySubnet",
            "properties": {
              "addressPrefix": "10.0.0.0/24"
            }
          }
        ]
      }
    }
  ]
}

Azure Quickstart templates

Azure Quickstart Templates are a collection of pre-built Azure Resource Manager (ARM) templates provided by Microsoft and the Azure community. These templates are designed to simplify the process of deploying commonly used infrastructure and applications on Azure. You can find these templates on the official GitHub repository named “Azure/azure-quickstart-templates.”

How to create an ARM template

Let’s go through the steps to create the ARM templates.

  1. Understand the end goal you want your Azure resource to look like, e.g., as shown in the previous example, the deployment of a VNET with a single subnet in the EastUS region.
  2. Get comfortable with the makeup of ARM templates — check out the latest schema on GitHub.
  3. Choose a code editor such as Visual Studio code and create a new file with a .json extension. You can install the VSCode ARM template extension to provide language support, resource snippets, and resource auto-completion to help you create and validate Azure Resource Manager templates.
  4. Start filling in the ARM template with a basic structure, at a minimum, this will include a schema, contentVersion, resources, and outputs.
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "resources": [],
  "outputs": {}
}
  1. Fill out the resources section, for example our VNET configuration might look like this:
"resources": [
    {
      "type": "Microsoft.Network/virtualNetworks",
      "apiVersion": "2020-11-01",
      "name": "MyVNet",
      "location": "East US",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "10.0.0.0/16"
          ]
        },
        "subnets": [
          {
            "name": "MySubnet",
            "properties": {
              "addressPrefix": "10.0.0.0/24"
            }
          }
        ]
      }
    }
  ]
  1. Deploy the template using the methods shown below.

Example - How to deploy ARM templates using PowerShell

Once you have defined your ARM template, you can deploy it using Powershell. The script below can be altered as necessary:

deploy-vnet.ps1

$resourceGroupName = "MyResourceGroup"  # Replace with your desired resource group name
$deploymentName = "MyVNETDeployment"        # Replace with your desired deployment name
$templateFile = "C:\Path\To\Your\vnet.json"  # Replace with the path to your ARM template file

# Login to Azure (you will be prompted for credentials)
Connect-AzAccount

# Create a new resource group
New-AzResourceGroup -Name $resourceGroupName -Location "East US"

# Deploy the ARM template
New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -Name $deploymentName -TemplateFile $templateFile
.\deploy.ps1

Or using Azure CLI:

az login

az group create --name MyResourceGroup --location EastUS

az deployment group create \
  --resource-group MyResourceGroup \
  --template-file azuredeploy.json

ARM deployment modes

Azure Resource Manager (ARM) supports two primary deployment modes for deploying and managing resources: incremental mode and complete mode. By default, deployments operate in incremental mode. You only need to specify --mode Complete if you explicitly want to use complete mode.

Incremental mode

In incremental mode, ARM deploys and updates only the resources defined in your template that have changed or are new. It leaves existing resources in the resource group unchanged. Incremental mode is suitable for most scenarios, especially during regular deployments or updates where you want to add, modify, or remove specific resources without affecting the entire resource group.

Complete mode

In complete mode, ARM deploys and updates all resources defined in your template, and it removes any resources in the resource group that are not defined in the template. Complete mode is typically used when you want to ensure that the resource group exactly matches the state defined in the template. It’s more aggressive and can lead to the deletion of existing resources not defined in the template.

Examples to deploy using the complete mode

Azure CLI:

az deployment group create --resource-group MyResourceGroup --template-file azuredeploy.json --parameters @azuredeploy.parameters.json --mode Complete

Azure Powershell:

New-AzResourceGroupDeployment -ResourceGroupName MyResourceGroup -TemplateFile .\azuredeploy.json -TemplateParameterFile .\azuredeploy.parameters.json -Mode Complete

ARM template vs Terraform

Azure Resource Manager (ARM) templates and Terraform are both Infrastructure as Code (IaC) tools used for provisioning and managing resources in cloud environments. However there are some key differences:

Syntax

Both use declarative language — ARM uses JSON, whereas Terraform uses HashiCorp Configuration Language (HCL). HCL provides a concise and expressive syntax, allowing users to define infrastructure configurations with ease, in contrast, JSON can be trickier to follow.

Ecosystem

ARM can only be used with Azure, whereas Terraform can be used with multiple providers (for example, Azure, AWS and Google Cloud). Provider independence is a key benefit of using Terraform.

It also has a large and active community, resulting in a rich ecosystem of modules and configurations that can be shared and reused, although the ARM quick start templates are a great resource and also have a large and active community.

ARM templates provide tight integration with Azure services, offering first-party support and specific resource types. Terraform has Azure provider support, but it may not cover all Azure services immediately after their release. ARM templates can be authored and deployed directly from the Azure Portal, providing a seamless experience.

State files

Terraform maintains a state file that tracks the current state of the infrastructure, helping with resource tracking and changes.

When using automation and CI/CD pipelines to run Terraform, the state file needs to be accessible, and permission must be given to the service principal running the pipeline to access the storage account container that holds the state file. This makes shared storage the perfect candidate to hold the state file. Permissions can be granted as needed. Azure Storage accounts or Amazon S3 buckets are an ideal choice. You can also use a tool such as Spacelift to manage your state for you.

ARM template vs Azure Blueprints

Where ARM templates are primarily used for Infrastructure as Code (IaC), Azure Blueprints are used for defining and deploying a set of resource templates and other artifacts as a package. They go beyond IaC and also include policy definitions, resource groups, role-based access control (RBAC), and more. ARM templates offer fine-grained control over individual resources, while Azure Blueprints provide a higher-level, more abstract view of an entire environment. Azure Blueprints aims to provide a more comprehensive governance framework.

ARM templates best practices

Adhering to best practices can help ensure the reliability, security, and maintainability of your infrastructure. The following points apply to most IaC languages.

  1. Break down your templates into smaller, modular files, enabling them to be reused.
  2. Use parameters to allow users to input values during deployment.
  3. Use variables to reduce redundancy.
  4. Avoid hardcoding secrets or sensitive information directly in the template. Instead, use Azure Key Vault or other secure methods for handling sensitive data.
  5. Implement proper error handling in your templates. Leverage functions like copyIndex() and if() to handle different scenarios gracefully.
  6. Validate your templates before deployment using tools like the Azure Resource Manager Template Toolkit (arm-ttk) or built-in validation commands in Azure CLI or PowerShell.

For example, the validate command in Azure CLI or the Test-AzResourceGroupDeployment checks the template syntax and structure without actually deploying any resources.

az deployment group validate --resource-group <resource-group-name> --template
Test-AzResourceGroupDeployment -ResourceGroupName <resource-group-name> -TemplateFile <path-to-template-file>
  1. Store your templates in a version control system (e.g., Git) to track changes, collaborate with others, and maintain a history of your infrastructure code.
  2. Include comments and documentation in your templates to explain the purpose of resources, parameters, and variables.

Key points

ARM templates are used as a declarative IaC method to deploy resources into Azure. They have many advantages if you are strictly working with Azure, but you may want to consider other options, such as Terraform, if you want to work with multiple clouds or prefer working in HCL syntax over JSON. Utilizing the Azure quick-start templates when working with ARM is a great way to get familiar with the syntax and layout, and in most cases, there is no need to create ARM templates from scratch.

If you want to learn more about Spacelift, create a free account today or book a demo with one of our engineers.

The Most Flexible CI/CD Automation Tool

Spacelift is an alternative to using homegrown solutions on top of a generic CI. It helps overcome common state management issues and adds several must-have capabilities for infrastructure management.

Start free trial

The Practitioner’s Guide to Scaling Infrastructure as Code

Transform your IaC management to scale

securely, efficiently, and productively

into the future.

ebook global banner
Share your data and download the guide