HSR Sector 6 · Bangalore +91 96110 27980 Mon–Sat · 09:30–20:30
Chapter 9 of 20 — Azure Cloud Fundamentals
intermediate Chapter 9 of 20

Azure ARM Templates & Bicep — Infrastructure as Code Guide

By Vikas Swami, CCIE #22239 | Updated Mar 2026 | Free Course

What is Infrastructure as Code — Why ARM Templates Matter

Infrastructure as Code (IaC) has revolutionized the way organizations manage and provision cloud resources by enabling automated, repeatable, and version-controlled infrastructure deployments. Instead of manual configurations, developers and DevOps teams write code—declarative or imperative—that defines the desired state of infrastructure components. This approach reduces errors, accelerates deployment times, and enhances consistency across environments.

Within the Azure ecosystem, Azure ARM templates (Azure Resource Manager templates) serve as a foundational IaC tool. These JSON-based files describe Azure resources and their configurations, allowing for automated deployment and management. By defining resources such as virtual machines, storage accounts, and networking components in ARM templates, teams can deploy complex environments reliably and repeatedly.

Why do ARM templates matter? They enable true Infrastructure as Code by providing a declarative syntax that Azure understands directly. They support idempotent deployments, meaning re-running a template ensures the environment remains consistent without duplicating resources. Additionally, ARM templates integrate seamlessly with Azure DevOps pipelines, Git repositories, and other automation tools, making them essential for modern cloud operations. Organizations leveraging ARM templates report faster provisioning, reduced manual errors, and improved compliance, making it a vital skill for cloud engineers. For those looking to deepen their understanding, Networkers Home offers comprehensive courses on Azure infrastructure as code.

ARM Template Structure — Schema, Parameters, Variables & Resources

An ARM template’s structure is designed to be modular and flexible, enabling users to define complex cloud environments in a clear, organized manner. Understanding its core components is critical for effective template development:

  • Schema: Specifies the version of the ARM template JSON schema, which validates the template structure. Typically, it points to the latest supported schema, e.g., https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#.
  • Parameters: Allow input values during deployment, making templates reusable across different environments or configurations. For example, VM size or storage account name can be parameterized.
  • Variables: Store values computed within the template, reducing repetition and simplifying complex expressions. These are set once and reused throughout the template.
  • Resources: The core of the template, defining Azure resources like VMs, storage accounts, networks, and more. Each resource has properties specifying its configuration.
  • Outputs: Return values post-deployment, such as resource IDs or connection strings, for further automation or reference.

Here is a simplified snippet illustrating these components:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "parameters": {
    "storageAccountName": {
      "type": "string"
    }
  },
  "variables": {
    "location": "eastus"
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2019-06-01",
      "name": "[parameters('storageAccountName')]",
      "location": "[variables('location')]",
      "kind": "StorageV2",
      "sku": {
        "name": "Standard_LRS"
      }
    }
  ],
  "outputs": {
    "storageAccountId": {
      "type": "string",
      "value": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
    }
  }
}

This example demonstrates how parameters, variables, and resource definitions work together to create a deployable Azure environment. Mastery of these components is vital for developing scalable and maintainable ARM templates, a skill emphasized in the Networkers Home Azure course.

Writing Your First ARM Template — Deploying a Storage Account

Creating your first ARM template to deploy an Azure storage account provides a practical introduction to infrastructure as code. This process involves defining a JSON template with minimal components, deploying it via Azure CLI, and verifying the resource creation.

Step 1: Define the Template

Begin with a simple template that includes schema, parameters, variables, and resources. For example:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageAccountName": {
      "type": "string",
      "metadata": {
        "description": "Unique name for the storage account"
      }
    }
  },
  "variables": {
    "location": "eastus"
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2019-06-01",
      "name": "[parameters('storageAccountName')]",
      "location": "[variables('location')]",
      "kind": "StorageV2",
      "sku": {
        "name": "Standard_LRS"
      }
    }
  ],
  "outputs": {
    "storageAccountResourceId": {
      "type": "string",
      "value": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
    }
  }
}

Step 2: Deploy Using Azure CLI

Use the Azure CLI command to deploy the template:

az deployment group create --resource-group MyResourceGroup --template-file storage-account-template.json --parameters storageAccountName=mystorageaccount123

Replace MyResourceGroup with your resource group name and ensure the template file path is correct.

Step 3: Verify Deployment

Check the deployment status:

az resource show --resource-group MyResourceGroup --name mystorageaccount123 --resource-type Microsoft.Storage/storageAccounts

If successful, the storage account appears in the Azure portal, confirming the ARM template deployment. This hands-on approach solidifies understanding of the core concepts involved in Azure infrastructure as code and is covered extensively in Networkers Home Blog.

Template Functions — String, Numeric, Array & Resource Functions

ARM templates provide an extensive set of functions that enable dynamic and flexible deployments. These functions process data, compute values, and manipulate resources during template deployment, making templates more powerful and adaptable.

String Functions

  • concat(): Combines multiple strings. Example: [concat('storage', 'account')] outputs storageaccount.
  • substring(): Extracts a portion of a string. Example: [substring('HelloWorld', 0, 5)] results in Hello.
  • length(): Returns string length. Example: [length('Azure')] yields 5.

Numeric Functions

  • add(): Adds numbers. Example: [add(5, 10)] outputs 15.
  • mul(): Multiplies numbers. Example: [mul(4, 5)] yields 20.
  • div(): Divides numbers. Example: [div(20, 4)] results in 5.

Array Functions

  • length(): Gets array length. Example: [length([1,2,3])] returns 3.
  • join(): Concatenates array elements into a string. Example: [join(['a','b'],'-')] outputs a-b.
  • contains(): Checks if an array contains a value. Example: [contains([1,2,3], 2)] returns true.

Resource Functions

  • resourceId(): Generates resource IDs. Example: [resourceId('Microsoft.Storage/storageAccounts', 'mystorage')].
  • reference(): Retrieves runtime information about a resource.

Mastering these functions enhances the dynamic capabilities of your ARM templates, enabling conditional deployments, parameter transformations, and resource referencing, essential skills for Azure infrastructure as code. For more examples and practical tips, visit the Networkers Home Blog.

Linked and Nested Templates — Modular Deployments

As infrastructure complexity grows, managing large ARM templates can become challenging. To address this, Azure supports linked and nested templates, allowing modular, reusable, and maintainable deployments.

Nested Templates

Nested templates are embedded within a parent template, enabling logical grouping of resources. They are useful for deploying repeating resource patterns or encapsulating specific infrastructure components.

Example: A parent template deploys a virtual network and calls a nested template to set up subnets:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "name": "nestedSubnetDeployment",
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "resources": [
            {
              "type": "Microsoft.Network/virtualNetworks/subnets",
              "apiVersion": "2020-11-01",
              "name": "[concat('myVnet/subnet1')]",
              "properties": {
                "addressPrefix": "10.0.1.0/24"
              }
            }
          ]
        }
      }
    }
  ]
}

Linked Templates

Linked templates reside as separate files and are called at deployment time, promoting reuse and separation of concerns. Using the linkedTemplate resource type, you can invoke external templates:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2019-10-01",
      "name": "linkedDeployment",
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "https://raw.githubusercontent.com/yourrepo/azure-templates/subnet.json"
        },
        "parameters": {
          "subnetName": {
            "value": "subnetA"
          }
        }
      }
    }
  ]
}

Utilizing linked and nested templates facilitates modular deployments, improves maintainability, and aligns with enterprise-scale Azure infrastructure as code practices. These techniques are integral to managing complex environments efficiently, as highlighted in the Networkers Home Blog.

Azure Bicep — Simplified IaC Syntax for ARM

While ARM templates are powerful, their JSON syntax can become verbose and difficult to manage for large deployments. Azure Bicep introduces a domain-specific language (DSL) designed to simplify Azure infrastructure as code, making it more accessible and maintainable.

Bicep compiles down to ARM JSON templates, ensuring full compatibility with Azure Resource Manager. Its syntax is concise, declarative, and supports features like modules, parameters, and outputs, similar to other modern IaC tools like Terraform.

Key Features of Azure Bicep

  • Simplified syntax: Less verbose than JSON ARM templates, enabling faster development.
  • Modularity: Supports modules for reusable template components.
  • IntelliSense and tooling integration: Compatible with Visual Studio Code, providing syntax highlighting and validation.
  • Seamless integration: Bicep files compile into ARM JSON templates, deployable via Azure CLI or PowerShell.

Example: Deploying a VM with Bicep

param vmName string = 'myVM'
param adminUsername string
param adminPassword securestring

resource vm 'Microsoft.Compute/virtualMachines@2021-07-01' = {
  name: vmName
  location: 'eastus'
  properties: {
    hardwareProfile: {
      vmSize: 'Standard_DS1_v2'
    }
    osProfile: {
      computerName: vmName
      adminUsername: adminUsername
      adminPassword: adminPassword
    }
    storageProfile: {
      imageReference: {
        publisher: 'MicrosoftWindowsServer'
        offer: 'WindowsServer'
        sku: '2019-Datacenter'
        version: 'latest'
      }
      osDisk: {
        createOption: 'FromImage'
      }
    }
    networkProfile: {
      networkInterfaces: [
        {
          id: resourceId('Microsoft.Network/networkInterfaces', '${vmName}NIC')
        }
      ]
    }
  }
}

This concise syntax significantly reduces complexity, making deployments faster and easier to maintain. For those interested in adopting Azure Bicep, Networkers Home offers courses on mastering Bicep and modern IaC practices.

Template Specs & Deployment Stacks — Enterprise-Scale IaC

For organizations managing multiple deployments and aiming for consistency, Azure offers Template Specs. These are versioned, reusable template repositories stored in Azure, enabling central governance and streamlined deployment workflows.

Template Specs facilitate enterprise-scale infrastructure as code by providing:

  • Version control: Manage multiple iterations of templates with clear revision history.
  • Governance: Enforce standards and compliance across deployments.
  • Reuse: Share templates across teams and projects without duplication.

Deployment stacks extend this concept by organizing multiple related resources into a single, manageable unit. Using deployment stacks, organizations can orchestrate complex environments with dependencies, using nested templates or modules, ensuring consistency and automation at scale.

For example, deploying a full environment comprising virtual networks, security groups, VMs, and databases can be encapsulated within a deployment stack, simplifying operations and change management. These enterprise-grade practices are critical for large-scale Azure implementations and are discussed extensively in the Networkers Home Blog.

ARM vs Terraform vs Bicep — Choosing the Right IaC Tool

When selecting an Infrastructure as Code tool for Azure, organizations often compare ARM templates, Terraform, and Bicep. Each has unique strengths and considerations:

Feature ARM Templates Terraform Azure Bicep
Language JSON HCL (HashiCorp Configuration Language) Domain-specific language (Bicep syntax)
Azure Native Yes No (requires providers) Yes (compiles to ARM)
Ease of Use Moderate (verbose JSON) High (more readable syntax) High (simplified syntax)
Modularity Supported via nested templates Supported via modules Supported via modules
Community & Ecosystem Large (native to Azure) Large (multi-cloud) Growing (Azure-specific)
Deployment Integration Azure CLI, PowerShell, ARM Terraform CLI, AzureRM provider Azure CLI, PowerShell

Choosing between these tools depends on project requirements, team skillset, and organizational standards. ARM templates are ideal for Azure-native deployments; Terraform offers multi-cloud flexibility; Bicep provides a modern, simplified approach to Azure-specific infrastructure as code. For comprehensive training, visit Networkers Home, which offers courses tailored to these technologies.

Key Takeaways

  • Azure ARM templates are JSON-based declarative files fundamental to Azure infrastructure as code.
  • The structure of ARM templates includes schema, parameters, variables, resources, and outputs, enabling flexible and reusable deployments.
  • Deploying a storage account via ARM template involves defining the resource and executing CLI commands for automation.
  • Template functions such as string, numeric, array, and resource functions enhance dynamic template capabilities.
  • Linked and nested templates facilitate modular, maintainable, and scalable Azure deployments.
  • Azure Bicep simplifies ARM template syntax, making infrastructure as code more accessible and manageable.
  • Template Specs and deployment stacks support enterprise-scale automation and governance.

Frequently Asked Questions

What are the advantages of using Azure ARM templates over manual deployment?

Azure ARM templates automate resource provisioning, ensuring consistent and repeatable deployments. They reduce human error, enable version control, and facilitate rapid environment setup. Automating deployments with ARM templates also improves scalability and compliance, especially in complex infrastructures. Additionally, ARM templates seamlessly integrate with Azure DevOps pipelines, enabling continuous integration and deployment workflows. For professionals seeking to master these techniques, Networkers Home provides specialized training in Azure automation and infrastructure as code.

Can I integrate ARM templates with other automation tools like Terraform or Bicep?

Yes, ARM templates can be integrated with tools like Terraform and Bicep to leverage their respective advantages. Bicep, a domain-specific language, compiles directly into ARM JSON templates, offering a more concise syntax while maintaining compatibility. Terraform, although multi-cloud, supports deploying Azure resources through the AzureRM provider, which can invoke ARM templates as part of its deployment process. This interoperability allows teams to choose the best tool for their needs—using ARM templates for direct Azure-native deployment, Bicep for simplified syntax, and Terraform for multi-cloud orchestration. This flexibility is key to modern infrastructure management, as highlighted by Azure experts at Networkers Home Blog.

What is the future of Azure infrastructure as code with tools like ARM templates and Bicep?

The future of Azure infrastructure as code is leaning towards more streamlined, modular, and developer-friendly tools. Bicep is rapidly gaining adoption due to its simplified syntax, and Microsoft continues to enhance its capabilities, including better tooling, integration, and support for complex scenarios. ARM templates remain vital for deep Azure integrations, but Bicep offers a more approachable alternative for most users. Additionally, enterprise features like Template Specs enable scalable governance. The trend indicates a move towards unified, declarative, and automation-centric workflows, empowering teams to deploy faster and more reliably. For ongoing learning and updates, stay connected with Networkers Home Blog.

Ready to Master Azure Cloud Fundamentals?

Join 45,000+ students at Networkers Home. CCIE-certified trainers, 24x7 real lab access, and 100% placement support.

Explore Course