Intro

Azure Virtual Desktop (AVD) is a managed service that runs virtual desktops and applications in Azure. Some components are deployed and configured to fit your company’s needs, even with a managed solution. In this blog post, I will walk you through the necessary steps before any end-user can log in to the virtualized desktop. I will use Bicep code and PowerShell in this blog post, but there are more options if you prefer other languages. This blog post also starts the topic of AVD on my blog, and I intend to add more during the next weeks and months. My main focus is on automation, but there will also be a few on optimization in AVD.

In this blog, I want to get the following deployed and ready to use.

  • Host pool
  • Application groups
  • Workspace

Host pool

The host pool is a collection of machines delivering the desktops or applications you use in the AVD solution. It is where you define whether you want to host desktops or applications and set the load balancing type to either depth or breadth logins. Many companies use depth-first load balancing only to have the minimum required virtual machines running. No matter which load balancing you select, you must analyze the required number of hosts at any given time of the day and week. This analysis enables you to create scaling plans that fit your needs and allow cost savings.

Below is the most basic code for deploying a host pool.

param location string = 'WestEurope'

resource hostpool 'Microsoft.DesktopVirtualization/hostPools@2024-08-08-preview' = {
  name: 'vdpool-avd-demo'
  location: location
  properties: {
    hostPoolType: 'Pooled'
    loadBalancerType: 'DepthFirst'
    preferredAppGroupType: 'Desktop'
 }
}

Application groups

Application groups are the link between applications or desktops and end-users. To access an application, an end-user must be a member of an application group. These application groups are usually mapped one-to-one with an Entra ID security group.

Below is the code for creating an application group for remote apps and one for desktops.

resource desktop_dag 'Microsoft.DesktopVirtualization/applicationGroups@2024-08-08-preview' = {
  name: 'vdag-avd-demo-desktop'
  location: location
  properties: {
    friendlyName: 'AVD Demo Desktop'
    applicationGroupType: 'Desktop'
    hostPoolArmPath: resourceId('Microsoft.DesktopVirtualization/hostpools', hostpool.name)
 }
}

resource remote_app_dag 'Microsoft.DesktopVirtualization/applicationGroups@2024-08-08-preview' = {
  name: 'vdag-avd-demo-remoteapp'
  location: location
  properties: {
    friendlyName: 'AVD Demo remote app'
    applicationGroupType: 'RemoteApp'
    hostPoolArmPath: resourceId('Microsoft.DesktopVirtualization/hostpools', hostpool.name)
 }
}

Workspace

The last piece of the puzzle is the AVD workspace. The workspace is a collection of application groups. Each application group references a remote app or desktop; adding multiple groups to the workspace ensures all required applications are available to users. Usually, the workspace defines the audience for the combined applications presented; this can, for instance, be “Company workspace” or “External access for Company.”

Below is the code to create a workspace.

resource workspace 'Microsoft.DesktopVirtualization/workspaces@2024-08-08-preview' = {
  name: 'avd-demo'
  location: location
  properties: {
    friendlyName: 'AVD Demo'
    applicationGroupReferences: [
      resourceId('Microsoft.DesktopVirtualization/applicationGroups', desktop_dag.name)
      resourceId('Microsoft.DesktopVirtualization/applicationGroups', remote_app_dag.name)
 ]
    description: 'AVD Demo Workspace' 
 }
}

Code

I can now combine the code snippets above into a single file I name main.bicep. Below is the complete code from the file.

param location string = 'WestEurope'

resource hostpool 'Microsoft.DesktopVirtualization/hostPools@2024-08-08-preview' = {
  name: 'vdpool-avd-demo'
  location: location
  properties: {
    hostPoolType: 'Pooled'
    loadBalancerType: 'DepthFirst'
    preferredAppGroupType: 'Desktop'
 }
}

resource workspace 'Microsoft.DesktopVirtualization/workspaces@2024-08-08-preview' = {
  name: 'avd-demo'
  location: location
  properties: {
    friendlyName: 'AVD Demo'
    applicationGroupReferences: [
      resourceId('Microsoft.DesktopVirtualization/applicationGroups', desktop_dag.name)
      resourceId('Microsoft.DesktopVirtualization/applicationGroups', remote_app_dag.name)
 ]
    description: 'AVD Demo Workspace' 
 }
}

resource desktop_dag 'Microsoft.DesktopVirtualization/applicationGroups@2024-08-08-preview' = {
  name: 'vdag-avd-demo-desktop'
  location: location
  properties: {
    friendlyName: 'AVD Demo Desktop'
    applicationGroupType: 'Desktop'
    hostPoolArmPath: resourceId('Microsoft.DesktopVirtualization/hostpools', hostpool.name)
 }
}

resource remote_app_dag 'Microsoft.DesktopVirtualization/applicationGroups@2024-08-08-preview' = {
  name: 'vdag-avd-demo-remoteapp'
  location: location
  properties: {
    friendlyName: 'AVD Demo remote app'
    applicationGroupType: 'RemoteApp'
    hostPoolArmPath: resourceId('Microsoft.DesktopVirtualization/hostpools', hostpool.name)
 }
}

Pre-deployment requirements

Deploying a bicep code from your machine requires a few requirements. First, you will need to install Bicep on a Windows machine; this can be done with Winget using this command:

"winget install -e --id Microsoft.Bicep

If you are on a Mac, you can brew with the following commands:

brew tap azure/bicep
brew install bicep

It is also required to have either Azure PowerShell modules or Azure CLI installed; I will be using the Azure PowerShell modules, which I installed with this command:

Install-Module Az

Deployment

I now have the code to deploy the required resources to Azure. To simplify this first blog post, I can deploy the code to a resource group I already have using the command below.

New-AzResourceGroupDeployment -Name "AVD-Demo" -TemplateFile ./main.bicep -ResourceGroupName "rg-avd-demo"

Summary

In this blog post, I created the basic code for deploying most of the required resources for AVD. Although not a hard requirement, I will also include a storage account as a needed resource, but since it is a bit more complex and not a resource deployed with Bicep alone, I will save this resource for another post. The resources I have deployed are enough to enable the deployment of session hosts, which in turn will allow users to log into AVD and start using the applications deployed to these hosts.

Credits and sources

Microsoft Learn

https://learn.microsoft.com/en-us/azure/virtual-desktop/ https://learn.microsoft.com/en-us/azure/virtual-desktop/terminology https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations#virtual-desktop-infrastructure