March 22, 2016

Azure ARM Custom VMs

In Azure ASM mode, you have this neat little tool in the portal that allows you to show VMs that you've 'captured' and easily redeploy. This was to support the scenarios where you sysprepped and/or uploaded your own VMs. In ARM mode, things are a bit more powerful (read: tricky). I've been told the new portal will support the old ASM tool soon but I needed to do it now, so I should embrace my ARM template skills. I've also been told to stop calling it the new portal and just call it the portal, but that's an annoyance for another time.

You certainly can deploy a sysprepped VM with PowerShell (I showed off how to deploy VM in ARM with PowerShell recently.) Now, let's do it with a sysprepped VM and ARM templates!

First, you need a sysprepped VM. There's a nice article here on how to do that if you are unfamiliar. Key point - if you don't OOBE/Generalize/Shutdown it simply will not work:
really important step

Once, you have sysprepped and your VM is shutdown, you can upload it to Azure storage and skip to the deployment step - but read this if you want a briefing on how to do it correctly. If you are sysprepping FROM Azure, you need to tell Azure that it is a sysprepped image. Here's how you do it:

Set-AzureRmVm -ResourceGroupName YourResourceGroup -Name YourWindowsVM -Generalized

Then capture it to storage:
Save-AzureRmVMImage -ResourceGroupName YourResourceGroup -VMName YourWindowsVM -DestinationContainerName YourImagesContainer -VHDNamePrefix YourTemplatePrefix -Path Yourlocalfilepath\Filename.json

What's that "YourLocalFilePath" business all about? Well, when you capture a VM to storage, it puts it in the storage container of your choosing, but, to keep you from messing it up (ala, creating a VM right from it and never being able to use it again as an image), it puts it into a secret storage spot you can't see in that container. The "Filename.json" file that you save will give you the URL you will need here in a minute. The URL you want is located at this node in Filename.json: resources > storageProfile > osDisk > image > uri.

Now, you have a sysprepped VM, you've told Azure that it is generalized and ready to be an image, you've deployed it to storage ready to be used and you've grabbed the path to said image. Now, let's use an ARM template to deploy it!

Just click the Deploy to Azure button :) or see pretty picture of the template we've built for you by clicking the visualize button:

deploy to azure

Easy right? hehe - yes, you can use that for repeatable production deployments. You may, however, want to do that from your own console and not my website, so, simply download the pre-baked template and issue a new template deployment:
New-AzureRmResourceGroupDeployment -Name ExampleDeployment -ResourceGroupName ExampleResourceGroup -TemplateFile <PathOrLinkToTemplate> -myParameterName "parameterValue".

At first, I was annoyed by the fact that there templates were hard to make. Then I realized, these quickstart templates that are up in GitHub where this template comes from are intended to cover 95% or better of all the deployments you could ever shake a stick at and they are always adding more (and taking contributions). Pretty cool stuff :)