The Usual Tech Ramblings

Azure VMs and Setting Subnets via PowerShell

One of the projects I’ve been working on recently is a POC in Azure to allow us to move a collection of desktop users to lower end laptops, while using high end servers to perform a lot of data processing. The idea is that we can spin up and destroy machines as we see fit. The plan was fairly solid, and we build out our domain controllers and a template machine with all the software in it, before configuration. We then used PowerShell to spin up new machines as we needed them.

One of the issues I stumped over when working on this was making sure the servers were put into the right network. This was important as they were being joined to a domain. I had originally started with something like this:

$img = 'imgid_Windows-Server-2008-127GB.vhd'
$svcname = 'mytestservice01'
$svcpass = '!testpass321!'
$svcuser = 'testadmin'

$vm1 = New-AzureVMConfig -ImageName $img -InstanceSize 'ExtraSmall' -Name $svcname | `
  Add-AzureProvisioningConfig -WindowsDomain -AdminUsername $svcuser -Password $svcpass -DomainUserName 'dmnadmin' -Domain 'TestDomain' -DomainPassword 'ImnotTelling!' -JoinDomain 'TestDomain.local' -TimeZone 'Canada Central Standard Time'

New-AzureVM -VMs $vm1 -ServiceName $svcname -VNetName 'Test_Net' -AffinityGroup 'TestGroup-USEast'

This seemed to look right, and worked fine, as long as I wasn’t trying to add it to a VNet or an Affinity Group. When I added those options, I was thrown the following error:

New-AzureVM : Networking.DeploymentVNetAddressAllocationFailure : Unable to allocate the required address spaces for the deployment in a new or predefined subnet that is contained within the specified virtual network.

It seemed to me that the New-AzureVM command should have had some method to define which subnet was to be allocated to, but it wasn’t there. What was even more confusing was this VNet only had a single subnet, so you’d think it might select that, but not so much luck.

The answer lies in the Set-AzureSubnet command, which should have been pretty obvious to me. You can add it as part of your provisioning command like this:

$vm1 = New-AzureVMConfig -ImageName $img -InstanceSize 'ExtraSmall' -Name $svcname | `
    Add-AzureProvisioningConfig -WindowsDomain -AdminUsername $svcuser -Password $svcpass -DomainUserName 'dmnadmin' -Domain 'TestDomain' -DomainPassword 'ImnotTelling!' -JoinDomain 'TestDomain.local' -TimeZone 'Canada Central Standard Time' | `
  Set-AzureSubnet 'Subnet-1'

All I’ve done is added the extra command to the end, and now Azure is happy. This will spin up a new VM and drop it in the right VNet, Affinity Group, and Subnet. Based on the VNet’s network configurations, and DNS settings, the new machine is provisioned, and joined to the domain immediately.

This makes me very happy because this is a quick sample of how we’d proceed with automating and deploying an undefined number of VMs in Azure based off of our golden image. With some minor tweaks we can loop through and spin up 50 machines with little work.