Microsoft Azure Infrastructure
Andrew Posted on 12:51 pm

How to Deploy Azure Virtual Machines – Part 4 – JSON Templates

Today we continue our deployment of Microsoft Azure virtual machines and start exploring JSON and ARM templates. There are a lot of ways to do deployment as we continue our look at the options. Let’s look at templates in JSON for creating VM infrastructure.

If you missed the start of this series, check out my first post on Azure VMs right here.

The next way I’ll show you to deploy a VM in Azure is also via the Portal so let’s head to https://portal.azure.com and get started.

Now today things are a little different. We’re going to use a GitHub Azure Quickstart Template that you can find here: https://portal.azure.com/#create/Microsoft.Template/uri/https%3a%2f%2fraw.githubusercontent.com%2fAzure%2fazure-quickstart-templates%2fmaster%2f101-vm-simple-windows%2fazuredeploy.json

I’ve put the link into full text above because I want you to take a moment and understand what your loading. Microsoft has a lot of quickstart templates published on GitHub that we can use and I’ll publish the code for this at the bottom of this article (if you’ve worked in JSON you know why it’s at the end already!).

Ok, so how I do this is log into an inPrivate session in Edge and log into my testing subscription in Azure at https://portal.azure.com, then I copy the GitHub URL into a new tab. Very Easy! It will load up a blade called Deploy a Simple Windows VM right from the JSON template.

Alright, we have some cool stuff prepopulated here and some oddness. No problem, let’s get it all sorted:

  1. Enter the resource group we created a few articles ago called rgVMCreationGames
  2. Enter your username to use for the vm
  3. Enter a strong password to use
  4. You can clear this box, we don’t need a DNS name for our little test
  5. Let’s name the public IP as ‘myPublicIP4’ that will be aligned with our virtual machine name
  6. Select Dynamic
  7. Choose Basic
  8. Leave the default setting on 2019 – Datacenter
  9. Select your favourite size for the vm but Standard D2_v3 will be ok today
  10. Enter ‘Canada Central’ for your Location
  11. Name the vm ‘vmgames4’ since this is our 4th vm we are creating together

Ok, now you can click on Review + Create.

We really want to see the happy green Validation Passed. Correct any errors if you see them. Our settings should give you a clean pass here.

Once the vm is created, let’s do the same thing we tend to do and connect to it to make sure it’s operational. Let’s jump back over to the Virtual Machines blade in Azure Portal and get the public ip address:

Take a moment to confirm the options you selected are used in the virtual machine and then let’s use Microsoft Remote Desktop, or your other favourite tool to connect to our server.

Well – this is looking good! I think the server is up and running with the basic config starting from that JSON template. Well done!

Remember that in PowerShell you can run shutdown -p and shutdown the server nice and quickly, but you still need to deallocate that system in Azure to remove the billing and save those credits!

So we’ve created 4 different server in 4 different ways now. I have one more treat that I want to share with templates and creating VMs next time so check back again soon to catch the next and final article in our series.

JSON Template That We Used Today

{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminUsername": {
"type": "string",
"metadata": {
"description": "Username for the Virtual Machine."
}
},
"adminPassword": {
"type": "securestring",
"minLength": 12,
"metadata": {
"description": "Password for the Virtual Machine."
}
},
"dnsLabelPrefix": {
"type": "string",
"defaultValue": "[toLower(concat(parameters('vmName'),'-', uniqueString(resourceGroup().id, parameters('vmName'))))]",
"metadata": {
"description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
}
},
"publicIpName": {
"type": "string",
"defaultValue": "myPublicIP",
"metadata": {
"description": "Name for the Public IP used to access the Virtual Machine."
}
},
"publicIPAllocationMethod": {
"type": "string",
"defaultValue": "Dynamic",
"allowedValues": [
"Dynamic",
"Static"
],
"metadata": {
"description": "Allocation method for the Public IP used to access the Virtual Machine."
}
},
"publicIpSku": {
"type": "string",
"defaultValue": "Basic",
"allowedValues": [
"Basic",
"Standard"
],
"metadata": {
"description": "SKU for the Public IP used to access the Virtual Machine."
}
},

"OSVersion": {
  "type": "string",
  "defaultValue": "2019-Datacenter",
  "allowedValues": [
    "2008-R2-SP1",
    "2012-Datacenter",
    "2012-R2-Datacenter",
    "2016-Nano-Server",
    "2016-Datacenter-with-Containers",
    "2016-Datacenter",
    "2019-Datacenter",
    "2019-Datacenter-Core",
    "2019-Datacenter-Core-smalldisk",
    "2019-Datacenter-Core-with-Containers",
    "2019-Datacenter-Core-with-Containers-smalldisk",
    "2019-Datacenter-smalldisk",
    "2019-Datacenter-with-Containers",
    "2019-Datacenter-with-Containers-smalldisk"
  ],
  "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_D2_v3",
  "metadata": {
    "description": "Size of the virtual machine."
  }
},
"location": {
  "type": "string",
  "defaultValue": "[resourceGroup().location]",
  "metadata": {
    "description": "Location for all resources."
  }
},
"vmName": {
  "type": "string",
  "defaultValue": "simple-vm",
  "metadata": {
    "description": "Name of the virtual machine."
  }
}

},
"variables": {
"storageAccountName": "[concat('bootdiags', uniquestring(resourceGroup().id))]",
"nicName": "myVMNic",
"addressPrefix": "10.0.0.0/16",
"subnetName": "Subnet",
"subnetPrefix": "10.0.0.0/24",
"virtualNetworkName": "MyVNET",
"subnetRef": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('virtualNetworkName'), variables('subnetName'))]",
"networkSecurityGroupName": "default-NSG"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"name": "[variables('storageAccountName')]",
"location": "[parameters('location')]",
"sku": {
"name": "Standard_LRS"
},
"kind": "Storage",
"properties": {}
},
{
"type": "Microsoft.Network/publicIPAddresses",
"apiVersion": "2020-06-01",
"name": "[parameters('publicIPName')]",
"location": "[parameters('location')]",
"sku": {
"name": "[parameters('publicIpSku')]"
},
"properties": {
"publicIPAllocationMethod": "[parameters('publicIPAllocationMethod')]",
"dnsSettings": {
"domainNameLabel": "[parameters('dnsLabelPrefix')]"
}
}
},
{
"type": "Microsoft.Network/networkSecurityGroups",
"apiVersion": "2020-06-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": "2020-06-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": "2020-06-01",
"name": "[variables('nicName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPName'))]",
"[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]"
],
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAllocationMethod": "Dynamic",
"publicIPAddress": {
"id": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPName'))]"
},
"subnet": {
"id": "[variables('subnetRef')]"
}
}
}
]
}
},
{
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2020-06-01",
"name": "[parameters('vmName')]",
"location": "[parameters('location')]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]",
"[resourceId('Microsoft.Network/networkInterfaces', variables('nicName'))]"
],
"properties": {
"hardwareProfile": {
"vmSize": "[parameters('vmSize')]"
},
"osProfile": {
"computerName": "[parameters('vmName')]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"storageProfile": {
"imageReference": {
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "[parameters('OSVersion')]",
"version": "latest"
},
"osDisk": {
"createOption": "FromImage",
"managedDisk": {
"storageAccountType": "StandardSSD_LRS"
}
},
"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]"
}
}
}
}
],
"outputs": {
"hostname": {
"type": "string",
"value": "[reference(parameters('publicIPName')).dnsSettings.fqdn]"
}
}
}

This is the base JSON quick start template provided by Microsoft on GitHub at the URL listed in the article.