Onboarding : Azure Infrastructure deployment


  • Understand ARM template
  • Implement Infrastructure as code
  • Deploy ARM Template via Powershell
  • Implement and deploy Infrastructure via Terraform

Available provisioning solutions

Discover the services and tools available to automate the deployment and configuration of your Azure infrastructure

Scenario: A clothing manufacturer that’s moving several product design applications to Azure virtual machines. The company needs to scale out to many virtual machines now and in the future. Their current manual process is time consuming and error prone. They want to automate the scale-out process to improve operational abilities. They’re unsure about the tools that are available on Azure to provision compute resources, and where each fits into the overall provisioning process.

Available provisioing solutions are:

  • Custome scripts (VMs)
  • Desired State Configuration Extensions (VMs)
  • Chef Server
  • Terraform (all resources)
  • Azure Automation State Configuration
  • Azure Resource Manager templates (all resources)
Custome scripts (VMs)
  • custom script extension downloads and runs scripts on vms
  • useful for post deployment configuration, software installation
  • this script can be powershell script on local file server, Github, azure storage, other locations that are accessible to vm
  • available via powershell, cli, ARM template
    "apiVersion": "2019-06-01",
    "type": "Microsoft.Compute/virtualMachines/extensions",
    "name": "[concat(variables('virtual machineName'),'/', 'InstallWebServer')]",
    "location": "[parameters('location')]",
    "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/',variables('virtual machineName'))]"
    "properties": {
        "publisher": "Microsoft.Compute",
        "type": "CustomScriptExtension",
        "typeHandlerVersion": "1.7",
        "settings": {
            "fileUris": [
            "commandToExecute": "powershell.exe -ExecutionPolicy Unrestricted -File your-script-file.ps1"

Note: Take care if your configuration or management task requires a restart. A custom script extension won’t continue after a restart.

Desired State Configuration Extensions (VMs)
  • DSC extensions are for more complex configuration, installation
  • configuration for state can be located in blob storage, internal file storage
  • DSC can reboot, and continue the execution after reboots are completed
	"type": "Microsoft.Compute/virtualMachines/extensions",
	"name": "Microsoft.Powershell.DSC",
	"apiVersion": "2018-06-30",
	"location": "your-region",
	"dependsOn": [
		"[concat('Microsoft.Compute/virtualMachines/', parameters('virtual machineName'))]"
	"properties": {
		"publisher": "Microsoft.Powershell",
		"type": "DSC",
		"typeHandlerVersion": "2.77",
		"autoUpgradeMinorVersion": true,
		"settings": {
			"configuration": {
				"url": "https://demo.blob.core.windows.net/iisinstall.zip",
				"script": "IisInstall.ps1",
				"function": "IISInstall"
		"protectedSettings": {
			"configurationUrlSasToken": "odLPL/U1p9lvcnp..."
Chef Automate Server
  • chef server handels 10,000 node/machine at a time
  • works on-prem and cloud
  • it can be hosted for you and works as a service
  • Use Chef’s knife tool to deploy virtual machines and simultaneously apply recipes to them. You install the knife tool on your admin workstation, which is the machine where you create policies and execute commands. Then run your knife commands from your admin workstation.
# The following example shows how a knife command can be used to create a virtual machine on Azure. The command
# simultaneously applies a recipe that installs a web server on the machine.

knife azurerm server create `
    --azure-resource-group-name rg-chefdeployment `
    --azure-storage-account store `
    --azure-vm-name chefvm `
    --azure-vm-size 'Standard_DS2_v2' `
    --azure-service-location 'eastus' `
    --azure-image-reference-offer 'WindowsServer' `
    --azure-image-reference-publisher 'MicrosoftWindowsServer' `
    --azure-image-reference-sku '2016-Datacenter' `
    --azure-image-reference-version 'latest' `
    -x myuser `
    -P yourPassword `
    --tcp-endpoints '80,3389' `
    --chef-daemon-interval 1 `
    -r "recipe[webserver]"

You can also use the Chef extension to apply recipes to the target machines. The following example defines a Chef extension for a virtual machine in an Azure Resource Manager template. It points to a Chef server by using the chef_server_url property. It points to a recipe to run on the virtual machine to put it in the desired state.

  "type": "Microsoft.Compute/virtualMachines/extensions",
  "name": "[concat(variables('virtual machineName'),'/', variables('virtual machineExtensionName'))]",
  "apiVersion": "2015-05-01-preview",
  "location": "[parameters('location')]",
  "dependsOn": [
    "[concat('Microsoft.Compute/virtualMachines/', variables('virtual machineName'))]"
  "properties": {
    "publisher": "Chef.Bootstrap.WindowsAzure",
    "type": "LinuxChefClient",
    "typeHandlerVersion": "1210.12",
    "settings": {
      "bootstrap_options": {
        "chef_node_name": "chef_node_name",
        "chef_server_url": "chef_server_url",
        "validation_client_name": "validation_client_name"
      "runlist": "recipe[your-recipe]",
      "validation_key_format": "validation_key_format",
      "chef_service_interval": "chef_service_interval",
      "bootstrap_version": "bootstrap_version",
      "bootstrap_channel": "bootstrap_channel",
      "daemon": "service"
    "protectedSettings": {
      "validation_key": "validation_key",
      "secret": "secret"

A recipe might look like the one that follows. The recipe installs an IIS web server.

#install IIS on the node.
powershell_script 'Install IIS' do
     action :run
     code 'add-windowsfeature Web-Server'

service 'w3svc' do
     action [ :enable, :start ]
  • Hashicorp Configuration Language (HCL)
# Configure the Microsoft Azure as a provider
provider "azurerm" {
    subscription_id = "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    client_id       = "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    client_secret   = "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    tenant_id       = "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# Create a resource group
resource "azurerm_resource_group" "myterraformgroup" {
    name     = "myResourceGroup"
    location = "eastus"

    tags = {
        environment = "Terraform Demo"
# Create the virtual machine
resource "azurerm_virtual_machine" "myterraformvirtual machine" {
    name                  = "myvirtual machine"
    location              = "eastus"
    resource_group_name   = "${azurerm_resource_group.myterraformgroup.name}"
    network_interface_ids = ["${azurerm_network_interface.myterraformnic.id}"]
    virtual machine_size               = "Standard_DS1_v2"

    storage_os_disk {
        name              = "myOsDisk"
        caching           = "ReadWrite"
        create_option     = "FromImage"
        managed_disk_type = "Premium_LRS"

    storage_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "16.04.0-LTS"
        version   = "latest"

    os_profile {
        computer_name  = "myvirtual machine"
        admin_username = "azureuser"

    os_profile_linux_config {
        disable_password_authentication = true
        ssh_keys {
            path     = "/home/azureuser/.ssh/authorized_keys"
            key_data = "ssh-rsa AAAAB3Nz{snip}hwhaa6h"

    boot_diagnostics {
        enabled     = "true"
        storage_uri = "${azurerm_storage_account.mystorageaccount.primary_blob_endpoint}"

    tags = {
        environment = "Terraform Demo"
Azure Automation State Configuration (DSC)
Azure Resource Manager templates (all resources)

Azure Resource Manager (ARM) template

  • Structure of section and spesific properties of each sections
  • Version of the template language is important “2019-04-01”
  • Sections of the ARM template
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", # required
  "contentVersion": "", # required : any value is acceptable
  "apiProfile": "",
  "parameters": {  },
  "variables": {  },
  "functions": [  ],
  "resources": [  ], # required
  "outputs": {  }

Parameter section for input value in deployment time

limited to 256 parameters

We can used objects that contains multiple properties

"parameters": {
  "<parameter-name>" : { # required
    "type" : "<type-of-parameter-value>", # required : [string|securestring|int|bool|object|secureObject|array]
    "defaultValue": "<default-value-of-parameter>",
    "allowedValues": [ "<array-of-allowed-values>" ],
    "minValue": <minimum-value-for-int>,
    "maxValue": <maximum-value-for-int>,
    "minLength": <minimum-length-for-string-or-array>,
    "maxLength": <maximum-length-for-string-or-array-parameters>,
    "metadata": {
      "description": "<description-of-the parameter>"
  • Variables to reduce the complexity
"variables": {
  "<variable-name>": "<variable-value>",
  "<variable-name>": {
  "<variable-object-name>": {
    "copy": [
        "name": "<name-of-array-property>",
        "count": <number-of-iterations>,
        "input": <object-or-value-to-repeat>
  "copy": [
      "name": "<variable-array-name>",
      "count": <number-of-iterations>,
      "input": <object-or-value-to-repeat>


  "type": "Microsoft.Compute/virtualMachines",
  "apiVersion": "2018-10-01",
  "name": "[variables('virtual machineName')]",
  "location": "[parameters('location')]",
  "dependsOn": [
    "[resourceId('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
    "[resourceId('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
  "properties": {
    "hardwareProfile": {
      "virtual machinesize": "Standard_A2"
    "osProfile": {
      "computerName": "[variables('virtual machineName')]",
      "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]"

Source: https://docs.microsoft.com/en-us/learn/modules/choose-compute-provisioning/

Implement Infrastructure as code

Deploy ARM Template via Powershell


You owe your dreams your courage.

Koleka Putuma

Published by parisamoosavinezhad

- Software Engineer - Software Architect - Software and database specialist - Cloud solution architect

One thought on “Onboarding : Azure Infrastructure deployment

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 )

Google photo

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

Twitter picture

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

Facebook photo

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

Connecting to %s

%d bloggers like this: