Azure Resource Manager (ARM) Template Basics

Get Started. It's Free
or sign up with your email address
Azure Resource Manager (ARM) Template Basics by Mind Map: Azure Resource Manager (ARM) Template Basics

1. What are ARM templates?

1.1. In Azure, teams need to manage infrastructure and application code through a unified process

1.2. ARM templates are Microsoft's solution for deploying "infrastructure as code"

1.3. The template is a JavaScript Object Notation (JSON) file that defines the infrastructure and configuration for your project

1.4. The template uses declarative syntax, which lets you state what you intend to deploy without having to write the sequence of programming commands to create it

2. Resource providers and types

2.1. One of the building blocks of Azure necessary to understand ARM templates

2.2. When deploying resources, you frequently need to retrieve information about the resource providers and types

2.2.1. For example, if you want to store keys and secrets, you work with the Microsoft.KeyVault resource provider This resource provider offers a resource type called vaults for creating the key vault

2.3. The name of a resource type is in the format: {resource-provider}/{resource-type}

2.3.1. For example, the resource type for a key vault is Microsoft.KeyVault/vaults

2.4. Before using a resource provider, your Azure subscription must be registered for the resource provider

2.4.1. In Azure Portal, via the subscription and Resource providers page, we can see all the resource providers currently registered for our subscription Here we can also register or unregister resource providers

2.5. Use Resource Explorer to see resource providers and types and how specific resources you have provisioned in one of your subscriptions are declaratively represented in JSON format

3. Resource dependencies & management hierarchy

3.1. When deploying resources, you may need to make sure some resources exist before other resources

3.1.1. For example, you need a logical SQL server before deploying a database

3.1.2. You establish this relationship by marking one resource as dependent on the other resource

3.2. Azure resources are grouped into a hierarchy

3.2.1. At the top level is the tenant A tenant is a dedicated and trusted instance of Azure AD that's automatically created when your organization signs up for a Microsoft cloud service subscription, such as Microsoft Azure, Microsoft Intune, or Office 365 An Azure tenant represents a single organization

3.2.2. At the 2nd level you can optionally create management groups If your organization has many subscriptions, you may need a way to efficiently manage access, policies, and compliance for those subscriptions

3.2.3. At the 3rd level you have subscriptions If you don't implement management groups, then subscriptions will serve as the 2nd level of the resource management hierarchy Subscriptions are created automatically when you sign up for Microsoft cloud services (inc. Azure), and you can also create additional subscriptions as a way to separate billable resources

3.2.4. At the 4th level you have resource groups A resource group is a container that holds related resources for an Azure solution All resources exist exclusively inside a single resource group It is NOT possible for a resource to exist outside of a resource group or to exist in more than one resource group Resource groups do NOT represent boundaries between dependent resources For example, it is fine to have a NIC (for a VM) exist in one resource group and a VNet that the NIC depends on exist in another resource group Resource groups do NOT constrain their associated resources to a single Azure region Although a resource group IS bound to a specific region, this is only because it is a metadata object that must exist somewhere; it can contain resources tied to different regions

4. What are the options for Azure resource provisioning?

4.1. As well as the JSON-based ARM templates, we also have the option of using the Azure Portal and/or PowerShell/CLI

4.1.1. Provisioning via Portal Main advantage is that it's intuitive However, it's not scalable or repeatable, making it a slow and error prone method, and it's simply not an option for CI/CD

4.1.2. Provisioning via PowerShell/CLI Advantage is that it's very flexible; we can specify exactly what we want via scripts that can be source controlled and repeatable The main drawback is that they are not declarative but rather procedural (i.e. you must specify exactly what resource to provision in what order), and if they fail midway you cannot just re-run the scripts

4.1.3. Provisioning via ARM templates (JSON) Advantage is that they are declarative, repeatable and restartable (i.e. you are specifying what target state should look like and Azure Resource Manager figures out how to make it so without you worrying about that process) The drawback is that the JSON templates can be intimidating at first, but they are recommended as the only way to implement Infrastructure as Code in your source control and CI/CD pipelines

5. ARM template anatomy

5.1. An ARM template has 3 key elements that you will focus most of your time on: Parameters, Variables and Resources

5.1.1. Parameters are used to customize a template with values specific for the target environment (e.g. Dev to UAT/Pre Prod/Prod, etc.)

5.1.2. Variables augment parameters by enabling common constant values or by applying expressions to parameters

5.1.3. Resources are where you specify the resource providers and types and all the configuration options for the resources, leveraging parameters and variables It's very important to avoid the inclusion of hard coded values in your resources section; there should be nothing that is instance specific or environment specific

5.2. In addition to these 3 key elements, there are some others to note

5.2.1. $schema element is always required and provides the location (in the form of a URL) of the JavaScript Object Notation (JSON) schema file that describes the version of the template language For all types of ARM template depoyment, the $schema URL begins: Appended to this URL are version number + JSON template filename The version number you use depends on the scope of the deployment and your JSON editor Deployment scope includes resource group, subscription, management group and tenant deploymentTemplate.json# references resource group subscriptionDeploymentTemplate.json# references subscription managementGroupDeploymentTemplate.json# references management group tenantDeploymentTemplate.json# references tenant Example $schema for the latest version available for resource group deployment for Visual Studio Code with Azure Resource Manager tools extension (correct as of Feb-2021 - check previous link for more up to date info)

5.2.2. contentVersion element is always required and defaults to a value of "", but this value is for us to use as developers, incrementing as we see fit during the lifecycle of the ARM template

5.2.3. apiProfile, functions and outputs are optional elements

6. How to create an ARM template

6.1. The recommended IDE for developing ARM templates is Visual Studio Code with the Azure Resource Manager tools extension, but it is not recommended to develop ARM templates from scratch

6.1.1. This provides automatic formatting and intellisense

6.2. Main options to create an initial template (which you then move into source control and develop to a conclusion using Visual Studio Code):

6.2.1. In Azure Portal, go to a currently provisioned resource (typically in your Azure Dev environment) and choose the Export template option under Automation You will find this under almost all the Azure resources although I've noticed that for Azure Data Factory, you need to launch the ADF Author & Monitor app, and the Export ARM Template option is found under the Manage page

6.2.2. In Azure Portal, search for "template" in resources and go to "Deploy a custom template" This creates a bare bones template and allows you to selectively add resources in order to build up the template

6.2.3. Go to GitHub azure-quickstart-templates repo This is the recommended way to create new templates for your own project The idea is to pick a template that comes close to meeting your needs, bring it into your project and tweak it in order to customise it for your project Templates preceded with 101 are the simplest, with 201 and 301 prefixes denoting progressively more complex scenarios Also, check out the Microsoft Azure Quickstarts Template site, as this provides some helpful search functionality with links to GitHub

7. Deploying ARM templates

7.1. There are many options for deploying ARM templates

7.1.1. Deploy ARM template via Azure Portal This is a 2-step process that involves creating a resource group manually via the Portal and then adding resources to that group using a custom (ARM) template

7.1.2. Deploy ARM template via Azure CLI

7.1.3. Deploy ARM template via Azure PowerShell

7.1.4. Deploy ARM template via REST API

7.1.5. Deploy ARM template via Azure Cloud Shell

7.1.6. Deploy ARM templates via Azure Pipelines (DevOps, for CI/CD)

7.2. There are two different deployment modes for ARM templates: incremental and complete

7.2.1. Incremental is the default mode if none is specified, and this ignores any target resources that are not specified in the ARM template, and attempts only to create or update target resources from the template

7.2.2. Complete behaves in the same way except that any resources not specified in the ARM template are removed from the target resource group Note: a single resource group is the usual target for any given ARM template It is however possible for an ARM template to deploy resources to multiple resource groups, or to deploy resources at a subscription level (typically RBAC assignments)

8. Linked and nested templates

8.1. Simple deployments only need a single ARM template, but for more complex scenarios, we should be looking at using linked or nested templates

8.1.1. Rather than having a single, huge, monolithic template that includes many resources as part of a solution, we should have a main template that references multiple smaller templates This modular approach makes template maintenance more practical and encourages re-use

8.1.2. The main template enables parameter management and provides the overall structure for calling other templates

8.1.3. Linked templates are stored as separate files and referenced by main template The linked template involves a public URI link to an ARM template file that is embedded inside the resources element of the main template The resources type is "Microsoft.Resources/deployments" The resources properties list always includes mode and templateLink Parameters for linked templates can be passed via a parametersLink to a separate parameters file or inline

8.1.4. Nested templates are embedded inside the main template The nested template is embedded inside the resources element of the main template The resources type is "Microsoft.Resources/deployments" The resources properties list always includes mode and template

9. Blueprints

9.1. Blueprints combine 3 elements: ARM templates + RBAC + Policy

9.1.1. They apply a complete configuration to an environment

9.1.2. If you have a complicated ARM template deployment, you can use a blueprint to combine many, simpler ARM templates and avoid creating a large complex template You can create a blueprint that contains only templates and no RBAC or Policy

10. Managing secrets

10.1. Secrets include usernames, passwords, access tokens and connection strings

10.2. We should never include secrets directly inside an ARM template or associated parameter file

10.3. We should use Azure Key Vault to store the secrets

10.4. The ARM templates and parameter files should contain references to secrets stored in Azure Key Vault, with appropriate RBAC permission first created via AAD + Azure Key Vault

10.4.1. In your key vault, under Access policies, you must ensure the option to enable access to Azure Resource Manager for template deployment is checked and saved

11. Best practices

11.1. There are a bunch of best practices around using ARM templates and a few of the most important are:

11.1.1. Templates have limits in terms of number of parameters, variables, resources, outputs and characters in an expression If you hit these limits, you are doing something wrong and should be looking at a much more modular approach based on linked templates or blueprints

11.1.2. Use parameters only as required Don't go crazy parameterizing values that in practice will not vary from one deployment to the next

11.1.3. Use variables if the value is needed more than once or needs to be constructed via an expression

11.1.4. Use "comments" for resources to make your templates more understandable for others

11.1.5. Only use DependsOn for a resource when it is essential as this reduces parallelism and makes the deployment slower

11.1.6. Try to create a library of template components