Build custom images using Azure VM Image Builder and Bicep

Rohan Islam
4 min readMar 12, 2023

--

In this blog, we will talk about Azure VM Image Builder and see how VM image build process can be automated using Bicep.

Let’s have basic understanding on Azure VM Image builder before we proceed with the fun part.

What is Azure VM Image Builder?

Azure VM Image Builder is a tool that simplifies VM image building process on Azure. It is built on HashiCorp Packer technology.

It helps create custom Windows or Linux images by using either Azure Marketplace images or existing images as the base image source and then distribute the image to a distribution target such as VM Image Version, Managed Image and Storage Blob (VHD).

What are the components used for Azure VM Image Builder?

The following Azure resources are required when VM Image Version is the intended image distribution target.

Azure compute gallery

In simple term, Azure Compute Gallery is the storage where we store our images. It simplifies custom image sharing across the organization.

VM image definition

It is the definition of the type of image and it is created within the Azure compute gallery. It holds information about the image such as Windows or Linux, max and min memory/cpu requirements etc.

Image template

The image template basically tells Packer how to build the image. The template file contains all the customization required for creating the custom image. The template is associated with the VM image definition.

User assigned managed identity

A user assigned managed identity is necessary to associate with the Image template resource. This is required to grant permission to Packer to build the image.

VM image version

An image version is created within VM Image Definition after successful build of an Image template. VMs can be deployed using this image version.

Now, we will see how we can automate the image build process using Bicep.

Objective

The objective is to create a custom Windows 10 image for Azure Virtual Desktop using Azure marketplace image as the source and VM Image Version as the distribution type. We will use Bicep for the complete deployment and PowerShell scripts for the image customization.

Prepare environment

Install Git

At first we will install Git on the PC from the official site if we do not have it already.

Create a Git repository

Now we will create a Git repository to host the code. I created a public GitHub repository so that I can share the code with you easily instead of making this blog lengthy.

Setup code editor

I am using VS Code as the code editor. If you do not already have it, you can download it from the official site. Install the following extensions on VS Code — GitHub Pull Requests and Issues, Azure Account, Bicep, PowerShell.

Press ctrl + shift + P to go to Command Palette of VS Code and sign in to Azure account. If you have multiple tenants then also run “Select Tenant” command to choose the tenant.

Now sign in to the GitHub account from VS Code and clone the blank repository to get started.

Let’s code & deploy

I created the following bicep files and PowerShell scripts as shown in the picture below. Then I directly deployed the bicep file “azureDeploy.bicep” from VS Code to start deployment onto my Azure subscription. The entire code can be found under my GitHub Repository.

After successful deployment we can see the following resources on the Azure portal within the newly created resources group.

Start Build

Now, we can go to the Image template resource and “Start build” to create an image version as per the template within the “VM image definition” resource.

Alternatively, the following PowerShell script can be used to trigger image build and capture the build status.

#Variables
$resourceGroupName = "rohanlab-avdimage-rg-01"
$imageTemplateName = "avd10ImageTemplate01"

#Build image
Start-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName -NoWait

#Get build status
$buildStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $resourceGroupName -Name $imageTemplateName)
$buildStatus | Format-List -Property *
$buildStatus.LastRunStatusRunState
$buildStatus.LastRunStatusRunSubState

The Image template creates a managed resource group to store the customization scripts within a storage account. During the image build process this resource group is used to provision temporary resources such as VM, disks etc. The packer log can be found within the storage account of this resource group.

It may take some time to compete the build based on the customization. Once the build is complete, a new VM Image Version resource will appear within the resource group.

We can provision VM or VMSS using the VM Image Version (which is basically the custom image that we just created) either via automation or from portal.

Thanks for reading, give it a 👏 if you like it. Please leave a comment and let me know if you have any feedback.

--

--

Rohan Islam

Cloud Architect | Continuous learner | Passionate about technologies