Azure Resource Manager (ARM) Templates - Deep Dive

Posted by: Brian Martel , on 2/23/2023, in Category Microsoft Azure
Views: 18752
Abstract: Azure Resource Manager (ARM) templates provide a powerful, flexible solution for managing and deploying resources in Azure. This article explores ARM template structure, deployment of multiple resources, multi-tiered templates, nested and linked templates, and parameter files.

Azure Resource Manager (ARM) templates are an efficient and adaptable way to define and deploy resources in Azure. They are JSON files that describe the desired state of resources and their dependencies and offer a structured approach to managing resources, ensuring consistency and reliability across different environments.

We briefly touched upon ARM templates in my previous article Provisioning Virtual Machines (VMs) in Azure.

In this tutorial, we will explore ARM template structure, deployment techniques for multiple resources, multi-tiered templates, nested and linked templates, and parameter files.

Breaking Down ARM Template Structure

ARM templates are composed of several elements, including mandatory and optional components. These elements are $schema, contentVersion, parameters, functions, variables, resources, and outputs.

Mandatory Elements

$schema

The $schema element is used to define the JSON schema that the ARM template will follow. It points to an official Microsoft schema definition and ensures the template adheres to the expected structure.

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

contentVersion

The contentVersion element specifies the version of the template. This is a required field, and it follows the format “Major.Minor.Patch”. Incrementing the version number helps track template changes over time.

{
  ...
  "contentVersion": "1.0.0.0",
  ...
}

Optional Elements

parameters

The parameters element allows customization of deployment without modifying the template. It does so by defining input values passed during deployment. Parameters are optional, but they offer a flexible way to manage different environments or configurations.

{
  ...
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "eastus",
      "metadata": {
        "description": "Location for all resources."
      }
    },
    ...
  },
  ...
}

functions

The functions element enables you to define custom functions that can be used within the template. These optional elements are useful for code reuse, simplifying expressions, or enhancing readability. Functions are defined using the namespace, members, and output properties. 

{
  ...
  "functions": [
    {
      "namespace": "customFunctions",
      "members": {
        "concatenateStrings": {
          "parameters": [
            {
              "name": "string1",
              "type": "string"
            },
            {
              "name": "string2",
              "type": "string"
            }
          ],
          "output": {
            "type": "string",
            "value": "[concat(parameters('string1'), parameters('string2'))]"
          }
        }
      }
    }
  ],
  ...
}

variables

variables store reusable values within the template. These optional elements help improve readability and maintainability by centralizing common values or expressions. Variables can reference parameters, other variables, or functions. 

{
  ...
  "variables": {
    "storageAccountName": "[concat('storage', uniqueString(resourceGroup().id))]",
    ...
  },
  ...
}

outputs

outputs define values returned after deployment completion. These optional elements are useful for capturing information about deployed resources, such as resource IDs or connection strings. 

{
  ...
  "outputs": {
    "storageAccountName": {
      "type": "string",
      "value": "[variables('storageAccountName')]"
    }
  }
}

Resources

resources are the core of ARM templates, defining the Azure resources that will be deployed or updated.

This mandatory field contains an array of resource objects. Each resource object includes properties such as type, apiVersion, name, location, dependsOn, and others. The type and apiVersion properties are crucial, as they specify the resource type and the version of the Azure Resource Manager API to be used for the deployment.

{
  ...
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2021-04-01",
      "name": "[variables('storageAccountName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "StorageV2"
    },
    ...
  ],
  ...
}

Deploying Multiple Resources

When deploying solutions in Azure, it’s common to have multiple resources that must be created or updated. ARM templates support two primary approaches for deploying multiple resources: multi-tiered templates and nested or linked templates.

Multi-tiered Templates

Multi-tiered templates enable the deployment of multiple resources within a single template, with some resources potentially depending on others. This approach is suitable for less complex solutions, as it allows for a single file that can deploy the entire solution to a resource group.

For instance, an ARM template can deploy an App Service plan and a web app. The web app may conditionally deploy a staging deployment slot if a production Boolean parameter is true. This demonstrates conditional resource deployments.

Nested and Linked Templates

For larger and more complex solutions, it can be helpful to split parts of a solution into separate templates and use another template to connect them. Nesting a template refers to defining the contents of another template as a Microsoft.Resources/deployments resource within the main template. Linking a template, on the other hand, involves providing the URI to a template file, which can be local or over the network.

Nested Template Example

Here’s an example of a nested template, where the contents of a child template are defined as a Microsoft.Resources/deployments resource within the main template: 

{
  ...
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "nestedTemplate1",
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "resources": [
            {
              "type": "Microsoft.Storage/storageAccounts",
              "apiVersion": "2021-04-01",
              "name": "[parameters('storageAccountName')]",
              "location": "East US",
              "sku": {
                "name": "Standard_LRS"
              },
              "kind": "StorageV2"
            }
          ]
        }
      }
    }
  ],
  ...
}

Linked Template Example

Here’s an example of a linked template, where the main template refers to another template file by providing its URI: 

{
  ...
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "linkedTemplate",
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri":"https://mystorageaccount.blob.core.windows.net/AzureTemplates/newStorageAccount.json",
          "contentVersion":"1.0.0.0"
        }
      }
    }
  ],
  ...
}
linked-templates-azure

Parameter Files

For a small number of parameters, specifying them in the deployment command is usually sufficient. However, as the number of parameters increases, using parameter files becomes more practical.

Parameter files can define values for parameters in ARM templates, allowing you to have a set of parameters for specific environments (e.g., development or production) and reference the relevant file during deployment. Parameter files are JSON files, and here’s an example for our ARM template, named web-app.parameters.json

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "production": {
            "value": false
        },
        "appPrefix": {
            "value": "myprefix"
        },
        "location": {
            "value": "eastus"
        }
    }
}

To use this file, remove the parameter arguments in the command lines and add --TemplateParameterFile <path to parameter file> in PowerShell or --parameters @{path to parameter file} in the CLI. You can create multiple parameter files with different values for different environments, such as development and production, and reference the appropriate file during deployment.

By deploying infrastructure consistently using ARM templates, you can streamline the management and maintenance of your Azure resources. This approach promotes reusability and consistency across environments, enabling better collaboration among team members and reducing the risk of manual configuration errors.

ARM Templates – Benefits

Using Azure Resource Manager templates provides several benefits:

1. Modularization: Splitting large templates into smaller, more manageable pieces enables better organization and easier maintenance. You can create reusable modules that can be combined and customized to suit various scenarios.

2. Versioning: ARM templates can be version-controlled, ensuring that you always have a history of changes and can roll back to previous versions if needed.

3. Parameterization: Parameter files allow you to customize template deployments with different values for different environments, such as development, staging, and production. This promotes consistency and minimizes the risk of accidental misconfigurations.

4. Automation: ARM templates can be deployed via the Azure Portal, Azure CLI, or Azure PowerShell, enabling you to automate infrastructure provisioning as part of your CI/CD pipeline.

5. Validation: ARM templates can be validated before deployment, ensuring that any potential issues are caught before they cause problems in your infrastructure.

Conclusion

ARM templates provide a robust and flexible method for managing Azure resources, enabling consistent and reliable infrastructure across various environments.

They allow for modularization, versioning, parameterization, automation, and validation, leading to simplified resource management and increased efficiency in cloud deployments.

By understanding and implementing ARM templates, you as a developer can significantly improve your Azure resource management process. This was also help your team to collaborate in a better way and reduce the risk of manual configuration errors.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author

Brian Martel, an experienced Azure and DevOps developer, has spent the last decade mastering technologies such as Kubernetes, Docker, Ansible, and Terraform. Armed with a Bachelor's degree in Computer Science and certifications like Cloud DevOps Engineer Expert (AWS and Azure) and Certified Kubernetes Administrator (CKA), Brian has a proven track record of guiding organizations through successful transitions to cloud-based infrastructures and implementing efficient DevOps pipelines.

He generously shares his wealth of knowledge as a mentor and an active participant in the developer community, contributing articles, speaking at user groups, and engaging with others on social media. All the while, Brian remains dedicated to staying current with the latest trends in his field.



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!