Azure – Deploy VM using ARM templates

Posted: August 20, 2020 in Azure

Azure Resource Manager templates are JavaScript Object Notation (JSON) files that define the infrastructure and configuration for your resources.

This template creates one Windows Server VM with one data disk, one NSG associated with VNET subnet and allows RDP traffic from anywhere.

Then it creates Storage account for storing boot diagnostic data and AzurePerformanceDiagnostics extension.

Parameters file (VM credentials and DNS suffix)

param.json:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "adminUsername": {
        "value": "GEN-UNIQUE"
      },
      "adminPassword": {
        "value": "Password1234"
      },
      "dnsLabelPrefix": {
        "value": "gen-unique124"
      }
    }
  }

template.json

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "performanceScenario": {
        "type": "string",
        "defaultValue": "basic"
      },
      "srNumber": {
        "type": "string",
        "defaultValue": ""
      },
      "traceDurationInSeconds": {
        "type": "int",
      "defaultValue": 300
      },
      "perfCounterTrace": {
        "type": "string",
        "defaultValue": "p"
      },
      "networkTrace": {
        "type": "string",
        "defaultValue": ""
      },
      "xperfTrace": {
        "type": "string",
        "defaultValue": ""
      },
      "storPortTrace": {
        "type": "string",
        "defaultValue": ""
      },
      "requestTimeUtc": {
        "type": "string",
        "defaultValue": "10/2/2017 11:06:00 PM"
      },		
      "adminUsername": {
        "type": "string",
        "metadata": {
          "description": "Username for the Virtual Machine."
        }
      },
      "adminPassword": {
        "type": "securestring",
        "metadata": {
          "description": "Password for the Virtual Machine."
        }
      },
      "dnsLabelPrefix": {
        "type": "string",
        "metadata": {
          "description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
        }
      },
      "windowsOSVersion": {
        "type": "string",
        "defaultValue": "2016-Datacenter",
        "allowedValues": [
          "2008-R2-SP1",
          "2012-Datacenter",
          "2012-R2-Datacenter",
          "2016-Nano-Server",
          "2016-Datacenter-with-Containers",
          "2016-Datacenter",
          "2019-Datacenter"
        ],
        "metadata": {
          "description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version."
        }
      },
      "vmSize": {
        "type": "string",
        "defaultValue": "Standard_B2ms",
        "metadata": {
          "description": "Size of the virtual machine."
        }
      },
      "location": {
        "type": "string",
        "defaultValue": "[resourceGroup().location]",
        "metadata": {
          "description": "Location for all resources."
        }
      }
    },
    "variables": {
      "storageAccountName": "[concat(uniquestring(resourceGroup().id), 'sawinvm')]",
      "storageAccountId": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
      "nicName": "myVMNic",
      "addressPrefix": "10.0.0.0/16",
      "subnetName": "Subnet",
      "subnetPrefix": "10.0.0.0/24",
      "publicIPAddressName": "myPublicIP",
      "vmName": "SimpleWinVM",
      "virtualNetworkName": "MyVNET",
      "subnetRef": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworkName'), variables('subnetName'))]",
      "networkSecurityGroupName": "default-NSG"
    },
    "resources": [
      {
        "type": "Microsoft.Storage/storageAccounts",
        "apiVersion": "2018-11-01",
        "name": "[variables('storageAccountName')]",
        "location": "[parameters('location')]",
        "sku": {
          "name": "Standard_LRS"
        },
        "kind": "Storage",
        "properties": {}
      },
      {
        "type": "Microsoft.Network/publicIPAddresses",
        "apiVersion": "2018-11-01",
        "name": "[variables('publicIPAddressName')]",
        "location": "[parameters('location')]",
        "properties": {
          "publicIPAllocationMethod": "Dynamic",
          "dnsSettings": {
            "domainNameLabel": "[parameters('dnsLabelPrefix')]"
          }
        }
      },
      {
        "comments":  "Default Network Security Group for template",
        "type":  "Microsoft.Network/networkSecurityGroups",
        "apiVersion":  "2019-08-01",
        "name":  "[variables('networkSecurityGroupName')]",
        "location":  "[parameters('location')]",
        "properties": {
          "securityRules": [
            {
              "name":  "default-allow-3389",
              "properties": {
                "priority":  1000,
                "access":  "Allow",
                "direction":  "Inbound",
                "destinationPortRange":  "3389",
                "protocol":  "Tcp",
                "sourcePortRange":  "*",
                "sourceAddressPrefix":  "*",
                "destinationAddressPrefix":  "*"
              }
            }
          ]
        }
      },
      {
        "type": "Microsoft.Network/virtualNetworks",
        "apiVersion": "2018-11-01",
        "name": "[variables('virtualNetworkName')]",
        "location": "[parameters('location')]",
        "dependsOn": [
          "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
        ],
        "properties": {
          "addressSpace": {
            "addressPrefixes": [
              "[variables('addressPrefix')]"
            ]
          },
          "subnets": [
            {
              "name": "[variables('subnetName')]",
              "properties": {
                "addressPrefix": "[variables('subnetPrefix')]",
                "networkSecurityGroup": {
                  "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]"
                }
              }
            }
          ]
        }
      },
      {
        "type": "Microsoft.Network/networkInterfaces",
        "apiVersion": "2018-11-01",
        "name": "[variables('nicName')]",
        "location": "[parameters('location')]",
        "dependsOn": [
          "[resourceId('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
          "[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
        ],
        "properties": {
          "ipConfigurations": [
            {
              "name": "ipconfig1",
              "properties": {
                "privateIPAllocationMethod": "Dynamic",
                "publicIPAddress": {
                  "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]"
                },
                "subnet": {
                  "id": "[variables('subnetRef')]"
                }
              }
            }
          ]
        }
      },
      {
        "type": "Microsoft.Compute/virtualMachines",
        "apiVersion": "2018-10-01",
        "name": "[variables('vmName')]",
        "location": "[parameters('location')]",
        "dependsOn": [
          "[resourceId('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
          "[resourceId('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
        ],
        "properties": {
          "hardwareProfile": {
            "vmSize": "[parameters('vmSize')]"
          },
          "osProfile": {
            "computerName": "[variables('vmName')]",
            "adminUsername": "[parameters('adminUsername')]",
            "adminPassword": "[parameters('adminPassword')]"
          },
          "storageProfile": {
            "imageReference": {
              "publisher": "MicrosoftWindowsServer",
              "offer": "WindowsServer",
              "sku": "[parameters('windowsOSVersion')]",
              "version": "latest"
            },
            "osDisk": {
              "createOption": "FromImage"
            },
            "dataDisks": [
              {
                "diskSizeGB": 1023,
                "lun": 0,
                "createOption": "Empty"
              }
            ]
          },
          "networkProfile": {
            "networkInterfaces": [
              {
                "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]"
              }
            ]
          },
          "diagnosticsProfile": {
            "bootDiagnostics": {
              "enabled": true,
              "storageUri": "[reference(resourceId('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))).primaryEndpoints.blob]"
            }
          }
        }
      },
      {
        "name": "[concat(variables('vmName'),'/AzurePerformanceDiagnostics')]",
        "type": "Microsoft.Compute/virtualMachines/extensions",
        "location":  "[resourceGroup().location]",
        "apiVersion": "2015-06-15",
        "properties": {
          "publisher": "Microsoft.Azure.Performance.Diagnostics",
          "type": "AzurePerformanceDiagnostics",
          "typeHandlerVersion": "1.0",
          "autoUpgradeMinorVersion": true,
          "settings": {
              "storageAccountName": "[variables('storageAccountName')]",
              "performanceScenario": "[parameters('performanceScenario')]",
              "traceDurationInSeconds": "[parameters('traceDurationInSeconds')]",
              "perfCounterTrace": "[parameters('perfCounterTrace')]",
              "networkTrace": "[parameters('networkTrace')]",
              "xperfTrace": "[parameters('xperfTrace')]",
              "storPortTrace": "[parameters('storPortTrace')]",
              "srNumber": "[parameters('srNumber')]",
              "requestTimeUtc":  "[parameters('requestTimeUtc')]",
              "resourceId": "[resourceId('Microsoft.Compute/virtualMachines', variables('vmName'))]"
          },
          "protectedSettings": {
              "storageAccountKey": "[listKeys(variables('storageAccountId'), '2019-04-01').keys[0].value]"
          }
        },
        "dependsOn": [
           "[resourceId('Microsoft.Compute/virtualMachines/', variables('vmName'))]",
           "[resourceId('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]"
        ]
    }
    ],
    "outputs": {
      "hostname": {
        "type": "string",
        "value": "[reference(variables('publicIPAddressName')).dnsSettings.fqdn]"
      }
    }
}

Login to Azure:

Connect-AzureRmAccount

Create resource group for resources

New-AzureRmResourceGroup -Name rg -Location 'west europe'

Deploy resources using ARM template files

New-AzureRmResourceGroupDeployment -ResourceGroupName 'rg' -TemplateFile 'template.json' -TemplateParameterFile 'param.json'

Running VM post-provisioning script

If we need to perform some configuration after VM is deployed, we need to use custom-script extensions.

First we need to upload script to storage account.This is simple script for installing IIS-iis.ps1

Install-Windowsfeature -name Web-Server -IncludeManagementTools
Set-Location -Path c:\inetpub\wwwroot
Add-Content iisstart.htm `
  "<H1><center>Welcome to my Web Server $env:COMPUTERNAME, Azure Rocks!</center></H1>"

Then,we need to add extension block to JSON file

   {
      "type": "Microsoft.Compute/virtualMachines/extensions",
      "apiVersion": "2019-07-01",
      "name": "[concat(variables('vmName'), '/CustomScriptExtension')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
          "[resourceId('Microsoft.Compute/virtualMachines', variables('vmName'))]"
      ],
      "properties": {
          "autoUpgradeMinorVersion": true,
          "publisher": "Microsoft.Compute",
          "type": "CustomScriptExtension",
          "typeHandlerVersion": "1.9",
          "settings": {
              "fileUris": [
                  "https://p27zkcgb2etnksawinvm.blob.core.windows.net/ddd/iis.ps1?sp=r&se=2020-08-21T15:09:38Z&sv=2019-12-12&sr=b&sig=oP4U77z4i9UdHUoL1yPSnKSzO%2BuVAQugzbqjp4j%2Frpw%3D"
              ],
              "commandToExecute": "[concat('PowerShell -ExecutionPolicy Unrestricted -File \"' , 'iis.ps1')]"
          },
          "protectedSettings": {}
      }
  }
Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s