Insight Tech APAC Blog Logo

Managing the Azure Virtual Desktop Gold Image - Virtual Desktop Series Post 1

Author:
Published: March 28, 2022

15 minutes to read

Azure Virtual Desktop is a Desktop-as-a-Service solution provided by Microsoft running on Azure. The Azure Virtual Desktop (AVD) session management control plane is entirely managed by Microsoft. As this is often the most complex aspect of implementing a Virtual Desktop Infrastructure (VDI) solution, AVD dramatically lowers the technical and financial barriers to entry for those who are on the fence about investing in a VDI solution.

VDI vs AVD - Who manages what?

Typically, solution architects and IT administrators begin planning a VDI deployment working out how they will network, configure and deploy all of the infrastructure and services in order to implement a functional solution. AVD enables IT administrators to create a functional host pool from a Virtual Machine (VM) image from a single wizard. This is a huge time and cost saving, however there is still one technical aspect of an AVD deployment that needs to be considered prior to deploying a host pool: the Gold Image.

The AVD Gold Image is in your subscription

What is a Gold Image?

A VDI Gold Image contains all software and profile management pre-configuration to deploy several identical VMs for users to log into. In this article I will describe the process for creating a VM to be used as a Gold Image, Capturing a VM to an image stored in a Compute Gallery, and finally, referencing a new Gold Image from the Host Pool configuration wizard.

The first step is to create the Azure object that can hold VM Images. While these can be stored in a Storage Account, it is highly recommended to make use of the Azure Compute Gallery. The Azure Compute Gallery lets you share custom VM images and application packages with others in an organization, within or across regions, or within an AAD tenant. Images in the Compute Gallery are version controlled. Image replicas (single or cross-region) reduce throttling during VM creation where multiple simultaneous deployments or cross-region deployments would overload a single replica. The Compute Gallery is free to create, however storage costs of each image replica, and for network egress to replicate the image to other regions are chargeable. Source: Store and share images in an Azure Compute Gallery

There are limits, per subscription, for deploying resources using Azure Compute Galleries:

  • 100 galleries, per subscription, per region
  • 1,000 image definitions, per subscription, per region
  • 10,000 image versions, per subscription, per region
  • 10 image version replicas, per subscription, per region
  • Any disk attached to the image must be less than or equal to 1TB in size

Source: Store and share images in an Azure Compute Gallery - Limits

Create the Gold Image VM

Secondly, a VM will need to be created in an Azure Resource Group that will be converted into the Gold Image. The type of AVD deployment that is being considered will determine which Azure Marketplace image is used to create the Gold Image VM.

The key consideration is the difference between Personal and Pooled Desktops

Personal Desktops - A VM allocated per user

  • Ideal for single-session users with heavy performance requirements
  • Choose the right VM to run robust apps like CAD, SAP and others
  • Always-on experience and single state retention

Pooled Desktops - Multiple users allocated to the same VM

  • Ideal for users with light to medium workloads with basic business requirements
  • Choose the right VM to run most business apps

Pooled Desktops allow multiple users to share a single VM’s resources. A Pooled Desktop Gold Image will need to user Multi-Session Windows 10 Marketplace image. For high performance users using Personal Desktops with dedicated VM resources, the standard Windows 10 Marketplace image can be used.

See below for an ARM Template excerpt when creating a Multi-Session Windows 10 VM to use as your Gold Image. Note the imageReference SKU below “win10-21h2-avd-g2”. For personal desktops, use the “21h1-ent-g2” SKU instead. Ensure that if you use the Generation 2 VM images or Accelerated Networking that these parameters need to be reflected across all script blocks from this post.

{
  "name": "[parameters('virtualMachineName')]",
  "type": "Microsoft.Compute/virtualMachines",
  "apiVersion": "2021-07-01",
  "location": "[parameters('location')]",
  "dependsOn": [
    "[concat('Microsoft.Network/networkInterfaces/', parameters('networkInterfaceName'))]"
  ],
  "properties": {
    "hardwareProfile": {
      "vmSize": "[parameters('virtualMachineSize')]"
    },
    "storageProfile": {
      "osDisk": {
        "createOption": "fromImage",
        "managedDisk": {
          "storageAccountType": "[parameters('osDiskType')]"
        },
        "deleteOption": "[parameters('osDiskDeleteOption')]"
      },
      "imageReference": {
        "publisher": "MicrosoftWindowsDesktop",
        "offer": "Windows-10",
        "sku": "win10-21h2-avd-g2",
        "version": "latest"
      }
    }
  }
}

The next step is to log into the VM and run updates, install corporate software, configure licensing, and set up your profile management solution (FSLogix configuration for AppMasking and Profile Management will be covered in a future post). Tools such as SCCM and Azure Automation can used to deploy software to the VM in an automated fashion. Azure DevOps Pipelines be used to trigger an Automation runbook for automated software deployment. Once ready, shut down and deallocate the VM.

Prepare the Gold Image VM

When an image is created using PowerShell, the Operating system state can be set to either Generalized or Specialized. Generalized images clear configuration for hostname, users and osProfile on the VM. These means that when multiple VMs are created from the one image, their admin user and hostname are configured during deployment which is what we need for an AVD Gold Image. After generalizing a VM, the VM becomes unusable. Before generalizing, you can take a Snapshot of the VM or take a backup using a Recovery Services Vault. You can then restore the VM from the Snapshot or backup to make edits to your Gold Image for a future image version. If you joined your Gold Image VM to a domain, you should remove it from the domain before Generalizing. Create a PowerShell .ps1 with the following code:

If (Test-Path -Path C:\Windows\Panther) {
  Remove-Item C:\Windows\Panther -Recurse -Force
}
cmd.exe /c "start /b %WINDIR%\system32\sysprep\sysprep.exe /generalize /shutdown /oobe"

These Azure CLI scripts will take a Snapshot of and Generalize the VM. The script you have just created will be referenced by the parameter –scripts below.

#Set the subscription Id
az account set --subscription $subscriptionId

#Get the disk Id
$diskId=$(az disk show --name "AVD_GOLD_IMAGE_0_0_1" --resource-group "AVD-DEMO" --query [id] -o tsv)

#Create the VM Snapshot
az snapshot create -g "AVD-DEMO" -n "AVD_GOLD_IMAGE_0_0_1" --source $diskId --hyper-v-generation "v2" --sku "Premium_LRS"

#Generalize the VM before creating an Image
az vm run-command invoke --command-id "RunPowerShellScript" --name "AVD_GOLD_IMAGE" -g "AVD-DEMO" --scripts "@C:\path\to\script.ps1"

#Deallocate VM
az vm deallocate -g "AVD-DEMO" -n "AVD_GOLD_IMAGE"

#Mark VM as Generalized
az vm generalize -g "AVD-DEMO" -n "AVD_GOLD_IMAGE"

Restore the Gold Image VM for image versioning

Use the following Azure CLI script to create a new Gold Image VM from the snapshot when you need to update your Gold Image. Ensure that the –size-gb parameter is the same size or greater than your Gold Image disk.

#Set the subscription Id
az account set --subscription $subscriptionId

#Get the snapshot Id
$snapshotId=$(az snapshot show --name "AVD_GOLD_IMAGE_0_0_1" --resource-group "AVD-DEMO" --query [id] -o tsv)

#Create a new Managed Disks using the snapshot Id - MAKE SURE SIZE MATCHES SNAPSHOT
az disk create --resource-group "AVD-DEMO" --name "AVD_GOLD_IMAGE_OsDisk_1" --sku "Premium_LRS" --size-gb 128 --hyper-v-generation "v2" --source $snapshotId

#Create VM by attaching created managed disks as OS
az vm create --name "AVD_GOLD_IMAGE" --resource-group "AVD-DEMO" --attach-os-disk "AVD_GOLD_IMAGE_OsDisk_2" --os-type "Windows"

The final step is create a Shared Image to be stored in the Compute Gallery. The information required for creating an image is:

  • The name of the Image
  • The name of the Compute Gallery
  • The name of the Resource Group the Compute Gallery resides in
  • The resource ID being used to create the image
  • The OS Type (Windows or Linux)
  • The OS State for the image (Specialized or Generalized)
  • The user-defined version number for the image

The best practice version number convention for images is MajorVersion.MinorVersion.Patch. A VM image can also be replicated to multiple regions for redundancy and faster provisioning of desktops in that region.

See below for an AzureCLI sample for creating a Compute Gallery image from a VM. Be sure to set –hyper-v-generation to v2 for Generation 2 VMs.

az sig image-definition create --resource-group "AVD-DEMO" \
--gallery-name "AVD_GALLERY" --gallery-image-definition "AVD_GOLD_IMAGE" \
--publisher "MicrosoftWindowsDesktop" --offer "Windows-10" --sku "win10-21h2-avd-g2" \
--os-type "Windows" --os-state "Generalized" --hyper-v-generation V2

az sig image-version create --resource-group "AVD-DEMO" \
--gallery-name "AVD_GALLERY" --gallery-image-definition "AVD_GOLD_IMAGE" \
--gallery-image-version 0.0.1 \
--managed-image "/subscriptions/xxx/resourceGroups/AVD-DEMO/providers/Microsoft.Compute/virtualMachines/AVD_GOLD_IMAGE" \
--target-regions "australiaeast=premium_lrs australiasoutheast=premium_lrs" --storage-account-type "Premium_LRS"

See below for a Terraform sample for creating a Compute Gallery image from a VM. Use terraform import to import the Resource Group, Virtual Network, Subnet, Network Interface and Virtual Machine if already created.

resource "azurerm_shared_image_gallery" "example" {
  name                = "AVD_GALLERY"
  resource_group_name = azurerm_shared_image_gallery.example.name
  location            = azurerm_resource_group.example.location
}

resource "azurerm_shared_image" "example" {
  name                = "AVD-GOLD-IMAGE"
  gallery_name        = azurerm_shared_image_gallery.example.name
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  specialized         = false
  os_type             = "Windows"
  hyper_v_generation  = "V2"

  identifier {
    publisher = "MicrosoftWindowsDesktop"
    offer     = "Windows-10"
    sku       = "win10-21h2-avd-g2"
  }
}

resource "azurerm_shared_image_version" "example" {
  name                = "0.0.1"
  gallery_name        = azurerm_shared_image_gallery.example.name
  image_name          = azurerm_shared_image.example.name
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  managed_image_id    = azurerm_virtual_machine.example.id

  target_region {
    name                   = azurerm_resource_group.example.location
    regional_replica_count = 1
    storage_account_type   = "Standard_LRS"
  }
}

Now for the final step. You can now incorporate the Compute Gallery image into the Host Pool ARM template. See below for the relevant configuration changes to the sessionHostConfigurationImageCustomInfoProps section and the imageInfo section within the sessionHostConfigurations section of the Host Pool ARM Template.

"sessionHostConfigurationImageCustomInfoProps": {
    "resourceId": "/subscriptions/xxx/resourceGroups/AVD-DEMO/providers/Microsoft.Compute/galleries/AVD_GALLERY/images/AVD-GOLD-IMAGE/versions/0.0.1"
}
{
    "name": "default",
    "apiVersion": "[parameters('apiVersion')]",
    "type": "sessionHostConfigurations",
    "dependsOn": [
        "[resourceId('Microsoft.DesktopVirtualization/hostpools/', parameters('hostpoolName'))]"
    ],
    "properties": {
        "vmSizeId": "[parameters('vmSize')]",
        "diskInfo": {
            "type": "[parameters('vmDiskType')]"
        },
        "customConfigurationTemplateUrl": "",
        "customConfigurationParameterUrl": "",
        "imageInfo": {
            "type": "CustomImage",
            "marketPlaceInfo": "",
            "customInfo": "variables('sessionHostConfigurationImageCustomInfoProps')"}
        }
    }
}

The Gold Image, with all preconfigured software, will now be used to create the session hosts! Gold Images created in this way can also be used for Windows 365 Enterprise Cloud PC.

In future posts, I will cover FsLogix Profile Management and creating Host Pools and Application Groups using Azure DevOps.