IaC on Azure: Terraform, ARM and Bicep

Martin Devlin
Contino Engineering

--

Infrastructure as Code (IaC) is a well-established, industry standard practice for infrastructure life-cycle management- particularly on public cloud providers like Azure. In this blog we’ll take a flyover view of the three IaC options you’re most likely come into contact with when working on Azure:

  • Terraform
  • Azure Resource Manager (ARM) templates
  • Azure Bicep

I’m going to assume you’ve already done work on another public cloud (let’s call it, oooh, AWS?) and you’re looking at working on Azure, or that you’re already using Azure and want to know what IaC options are available to you. All of these tools are idempotent so we won’t be considering that in Pro/Cons.

I’m not going to consider other options, like using az CLI, but you can read about someone who does here.

There’s a glossary of terms and some useful links at the end and here’s our Contino guide to Azure accreditation.

Terraform

Let’s start with Terraform, the go-to option for IaC and the one you’re most likely already familiar with. Terraform is a command-line tool that uses declarative manifests to create/destroy infrastructure. See our Contino guide to getting Terraform accredited.

Pros:

  • Ubiquitous: most professionals will already know this battle-hardened product and there are loads of examples, tutorials, etc.
  • Easy to use: readable yaml-like manifests, single executable, pwd-centric:
$ cd my-project/envs/dev
$ terraform init # one-off
$ terraform plan
...
$ terraform apply
...
$ terraform destroy
...
  • Community: the user community has developed various useful power-ups for Terraform, e.g. terragrunt and the Hashicorp Vault provider.
  • Cross-platform: Not only can you manage resources from multiple cloud providers in one Terraform project but much of what you learn using Terraform you can re-use elsewhere; you can even re-use some of your manifests with other cloud providers if you organise your code right.

Cons:

  • Coverage: Terraform has a mature and well-maintained Azure Provider that drives the ARM API, but in this line-up it is not going to be as up-to-date as Microsoft’s own offerings. If you’re going bleeding-edge then this might be something to consider.
  • Options: There are a multitude of patterns for organising resource and variables manifests. These can be elegant and cool, but you’ll need to put a little thought into this stuff.
  • State: You have to manage state files, which are typically stored in bucket storage like blob or S3. You need to take care around this, particularly with regard to terraformversions because breaking an environment’s state can be a painful experience.

Azure Resource Manager (ARM) Templates

ARM Templates are json manifests that are just one abstraction away from the raw API, the equivalent of AWS’s CloudFormation templates. This is the basic IaC offering and is deployed via the Portal UI or with the az tsCLI.

Pros:

  • Fully-featured: If it’s in the API then ARM templates will support it and do so with the same attributes, etc.
  • Exportable: If you’ve got a resource in Azure then you can usually export to an ARM template using the portal or az CLI. This is useful if you’ve got resources that you’ve deployed manually and want to get them into IaC.

Cons:

  • Unwieldy: the json manifests are big and verbose. Variable interpolation makes readability even more difficult.
  • Why, Just Why: Anything ARM Templates can do Bicep can do, but with much less eye-bleed and json pain and more code features.
  • Single-cloud: This is Azure-only, obs.

Azure Bicep

Cool new feature

Ignore the name. Having overcome that hurdle, the big win here is that Bicep is now Azure’s preferred IaC offering and supports everything in the API natively, just like ARM templates do but without the pain. Essentially, it’s a human-friendly wrapper around ARM. This video introduces the product nicely.

Bicep comes with a bunch of examples, is integrated with az, has an intelli-sense plugin for VSCode and they’re welcoming community contributions to the open-source project on github.

Bicep manifests look like this:

param location string = 'eastus'
param storageAccountName string = 'uniquestorage001'

resource stg 'Microsoft.Storage/storageAccounts@2019-06-01' = {
name: storageAccountName
location: location
kind: 'Storage'
sku: {
name: 'Standard_LRS'
}
}

So it’s still kind of json-y, but much more succinct than ARM templates and note that the parameters are a cinch compared to ARM templates. It also comes with language features like loops. The key takeaways are that:

  • It supports everything that ARM templates and therefore the API does, same parameter names and types.
  • It can export/import from ARM templates.
  • It’s based on simple text files.
  • It’s integrated with az out of the box. az deployment group create -f ./mystuff.bicep -g my-rg --parameters location=uksouthand you’re away. You can also use PowerShell, if that’s your thing.

Pros:

  • Azure-native: This is officially Azure’s flagship IaC product, will support everything now and going forward and is being updated regularly. Fully supported by MS and free to use.
  • Azure-integrated: No additional code to configure a provider, credentials, etc- if az works then Bicep will work from the same place.
  • Integrated state: Because it’s interacting with the API in real-time there’s no need to maintain state in external files.
  • Features: Like Terraform, Bicep supports organising your code into modules and scoping them. It also has language features like loops that are more elegant than their Terraform equivalents.
  • Way better than ARM Templates: With Bicep, MS have tried to make ARM more user-friendly, like Terraform, and the end product is somewhere between the two.

Cons:

  • Novelty: It’s new to me, it’s probably new to you, it’ll almost certainly be new to the people you want to work with it.
  • More Novelty: There’ll be bugs and probably a fair velocity in releases as it matures. Check your client SLAs if you think they may be affected.
  • Azure-only: Pretty obviously, this is 100% an Azure-only product like ARM. Scores 0 for multi-cloud and not much more for transferable skills.
  • ARM underneath: Under the hood, Bicep is still just driving ARM and is therefore limited to what ARM can do at any point.
  • Language: That .bicep file is really just a blob of json, isn’t it- meh. And the syntax-free interpolation (e.g. of location and storageAccountNamein the above example), while superficially convenient, means that vars, params and even resource names can get confused. Pro-Tip: Try prefixing with p_ , v_ and r_ to ensure uniqueness and to help you keep track of what’s a param, var or resource: p_location , r_stg

Conclusion

So what do you go for? As we all know, engineers and developers can get a bit tribal around tooling and, I’ve got to be honest, I’ve always liked working with Terraform: it is simple, it’s adaptable and it just works- just as long as you keep your state ship-shape, anyway :) The integrated state and credentials management in Bicep are, to me, its most compelling features at first glance.

But we need to be a bit more objective than that because the tooling for this is harder to change than you might think once you’ve deployed your organisation’s estate with it. So here’s my 2 cents:

ARM Templates: It’s a simple no.

Consider Bicep if:

  • Your project is Azure only.
  • You’re already using the Azure API through ARM templates, Blueprints or the az CLI. Bicep will be great upgrade for you.
  • You want the reassurance that you can call on MS for support.
  • You want to keep up with the latest Azure API.
  • You want to try something new.

Consider Terraform if:

  • Your project is multi-cloud or you may switch cloud providers later.
  • You have experienced developers, robust testing and quality-control.
  • You are more comfortable relying on your own people for support.
  • Your people favour open-source stuff.

In every case, run it by your people and see if they have a strong preference either way before letting MS talk you into Bicep.

My feeling is that organisations that are MS-centric and already heavily invested in Azure, Azure DevOps, etc will find Bicep a natural progression- particularly if they are currently using ARM Templates or Blueprints. It’s likely that ease of use in Azure Devops, in particular, will be a decisive factor. The fact that they can call on MS for support will also be a big plus for corporate users.

For organisations that are cloud-agnostic or already happily using Terraform and feel reassured that it’s the current industry standard, albeit on an Open Source support basis, then Terraform would remain the natural choice.

For new users, just try them out and go with what works for you. Both products are around for the long haul.

End

Glossary:

  • Azure: Microsoft’s public cloud offering, one of the big three along with Amazon Web Services (AWS) and Google Cloud Platform (GCP).
  • Declarative: Declares a desired state: set the table for 4 people.
  • IaC: Infrastructure as Code, a software methodology to manage IT infrastructure using automated tooling and version-controlled code.
  • Idempotent: Command that can be safely run over again and will add/modify/delete/do nothing, as appropriate.
  • Imperative: An instruction that doesn’t consider current state: set the table for 1 more person.
  • Manifest: As in cargo manifest- a list of items and their attributes, in this case of cloud compute resources.

References:

https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs

--

--