Exploring ARM Templates

February 9, 2017

Blog | Development | Exploring ARM Templates
Exploring ARM Templates

We’ve recently been exploring  ARM templates to mitigate the cost of environment setup. In this blog post, we’ll go over everything we’ve discovered and help you understand what ARM templates are, how to configure them, and why they are useful.

What is an ARM Template?

ARM template stands for Azure Resource Management templates. Azure is a cloud computing platform made by Microsoft and ARM templates are used to configure groups of cloud computing resources. The primary use case we’ve used ARM templates for is creating resource groups of virtual machines. For each resource type (such as Virtual Machine, Network Interfaces, Virtual Networks, etc.) there is a JSON (JavaScript Object Notation) schema that defines how it works.

ARM templates are declarative templates written in JSON. Visual Studio has an add-on that can give you base layouts for each resource type, it is highly recommended you install this before trying to write templates (although it still has some quirks, such as faulty syntax highlighting). This add-on can be found here. Deployment of these templates is handled via a PowerShell script. A base version of this script is delivered via Microsoft’s git repo for ARM templates.

Desired State Configs

You can define PowerShell scripts that you want to run on each VM via DSC. DSC’s are Desired State Configs, they are not part of the ARM templating system but rather a PowerShell tool. They are essentially declarative PowerShell scripts and are very useful for configuring Windows servers.

You hand the DSC to the VM and say “Hey, I want the VM to ultimately have all these things installed and running, you do whatever you have to do to get us from where you are now to where I want you to be.” A lot of the useful add-ons (like network/firewall) are experimental and can be found in here.

Developers Tip: Don’t use ARM Templates to debug your DSC. Use the built-in PowerShell tool: Start-DscConfiguration.

*For specifics on running a DSC visit Windows PowerShell Desired State Configuration Overview.

Why are ARM templates useful?

There are two main reasons to use ARM templates, timing, and cost. In this case, time savings equates to cost savings.

Developer time is expensive, and setting up environments manually takes a really long time. Once you have an ARM template created, all you have to do is update the parameters and then you have something specific for your project. Updating the parameters take 5 -10 minutes and updating the script takes 20 minutes, vs. provisioning environments manually which could take a full day.

In addition, having an environment means you have to pay hosting costs. Oftentimes, environments sit there not being used, and are not deleted even though you are paying for them because it’s actually more cost-effective to keep them up and running instead of provisioning it again later. ARM Templates will let you delete the environments and easily be able to rebuild them as needed via a handful of command line calls.

ARM templates are still relatively new to the new Azure portal. There are still kinks that need to be ironed out and functionality that doesn’t perform as expected but overall it’s effective and they are expanding and updating it regularly.

The interesting thing about ARM Templates is they can be generalized and customized. You start out with a general template but have parameters that can be modified. You have a separate azuredeploy.parameters.json file where all these customizations can be made. You can also setup a DNS zone in one resource group to handle all your DNS entries right in Azure instead of out on wherever your registrar lives.

Putting ARM Templates to Use:

We’ve been using ARM templates to create the various environments for a project; dev, QA, and demo. I was able to write one template that worked for 2 out of the 3 environments and just required parameter updates. For the final environment, I was able to use the other template as a base and expand upon it. These templates have been used by other developers on other projects, so once one is set up, it can be used for various purposes saving time and resources that can then be allocated towards other project areas.

Examples and How to:

Starting out you need the base azuredeploy.json for an arm template, this can be fetched from the azure quickstart template repo.

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
    },
    “variables”: {
    },
   “resources”: [
   ]
}

You’ll notice a few main sections here, Parameters, variables, and resources. Parameters is an area to define useful key value pairs that can be easily overridden in your azuredeploy.parameters.json. Anything that needs to be customized on a per item basis should be placed there. Let’s add environment prefix:

...
    "parameters": {
        "envPrefixName": {
           "type": "string",
           "metadata": {
               "description": "Prefix for the environment (2-5 characters)"
            },
           "defaultValue": "cust1",
           "minLength": 2,
           "maxLength": 5
    },
...

You’ll notice that it has a type, some metadata, default value, minLength, and maxLength. The only required data is the type, though it’s highly suggested that you have a metadata description. You can also limit values acceptable in parameters using the “allowedValues” array.

Next is variables. Variables are constructed values using other information, such as your parameters, static values (like IPs and IDs) and resourceIDs constructed from resources you produce later.

Let’s define a server name and list our apiVersion there too.

...
    “variables”: {
        "apiVersion": "2015-06-15",
        "webSrvName": "[concat(parameters('envPrefixName'), 'webSrv')]"
    },
...

We’re accessing the envPrefixName using the parameters() function. Accessing variables is very similar, but uses the variables() function.

Now we’ll define a VM in the resources array. Items in the resources array are generated in no particular order unless you state that one resource relies on another. In a real ARM template you would need to define a storage account, network interface, and any other resources your VM may rely on, but for this example, we will abstract that away.

…
    “resources”: [
    {
      "name": "[variables('webSrvName')]",
      "type": "Microsoft.Compute/virtualMachines",
      "location": "[resourceGroup().location]",
      "apiVersion": "[variables('apiVersion')]",
      "tags": {
        "displayName": "WebSrv"
      },
      "properties": {
        "hardwareProfile": {
          "vmSize": "["Standard_DS1"]"
        },
        "osProfile": {
          "computerName": "[variables('webSrvName')]",
          "adminUsername": "[“admin”]",
          "adminPassword": "[“Password123!”]"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "MicrosoftWindowsServer",
            "offer": "WindowsServer",
            "sku": "2012-R2-Datacenter",
            "version": "latest"
          },
        },
      }
    },
]
...

So, now you want to define what you want your variables to be for this environment. This is done in azuredeploy.parameters.json.

{
  "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "envPrefixName": {
      "value": "blog"
    }
  }
}

The important thing here is that you define the schema as http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#

This will change the envPrefixName parameter to blog instead of cust1.

Now to deploy it you should use the default Deploy-AzureResourceGroup.ps1 PowerShell script supplied by the quickstart template. This script can be updated and modified depending on your specific needs. This ps1 script should be located in the same place as your JSON files and any DSC that you may need for your env.

First thing you must do is navigate to the folder with your PowerShell script in an admin PowerShell console. Log into AzureRM with Login-AzureRmAccount then run the following commandlet:

.\Deploy-AzureResourceGroup.ps1 -ArtifactStagingDirectory 'WebCluster' -ResourceGroupLocation eastus 
-ResourceGroupName 'MyTestResourceGroup'

You can, of course, change the value of  ArtifactStagingDirectory, ResourceGroupLocation, and ResourceGroupName to values that work for you. This will check your template for validity then run through the steps to create your defined resources!

Now, this definitely isn’t all you need to start an ARM template, but most resources and variables follow a similar formula. All you need to get started can be found on Azure’s GitHub. It’s worth checking out.

George Jaray

George Jaray

Developer
Tags
  • ARM Templates
  • Azure
  • Productivity
  • Tutorial

Recent Work

Check out what else we've been working on