What we learned while evaluating Infrastructure as Code (IaC) frameworks for Microsoft Azure

Ganesan Senthilvel
Ganesan SenthilvelSenior Engineering Manager
Contents

The Trimble Maps engineering team recently added Microsoft Azure to our cloud computing providers. As part of the onboarding process, we needed to select an Infrastructure as Code (IaC) framework to manage this newly available cloud infrastructure through code, instead of through manual processes.

Our Top 3 choices for IaC were: Bicep, Pulumi and Terraform.

Popular IaC frameworks

Some background on these frameworks:

  • Bicep is Microsoft’s own domain-specific language, recently released as the next generation of JSON-based legacy framework ARM (Azure Resource Manager).
  • Bicep and Terraform are open-source tools and cloud agnostic. Terraform has decade long industry journey and a wider community than others.
  • As a unique feature, Pulumi allows a DevOps engineer to write the Infrastructure as Code using their favorite high-level languages such as C#, Python, or Go.

Our comparison

As part of the selection process, we reviewed and tested each framework and rated them based on the categories below. (Three stars was our top rating for any individual category.)

Bicep Pulumi Terraform
Creator Microsoft Pulumi HashiCorp
Release Date 2021 2018 2014
Simplicity ★★★ ★★
Domain Specific Language ★★ n/a ★★★
High Level Language n/a ★★ n/a
Multi-Cloud n/a ★★ ★★
Community ★★ ★★★
Custom Workflow ★★
Ecosystem ★★★ ★★ ★★
Deployment ★★ ★★★ ★★★
Longevity ★★ ★★★
Coding Layout Code-A Code-B Code-C
Execution Layout az deployment group
create -g G -f.F.bicep
pulumi up terraform apply
Store state of managed infrastructure n/a By default SaaS offering By default local terraform.tfstate
  • n/a - Not available at this time

Code-A

/*
 * Azure Resource Manager (ARM) region declare
 */
@description('Specifies the region for resources.')
param v map Location string = 'eastus'
/*
 * Azure resource name declare
 */
@description('Specifies the name of the resource.')
param vmapsName string = 'vmapsstore1'

/*
 * Azure storage declaration with system object
 * with naming, kind and other parameters
 */
 resource vmapsStore 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: vmapsName
  location: vmas Location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
  properties: {
    accessTier: 'Hot'
    supportsHttpsTrafficOnly: true
  }
}

Code-B

/*
 * .NET namespace using directives
 */
using Pulumi;
using Pulumi.AzureNative.Resources;
using Pulumi.AzureNative.Storage;
using Pulumi.AzureNative.Storage.Inputs;
using System.Collections.Generic;

/*
 * Pulumi deployment async method
 */
return await Pulumi.Deployment.RunAsync(() =>
{
    var config = new Pulumi.Config();

	/*
	 * Instantiate Azure storage resource
	 */
    var storageAccount = new StorageAccount(config.Get("storageAccountName"), new StorageAccountArgs
    {
        ResourceGroupName = config.Get("resourceGroupName"),
        Sku = new SkuArgs
        {
            Name = SkuName.Standard_LRS
        },
        Kind = Kind.StorageV2
    });

	/*
	 * Export storage ID of created resource
	 */
    return new Dictionary<string, object?>
    {
        ["storageId"] = storageAccount.Id
    };
});

Code-C

#
# Terraform declaration
#
terraform {
  required_version = ">= 1.1.7"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">= 3.27.0"
    }
  }
}

#
# Terraform Azure provider definition
#
provider "azurerm" {
  features {}
}

#
# Getting user input for storage name
# and resource group name
#
variable "name" {
  type = string
}
variable "resource_group_name" {
  type = string
}

#
# Terraform resource section definition
# with dynamic name, region, account info
#
resource "azurerm_storage_account" "storage" {
  name                     = var.name
  resource_group_name      = var.resource_group_name
  location                 = "eastus"
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

#
# Terraform output storage ID
# after successful execution
#
output "storageId" {
  value = azurerm_storage_account.storage.id
}

Advantages of Terraform

Based on our technical analysis of the above IaC frameworks, Terraform came out on top. Here are the Top 5 reasons why:

  1. Declarative - easy development

We preferred an IaC tool for declarative programming over imperative. It allows configuration code authors to specify their desired program end state, leaving the intricate tasks to the compiler’s capable hands.

Through intricate logic, the compiler determines the most efficient route to achieving the program’s objectives. Terraform’s declarative programming approach eliminates the need for users to grapple with complex programming logic when defining resources, as the tool autonomously optimizes resource allocation and logic deployment.

Terraform’s declarative programming style simplifies resource definition for users, sparing them from delving into intricate programming logic. The tool autonomously orchestrates resource placement and logic deployment for optimal efficiency.

  1. Collaboration - team support

If development efforts involve collaborating with multiple teams, maintaining uniform configurations becomes paramount to ensuring a cohesive development process. Terraform addresses this need by offering cloud and on-premises solutions that foster consistency in workflow among teams.

Moreover, Terraform provides a version control system (VCS) for effectively committing and managing configuration files within its cloud infrastructure, further enhancing the development experience.

  1. Automated Changes - easy maintenance

Terraform’s infrastructure utilizes declarative configuration files, eliminating the need for labor-intensive, time-consuming, step-by-step resource setup. Instead, the Infrastructure as Code (IaC) tool seamlessly manages the intricate logic beneath the surface, streamlining the process.

  1. Longevity with community - broad support

Terraform has garnered a substantial following over the course of its decade of existence, drawing in both experienced developers and newcomers. This community has evolved into a comprehensive ecosystem, housing numerous third-party tools and educational resources aimed at guiding newcomers towards mastering the industry’s best practices.

  1. Remote State - conflict resolution

Terraform has two types of store for Terraform state, namely local and remote.

  • Local mode persists the state on the local file system, where the Terraform command is executed.
  • But, remote state allows you to persist the details remotely, such as in an S3 bucket or any database.

It is possible to share the remote state for providing helpful capabilities such as preventing conflicts and inconsistencies.

Other factors

While Terraform rose to the top in our evaluation, it also had a few advantages over the other frameworks from the start:

  • We have prior experience with Terraform for the last few years in the product engineering cycle.
  • Recent feedback from the Microsoft expert team suggested that we select Terraform.

Share this article:

You May Also Like

Experimenting With LangChain AI

| By Ganesan Senthilvel

My recent experiences working with LangChain technology.

New Frameworks Provide New Ways to Create Cross Platform, Cross Mobile Applications

| By Ganesan Senthilvel

My recent experiences working with Flutter and Capacitor.

How to Help Guide Developers Through Your API Documentation

| By Chris Johnson

Tips on how to go beyond just documenting API endpoints and parameters.