LW.

Glorified Notepad

Why Terraform?

2021-03-06 Azure ARM Terraform IaC

Intro

I’m often asked if Microsoft provides the ability the deploy resources into Azure using Azure Resource Manager templates (ARM Templates) then why would I use Terraform for CI/CD deployments? In this post, I’ll try to answer this and provide an understanding of the differences and why, in my opinion, Terraform is the most versatile and agile tool available for IaC deployments.

Why Infrastructure as code?

Anyone who’s spent anytime deploying to Azure knows that the user interface is intuitive and that it guides you through the creation of deploying resources really well, prompting you for missing information and providing handy tooltips. Using the portal can, however, lead to human error and doesn’t lend itself to deploying at scale or redeploying the same resources over and over.

IaC allows organizations to capture infrastructure or application requirements in code allowing for redeployment, deployment at scale and can ensure that all resources are deployed using the correct standards. The largest benefit to investing in IaC is the time saving it offers giving organizations the ability to spin up vast environments with little configuration.

What are ARM templates?

ARM templates are Microsoft’s answer to IaC and contain all the parameters required to deploy a given resource. When deployed via Cloudshell or Powershell templates are able to create resource objects automatically without the need to be manually deployed through the portal.

ARM templates use JSON files typically referencing a variables file. The below is an example of an ARM template used to deploy a storage account:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageAccountType": {
      "type": "string",
      "defaultValue": "Standard_LRS",
      "allowedValues": [
        "Standard_LRS",
        "Standard_GRS",
        "Standard_ZRS",
        "Premium_LRS"
      ],
      "metadata": {
        "description": "Storage Account type"
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "Location for all resources."
      }
    }
  },
  "variables": {
    "storageAccountName": "[concat('store', uniquestring(resourceGroup().id))]"
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2019-06-01",
      "name": "[variables('storageAccountName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "[parameters('storageAccountType')]"
      },
      "kind": "StorageV2",
      "properties": {}
    }
  ],
  "outputs": {
    "storageAccountName": {
      "type": "string",
      "value": "[variables('storageAccountName')]"
    }
  }
}

Pros

  • Native to Azure
  • Always up to date and in sync with new services launched
  • Can be used directly from the Azure portal via “Template Deployment” deployed or via Cloudshell/Powershell
  • Can be provided to other users for easy deployment – for example, if offered to support a service.
  • Can be deployed by CI/CD services such as Azure DevOps

Cons

  • Larger, more complex code required adding to potential human error
  • Does not hold any state information
  • Cannot reference data from the deployment
  • Does not support other platforms

More Info on ARM templates can be found Here

What is Terraform?

Terraform uses HashiCorp Configuration Language (HCL) that allows organizations to define environments across over 200 providers covering both on-premises and cloud technologies such as Azure, AWS, G Cloud, and VMWare vSphere. HCL is a simple human-readable language that minimizes the code required for a given deployment relying on standardized blocks known as “Resource Blocks”.

Terraform utilizes a state file that keeps detailed information of previous deployments, allowing for data references from other resources. This feature further enables teams to utilize less code focusing on speed and accuracy. Terraform’s configuration elements are stored within .tf files and typically reference variable files using .tfvars files.

The below is an example of a Terraform template used to deploy a storage account:

resource "azurerm_storage_account" "example" {
  
  count                     = 1
  name                     	= "storageaccountname${count.index}"
  resource_group_name      	= azurerm_resource_group.example.name
  location                 	= azurerm_resource_group.example.location
  account_tier             	= "Standard"
  account_replication_type 	= "GRS"
  tags = {
    environment = "staging"
  	     }

}

Pros

  • Supports over 200 deployment types
  • Minimizes code required
  • Holds a state file that can be read from by other resources
  • Provides a hugely scalable solution
  • Can be deployed by CI/CD services such as Azure DevOps

Cons

  • Relies on Azure Resource Manager API’s
  • Lags behind ARM templates as updates to ARM API’s are slower than the release of services
  • Cannot be deployed directly from the Azure portal
  • Requires additional tooling/configuration initially

More Info on Terraform can be found Here

Conclusion

ARM templates provide a great way to deploy services into Azure using native tools that will almost always be up to date but lacks in areas such as multi-cloud, hyper-scale deployments, or code minimization. As such it is best used for smaller-scale deployments or where a service is going to be offered to external users such as via the Azure marketplace or GitHub.

Given that Terraforms code is much smaller, more flexible, easier to manage, and can cover multi-cloud and even on-premises solutions it is my preferred deployment tool giving me the ability to provide my customers with an IaC solution that can fit almost every requirement. It is however a personal and business decision, so I would recommend you review your requirements, consider future changes to that, and base your own decisions based on the outcome of these.

Project Bicep

Whilst Terraform is my personal choice today, Project Bicep is currently within its development stages and is aiming to reduce the code complexity of ARM using Domain Specific Language (DSL) for deploying Azure resources declaratively. As this service matures there is every chance that the benefits could outweigh the fact it is platform-specific, and I’ll review this over time.

If you’d like to take a look at Azure Bicep’s current progress Click Here