Azure Image builder is a service in Azure for creating your own customized virtual machine images to your specific requirements, instead of using Microsoft provided images and applying customization at each deployment. Organizations often require a custom image (Golden image) to meet their compliance obligations; these can be difficult to create and maintain adding complex barriers for achieving automation.
When not using Azure Image Builder, you typically use virtual machine custom script extensions to customise the marketplace image, however this can lengthen the deployment time based on the number of packages deployed and may not consistently deliver an identical outcome if not managed carefully.
Alternatively, (or in addition) we can store VHD images in Azure and reference it when building virtual machines. However, the management of such images can be a time-consuming process. When we need to update the custom image for monthly security patches, you need to create a virtual machine from the VHD and use it to re-build the VHD image.
To overcome the above-mentioned issues, we can leverage Azure image builder.
Figure 1 – Azure VM image builder
Azure shared image gallery
The shared image gallery is a container for storing images in an Azure subscription which can be replicated to any Azure public region. It provides features to share images to same or across Azure AD tenants.
How does it work:
The below picture illustrates the high-level activity involved in Azure image build process:
- Create an ARM template for the custom image. The template is used to define a source and customisations (scripts & etc) required as well as distribution of the image.
- Submit the image template to create an image template artifact in specified resource groups. In the background, the source image & specified customisation artifacts will be downloaded to a storage account with a staging resource group. The resource group name syntax: IT_<DestinationResourceGroup>_<TemplateName>
- Next, Image Builder will execute the image template with the downloaded artifacts and to create an image. Image Builder creates a VM using a D1v2 VM size, including the storage and networking required for the VM; it will be deleted once Image Builder has finished creating the image.
- The final step is Image Builder distribution of the image as specified in the ARM template as shared image or VHD or managed image.
The Azure Image Builder Service is available for Preview in selected Azure public regions. Images can be distributed outside of these regions, with shared image gallery.
In this blog, let me walk through the steps required to create a Golden base image of windows server and have it replicated to the Australia East region. Using it, I will create a new virtual machine in Australia East. The activity for this blog will be in Azure PowerShell.
Create a shared image gallery in your respected region.
In this section, we will create shared image gallery for storing custom images for usage.
- Log into Azure portal and access Azure Cloud shell will Azure PowerShell mode.
- Create a new resource group with name Azure-demo: New-AzResourceGroup -Name “Azure-demo” -Location “West US”
- Run below command for creating shared image gallery:
New-AzGallery -GalleryName “azdemoGallery” -ResourceGroupName “Azure-demo” -Location “West US” - The above command will create a Shared image gallery with name “azdemoGallery ” in West US region.
- Next, we need to create Gallery definition for storing windows images:
New-AzGalleryImageDefinition -GalleryName “azdemogallery” -ResourceGroupName “Azure-demo” -location “West US” -Name “winserverimages” -OsState generalized -Ostype windows -Publisher demo -offer windows -sku ‘win2016’
Create a PowerShell script and store in Azure storage account.
In this section, we will create PowerShell script to install IIS on virtual machine and store in Azure storage account.
- Create a one line script with name “iisinstall.ps1” as
Install-WindowsFeature -name Web-Server -IncludeManagementTools.
- Create a storage account with name “scriptstore” (use you own name if this creates a conflict) and store the PowerShell file in it.
- Save the location of script file for later use: https://scriptstore.blob.core.windows.net/script/iisinstall.ps1
Register preview feature and create user identity
In this section, we will register the service and create a user identity. The Azure VM image builder is currently in Preview and therefore the service needs to be registered for each subscription.
- To register the feature run command in PowerShell:
Register-AzProviderFeature -FeatureName VirtualMachineTemplatePreview -ProviderNamespace Microsoft.VirtualMachineImages - The above command will return the state as “registering” , it may take a few minutes to complete.
- Run the command to verify the state has changed to “registered”.
Get-AzProviderFeature -ProviderNamespace Microsoft.VirtualMachineImages -FeatureName VirtualMachineTemplatePreview - Install Azure user identity module with:
Install-Module -Name Az.ManagedServiceIdentity - Create an user identity for image service by running command :
New-AzUserAssignedIdentity -ResourceGroupName “azure-demo” -Name azureimageidentity - Let’s get above created identity resource and principal id for later use by running commands:
$identityNameResourceId=$(Get-AzUserAssignedIdentity -ResourceGroupName “azure-demo” -Name azureimageidentity).Id
$identityNamePrincipalId=$(Get-AzUserAssignedIdentity -ResourceGroupName “azure-demo” -Name azureimageidentity).PrincipalId
- Create a custom role template and store it with name: imagerole.json. Replace with your subscription id and resource group name.
{
“Name”: “Azure Image Builder Service Image Creation Role”,
“IsCustom”: true,
“Description”: “Image Builder access to create resources for the image build”,
“Actions”: [
“Microsoft.Compute/galleries/read”,
“Microsoft.Compute/galleries/images/read”,
“Microsoft.Compute/galleries/images/versions/read”,
“Microsoft.Compute/galleries/images/versions/write”,
“Microsoft.Compute/images/write”,
“Microsoft.Compute/images/read”,
“Microsoft.Compute/images/delete”
],
“NotActions”: [
],
“AssignableScopes”: [
“/subscriptions/<subscriptionID>/resourceGroups/<rgName>”
]
}
- Upload the above created file into Azure Cloud Shell, by clicking upload/download file button and select the imagerole.json. Please ensure, you have changed subscription id and resource group name in file.
- Run the command to create custom role from upload the file:
New-AzRoleDefinition -InputFile “imagerole.json” - Copy the role definition name and paste in command:
$imageRoleName = “Azure Image Builder Service Image Creation Role” - Provide access to above created service principal with role created:
New-AzRoleAssignment -ObjectId $identityNamePrincipalId -RoleDefinitionName $imageRoleName -Scope “/subscriptions/<subscription_id>/resourceGroups/<resourcegroup>”
Replace Subscription id and resource group
Create image template for custom image.
In this section, we will be create an ARM Template for custom image preparation. Create a template file named “custom-image-win.json
Replace the content of file with the name of your resource group, subscriptions, sharedimage gallery and image definition.
{
“$schema”: “http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#”,
“contentVersion”: “1.0.0.0”,
“parameters”: {
“imageTemplateName”: {
“type”: “string”
}
},
“variables”: {},
“resources”: [
{
“name”: “[parameters(‘imageTemplateName’)]”,
“type”: “Microsoft.VirtualMachineImages/imageTemplates”,
“apiVersion”: “2019-05-01-preview”,
“location”: “westus”,
“dependsOn”: [],
“identity”: {
“type”: “UserAssigned”,
“userAssignedIdentities”: {
“/subscriptions/<subid>/resourcegroups/azure-demo/providers/Microsoft.ManagedIdentity/userAssignedIdentities/azureimageidentity”: {}
}
},
“properties”: {
“buildTimeoutInMinutes”: 100,
“vmProfile”: {
“vmSize”: “Standard_D1_v2”,
“osDiskSizeGB”: 100
},
“source”: {
“type”: “PlatformImage”,
“publisher”: “MicrosoftWindowsServer”,
“offer”: “WindowsServer”,
“sku”: “2016-Datacenter”,
“version”: “latest”
},
“customize”: [
{
“type”: “PowerShell”,
“name”: “Createiis”,
“scriptUri”: “https://scriptsore.blob.core.windows.net/script/iisinstall.ps1”
},
{
“type”: “WindowsRestart”,
“restartCheckCommand”: “echo Azure-Image-Builder-Restarted-the-VM-after-iis > c:\\azdemo\\output.txt”,
“restartTimeout”: “5m”
}
],
“distribute”: [
{
“type”: “SharedImage”,
“galleryImageId”: “/subscriptions/<subid>/resourceGroups/Azure-demo/providers/Microsoft.Compute/galleries/azdemoGallery01/images/winserverimages”,
“runOutputName”: “winserver2016img”,
“artifactTags”: {
“baseosimg”: “windows2016”
},
“replicationRegions”: [“westus”, “australiaeast”]
}
]
}
}
]
}
The above template creates a windows server 2016 base image and creates a folder in c drive with a notepad file.
- Upload the above created file into Azure Cloud Shell, by clicking upload/download file button and select the custom-image-win.json.
- Run the command to submit the custom template for Azure image build:
New-AzResourceGroupDeployment -ResourceGroupName “azure-demo” -TemplateFile “custom-image-win.json” -imageTemplateName “win-2016-image” - Once the above command completes successfully, to start building the image, run:
Invoke-AzResourceAction -ResourceName “win-2016-image” -ResourceGroupName “azure-demo” -ResourceType Microsoft.VirtualMachineImages/imageTemplates -ApiVersion “2019-05-01-preview” -Action Run -Force - This will download any dependent artifacts (scripts etc), validate, check permissions, and store them in the staging Resource Group, prefixed, IT_<DestinationResourceGroup>_<TemplateName>
- You should see virtual machine, virtual network and staging storage account will be created in the staging resource group.
- The build process will take a minimum of 30 mins. Please check the image is available in image gallery and check replication it has been replicated to both east us and Australia east.
Verify the customisation:
- Now proceed to create a new virtual machine with the custom image we created in this process.
- Click +create VM from image under shared gallery and proceed with default.
- Login to newly created VM and check a notepad file has output information on c:\azuredemo\output.txt
- Browse localhost on Virtual machine to confirm IIS has been installed.
Note: If you want to enable the replication of base image to other location, please click update replication of image and select your Azure public region.
Additional notes:
- We can provide our existing Azure Virtual network for staging instead of Azure Default. This will provide access to things we own (File share and scripts etc.). Add the below lines within the VMprofile section of template:
“vnetConfig”: {
“subnetId”: “/subscriptions/<subscriptionID>/resourceGroups/<vnetRgName>/providers/Microsoft.Network/virtualNetworks/<vnetName>/subnets/<subnetName>”
}
- By default, VM size of custom image will “Standard_D1_v2 for Staging VM and it can be changed in ARM template. Example:
{
“vmSize”: “Standard_D2s_v3”
}
- By default, Azure Image Builder will also run ‘deprovision’ code at the end of each image customisation phase, to ‘generalize’ the image. Generalizing is a process where the image is set up so it can be used to create multiple VMs. For Windows VMs, Azure Image Builder uses Sysprep.
- We can enable access to Azure storage accounts with User assigned identity and storage account does not require public access.
Santhosh has over 15 years of experience in the IT organization. Working as a Cloud Infrastructure Architect and has a wide range of expertise in Microsoft technologies, with a specialization in public & private cloud services for enterprise customers. My varied background includes work in cloud computing, virtualization, storage, networks, automation and DevOps.