In the previous episode, we took a look at the ARM template schema, some of the tools that will help get you started in your ARM template journey, and deployed our first template. In this installation, we’ll take a deeper dive into some of the development methods and strategy.
Define Template Scope
Before developing a template, it’s important to define the scope of the template. In extreme cases, this could be the difference between the idea of an “infrastructure in a box” where you deploy a single template for your entire infrastructure vs. deploying separate templates for each resource type as you would in the Portal. Like most things, I think the best strategy is somewhere in the middle, and depends on your needs.
Generally, a good start is to begin your scope at the Resource Group level (however, it is possible to deploy to multiple Resource Groups). Some other things to think about when scoping the template are the region, life-cycle, deployment frequency, resource types, and purpose, of the resources.
For example, we may have an application that requires multiple Virtual Machines with separate roles. The architecture calls for 2 front-end servers, 2 application servers, and 2 back-end servers. You could deploy all 6 servers with a single template, but that could get convoluted and doesn’t provide the flexibility to easily redeploy a single tier. In this case, we can scope the templates to the tier level and separate out the 3 tiers into 3 templates.
Define Resource Property Values
With the template scope defined, the next step is to define the resource property values. These are the settings applied to Azure resources, like a Virtual Network’s address space, or a Virtual Machine’s OS.
Parameters can be used to define values that can change between deployments. The more parameters defined, the more dynamic the template becomes. Resource names are a great example of values that are generally set as parameters.
Variables can be used to reference hard-coded values that can be used multiple times throughout the template and are not going to change throughout deployments. However, defining a resource property as a variable allows us to easily change the value at a later point in time if needed.
Hard-coded values can be used to define settings that are not changing between deployment and are not going to change.
Define a Folder Structure
Determining an organized folder structure can be extremely valuable when developing your templates. As you start digging into more complex templates with multiple references, it’s easy to lose track of your files and end up with code sprawl.
Generally, I start by creating a root folder with a name that specifies the purpose of the template.
Inside the root folder, I place the template “azuredeploy.json” file, along with dedicated folders for the additional files that will be referenced by the template. The “parameters” folder for instance, contains any of the parameters files that are used to deploy the template. Multiple sets of parameters files can be stored inside this folder for separate deployments.
Understanding ARM API Versions
Each resource defined in a template contains an API version reference . Understanding how Azure manages these API versions can save you a lot of headache. Azure releases new API versions that include the latest features or settings available for a resource. However, it’s important to note that when a new API version is released, only certain Azure resources will be included in the release. This means that we can’t just grab the latest API version available and use that value for every resource in the template. It’s important to keep track of these API releases and ensure that templates are kept up to date.
The Azure team maintains a public GitHub repository of the ARM API versions available.
Additionally, you can download the deployment schema from the link below and search for the specific resource type and API versions available for that resource.
Development Scenario and Methods
There are multiple options for developing templates. To demonstrate these options, we’ll create an ARM template to deploy the following architecture. In this example we’re assuming that we have a server based web application that will utilize an Azure SQL database at the data tier.
We’ll start by browsing to the Azure QuickStart Template repository that’s hosted on GitHub. From here, we can search through sample templates for one that suits our needs. One of the sample templates available (shown below) will serve as a great starting point will account for the web application server.
Browse to the following location and download the “azuredeploy.json” and “azuredeploy.parameters.json” files.
Azure Generated Automation Script Templates
With our web application server taken care of, we need to add in our SQL Server and Database. For these two components, we’ll download the Automation Script template that Azure generates for existing resources.
We’ll start by provisioning an Azure SQL instance within the portal.
Once the SQL deployment is complete, we’ll navigate to the SQL Database resource and browse to the “Automation Script” blade. It’s important to note that the Automation Script will consist of all resources within the same Resource Group.
At the top of the Automation Script blade, we can download the template files to our local machine.
The downloaded template contains a number of reference files:
deploy.ps1 – PowerShell deployment script
deploy.sh – Azure CLI deployment script
deployer.rb – Azure Ruby SDK deployment script
DeploymentHelper.cs – C# class to deploy the template
parameters.json – parameters file for the deployment
template.json – core template file containing all of the resources to be deployed
For now, all we’re going to need from these files are: parameters.json and template.json.
Stitching the Templates Together
Now we need add the Azure SQL components into our template.
When we open up the downloaded template, we find that it consists of a number of resources outside of the Azure SQL Server and Database. In this case these resources include some of the Azure SQL settings that are provided by default and weren’t necessarily defined when we created the database in the Portal. For our purposes, we’ll remove all the resources and parameters outside of the SQL Server and Database. Then we can just copy/paste these sections into our existing template.
Template Reference Documentation
It’s just about time to test our template but let’s validate our downloaded template against the reference documentation. Navigate to the Azure reference documentation (found here) and browse under the “Reference” section to find SQL > Servers. In comparing the downloaded Automation Script template to the reference documentation, we notice that the “administratorLoginPassword” setting is missing from our template. Since the Automation Script does not download the secure string value, the setting is omitted from the downloaded template. It’s imperative to set a password on the database, so we’ll add this property into our template.
Currently, our template consists of the Azure QuickStart Virtual Network, Subnets, Virtual Machine, Network Interfaces, and the Automation Script downloaded SQL Server and Database which we validated against the template reference documentation. Let’s take a look at this template and deploy it into Azure.
We have all of the components accounted for – as laid out in our diagram – so let’s try deploying it:
Our template deployed successfully. Now we can take a look at our Resource Group in the Azure Portal and find that it consists of all the resources defined in our architecture.