This topic is part of a series about how to deploy a Windows Server 2016 RDS farm in Microsoft Azure. Previously, we have created the network resources, the storage account for diagnostics and the Windows image. In this topic, we will create all the Azure VM required for the solution. The deployment will be processed from a JSON template. This series talks about the following subjects:

Github

The template for this series are located in my Github. I have created a folder called RDSFarm that containers JSON template. For this topic, I have used RDS-VMs.json.

JSON template explanation

In this template, I create an availability set for each kind of service. So, I have 5 availability sets (Domain Controllers, File Servers, RD Host, RD Broker and RD Gateway). So, I have the following block code for each availability set:

{ "type": "Microsoft.Compute/availabilitySets", "sku": { "name": "Aligned" }, "name": "[parameters('ASDomainControllersName')]", "apiVersion": "[variables('computeResouresApiVersion')]", "location": "[variables('ResourcesLocation')]", "tags": { "displayName": "AS_DomainControllers" }, "properties": { "platformUpdateDomainCount": 5, "platformFaultDomainCount": 2 } }

Then I create the virtual network adapters. Each VM has one network adapters excepted the File Servers which have two (cluster and management). Each vNIC is connected to the right subnet. You can see also that I have created a loop (copy section): because each kind of service has at least two VMs, the loop avoids me to duplicate several times same block code.

{ "type": "Microsoft.Network/networkInterfaces", "name": "[concat(parameters('PrefixNameDC'), copyindex())]", "apiVersion": "[variables('NetworkResouresApiVersion')]", "location": "[variables('ResourcesLocation')]", "tags": { "displayName": "vNIC_DomainControllers" }, "copy": { "name": "DCnicLoop", "count": "[parameters('numberOfDC')]" }, "properties": { "ipConfigurations": [ { "name": "ipconfig1", "properties": { "privateIPAllocationMethod": "Dynamic", "subnet": { "id": "[Variables('vNetSubIntRef')]" } } } ], "dnsSettings": { "dnsServers": [] }, "enableIPForwarding": false } }

Next I create data disks. File Servers have four data disks each (for Storage Spaces Direct). Each Domain Controller has one data disk to host the AD database and RD Hosts have a data disk for application. All these disks are managed disks. I have also made a loop for each kind of data disk:

{ "type": "Microsoft.Compute/disks", "name": "[concat(parameters('PrefixNameDC'), copyindex(),'-Data01')]", "apiVersion": "[variables('computeResouresApiVersion')]", "location": "[variables('ResourcesLocation')]", "tags": { "displayName": "Disks_DomainControllers" }, "copy": { "name": "DCDskLoop", "count": "[parameters('numberOfDC')]" }, "properties": { "creationData": { "createOption": "Empty" }, "accountType": "Standard_LRS", "diskSizeGB": 10 } }

I have also created a public IP for the RD Access load balancer:

{ "type": "Microsoft.Network/publicIPAddresses", "name": "[parameters('PublicIPName')]", "apiVersion": "[variables('NetworkResouresApiVersion')]", "location": "[variables('ResourcesLocation')]", "tags": { "displayName": "Public IP Address" }, "properties": { "publicIPAllocationMethod": "Static", "idleTimeoutInMinutes": 4 }, "dependsOn": [] }

To finish, the following JSON block code creates VMs. I have a block code for each kind of VM. Then I use a loop to deploy several times the same VM with a different name. I use the Windows image to deploy the VM. Credentials are provided from parameters. Boot diagnostics are enabled and logs are stored in the storage account. Each vNIC is also bound to the right VM. VMs are added to availability set and connected to the right data disks.

{ "name": "[concat(parameters('PrefixNameDC'), copyindex())]", "type": "Microsoft.Compute/virtualMachines", "apiVersion": "[variables('computeResouresApiVersion')]", "location": "[variables('ResourcesLocation')]", "tags": { "displayName": "VM_DomainControllers" }, "copy": { "name": "DCVMLoop", "count": "[parameters('NumberOfDC')]" }, "dependsOn": [ "[resourceId('Microsoft.Compute/availabilitySets', parameters('ASDomainControllersName'))]", "[resourceId('Microsoft.Network/networkInterfaces', concat(parameters('PrefixNameDC'), copyindex()))]" ], "properties": { "osProfile": { "computerName": "[concat(parameters('PrefixNameDC'), copyindex())]", "adminUsername": "[parameters('adminUser')]", "adminPassword": "[parameters('adminPassword')]", "windowsConfiguration": { "provisionVmAgent": "true" } }, "hardwareProfile": { "vmSize": "Standard_DS1_v2" }, "storageProfile": { "imageReference": { "id": "[parameters('OSDiskMasterPath')]" }, "osDisk": { "name": "[concat(parameters('PrefixNameDC'), copyindex(),'-OS')]", "createOption": "FromImage", "managedDisk": { "storageAccountType": "Standard_LRS" } }, "dataDisks": [ { "lun": 2, "name": "[concat(parameters('PrefixNameDC'), copyindex(),'-Data01')]", "createOption": "Attach", "managedDisk": { "id": "[resourceId('Microsoft.Compute/disks', concat(parameters('PrefixNameDC'), copyindex(),'-Data01'))]" } } ] }, "networkProfile": { "networkInterfaces": [ { "id": "[resourceId('Microsoft.Network/networkInterfaces', concat(parameters('PrefixNameDC'), copyindex()))]" } ] }, "diagnosticsProfile": { "bootDiagnostics": { "enabled": true, "storageUri": "[reference(resourceId('rdsfarm', 'Microsoft.Storage/storageAccounts', parameters('Sto_LogsAccount')), '2015-06-15').primaryEndpoints['blob']]" } }, "availabilitySet": { "id": "[resourceId('Microsoft.Compute/availabilitySets', parameters('ASDomainControllersName'))]" } } }

Template deployment

To run the deployment with the JSON template, go to the marketplace and search for Template Deployment.

Then, copy past the template. You should have something like this:

Next change parameters as you wish and click on purchase.

After the deployment, I have stopped all VMs to not spend money immediately for VMs not used.

Result

Once the deployment is finished, you should have several Azure VM depending on the loop settings. On my side, I have 10 Azure VMs.

If I select a VM such as a file server, you can see that managed disks are well bound to Azure VM.

Network interfaces are also connected to the server and well associated with the right subnet.

Azure VM are also inside Availability Sets.

To finish, boot diagnostics are enabled and stored in the storage account.

Next topic

In the next topic, I will configure the domain controller. I’ll set the AD site and I’ll promote the Azure domain controllers.