Mastering ARM Templates (IaC): 
A Guide to Deploying Web Applications on Azure

Mastering ARM Templates (IaC): A Guide to Deploying Web Applications on Azure

An Azure Resource Manager (ARM) template is a JSON file that defines the infrastructure and configuration for your Azure resources. Creating an ARM template project involves defining resources such as virtual machines, storage accounts, and networking components in a reusable, declarative manner.

Scenario: Deploying a Simple Web Application

In this scenario, we will create an ARM template to deploy a simple web application infrastructure that includes:

  1. A Resource Group

  2. A Virtual Network with a subnet

  3. A Network Interface

  4. A Network Security Group (NSG)

  5. A Virtual Machine running a basic web server

  6. An Azure Storage Account

Step-by-Step Guide

Step 1: Create the Resource Group

Resource groups are containers that hold related resources for an Azure solution. Start by defining a resource group in your ARM template.

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "resources": [
        {
            "type": "Microsoft.Resources/resourceGroups",
            "apiVersion": "2023-01-01",
            "location": "[resourceGroup().location]",
            "name": "[parameters('resourceGroupName')]"
        }
    ]
}

Step 2: Define the Parameters Section

Parameters allow you to pass values into your template, making it reusable. Define parameters for the resource group name, virtual machine name, admin username, password, etc.

"parameters": {
    "resourceGroupName": {
        "type": "string",
        "defaultValue": "myResourceGroup",
        "metadata": {
            "description": "Name of the Resource Group"
        }
    },
    "vmName": {
        "type": "string",
        "defaultValue": "myVM",
        "metadata": {
            "description": "Name of the Virtual Machine"
        }
    },
    "adminUsername": {
        "type": "string",
        "defaultValue": "azureuser",
        "metadata": {
            "description": "Admin username for the Virtual Machine"
        }
    },
    "adminPassword": {
        "type": "securestring",
        "metadata": {
            "description": "Admin password for the Virtual Machine"
        }
    }
}

Step 3: Create the Virtual Network

Define a virtual network (VNet) and a subnet to host the virtual machine.

{
    "type": "Microsoft.Network/virtualNetworks",
    "apiVersion": "2023-05-01",
    "location": "[resourceGroup().location]",
    "name": "myVnet",
    "properties": {
        "addressSpace": {
            "addressPrefixes": [
                "10.0.0.0/16"
            ]
        },
        "subnets": [
            {
                "name": "mySubnet",
                "properties": {
                    "addressPrefix": "10.0.0.0/24"
                }
            }
        ]
    }
}

Step 4: Create a Network Interface

A network interface connects the virtual machine to the virtual network.

{
    "type": "Microsoft.Network/networkInterfaces",
    "apiVersion": "2023-05-01",
    "location": "[resourceGroup().location]",
    "name": "myNic",
    "properties": {
        "ipConfigurations": [
            {
                "name": "ipconfig1",
                "properties": {
                    "subnet": {
                        "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', 'myVnet', 'mySubnet')]"
                    },
                    "privateIPAllocationMethod": "Dynamic"
                }
            }
        ]
    },
    "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', 'myVnet')]"
    ]
}

Step 5: Create a Network Security Group

A Network Security Group (NSG) controls inbound and outbound traffic to the virtual machine.

{
    "type": "Microsoft.Network/networkSecurityGroups",
    "apiVersion": "2023-05-01",
    "location": "[resourceGroup().location]",
    "name": "myNSG",
    "properties": {
        "securityRules": [
            {
                "name": "allow-http",
                "properties": {
                    "priority": 100,
                    "protocol": "Tcp",
                    "access": "Allow",
                    "direction": "Inbound",
                    "sourceAddressPrefix": "*",
                    "sourcePortRange": "*",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "80"
                }
            }
        ]
    }
}

Step 6: Create the Virtual Machine

Define a virtual machine using the parameters and the network components defined earlier. This VM will run a basic web server.

{
    "type": "Microsoft.Compute/virtualMachines",
    "apiVersion": "2024-07-01",
    "location": "[resourceGroup().location]",
    "name": "[parameters('vmName')]",
    "properties": {
        "hardwareProfile": {
            "vmSize": "Standard_DS1_v2"
        },
        "osProfile": {
            "computerName": "[parameters('vmName')]",
            "adminUsername": "[parameters('adminUsername')]",
            "adminPassword": "[parameters('adminPassword')]"
        },
        "networkProfile": {
            "networkInterfaces": [
                {
                    "id": "[resourceId('Microsoft.Network/networkInterfaces', 'myNic')]"
                }
            ]
        },
        "storageProfile": {
            "imageReference": {
                "publisher": "Canonical",
                "offer": "UbuntuServer",
                "sku": "18.04-LTS",
                "version": "latest"
            },
            "osDisk": {
                "name": "[concat(parameters('vmName'), '-osdisk')]",
                "caching": "ReadWrite",
                "createOption": "FromImage",
                "managedDisk": {
                    "storageAccountType": "Standard_LRS"
                }
            }
        }
    },
    "dependsOn": [
        "[resourceId('Microsoft.Network/networkInterfaces', 'myNic')]"
    ]
}

Step 7: Create a Storage Account

A storage account is required for storing data such as VM diagnostic logs.

{
    "type": "Microsoft.Storage/storageAccounts",
    "apiVersion": "2023-01-01",
    "location": "[resourceGroup().location]",
    "name": "mystorageaccount",
    "sku": {
        "name": "Standard_LRS"
    },
    "kind": "StorageV2",
    "properties": {
        "accessTier": "Hot"
    }
}

Explanation:

  1. Parameters: The template defines parameters for resource group name, VM name, admin username, and admin password, allowing you to customize these values during deployment.

  2. Resources:

    • Virtual Network (myVnet): A virtual network with a single subnet.

    • Network Interface (myNic): Connects the VM to the virtual network.

    • Network Security Group (myNSG): Includes a security rule to allow HTTP traffic on port 80.

    • Virtual Machine (myVM): A Linux-based VM using Ubuntu, configured with the provided admin credentials and connected to the network interface.

    • Storage Account (mystorageaccount): Used for general storage purposes.

  3. Outputs: The template outputs the VM's resource ID after deployment, which can be useful for referencing the VM in subsequent operations or scripts.

This ARM template can be used to deploy the infrastructure by using Azure CLI or the Azure portal to initiate the deployment.

Step 8: Deploy the ARM Template

  1. Download the Template: Get the complete ARM Template azuredeploy.json from my gitHub repo https://github.com/blessador/webApplication-Arm-Templates

  2. Deploy Using Azure CLI:

A) Open the azuredeploy.json file you just downloaded in VS Code.

B) Login to Azure CLI

Click on Terminal -> New Terminal from your VSCode menu

C) Run the az login command

  1. You will be prompted in your browser to authenticate in order to run Azure CLI command from VS Code.

  2. Create the resource group that will contain all the Azure resources we want to deploy by running the command az group create --name myResourceGroup --location easus

  3. Next we need to run the following command as shown below to deploy all the resources as defined in azuredeploy.json file.

     az deployment group create --resource-group myResourceGroup --template-file azuredeploy.json --parameters adminPassword=<YourPassword>
    
  4. Verify Deployment: Check the Azure portal to verify that all the resources were deployed successfully.

    a. Azure Portal : As you can see all the resource have been deployed

    b. VS Code Terminal : Run this command to display the deployed resources

     az resource list --resource-group myResourceGroup --output table
    

Final Thought

You have created an ARM template project that deploys a simple web application infrastructure in Azure. This template can be extended or modified to include more resources and configurations as needed. ARM templates are powerful tools for automating the deployment and management of Azure resources, making them essential for infrastructure as code (IaC) practices.

Thank you

:Valentine Stephen