Contents

Windows Virtual Desktop with ARM and Azure DevOps

Introduction

In this post we will cover how to setup Windows Virtual Desktop ARM template with Azure DevOps. We walkthrough 2 different ARM templates. I’m using the ARM WVD templates from Microsoft: https://github.com/Azure/RDS-Templates/tree/master/ARM-wvd-templates that came earlier in 2020.

  • CreateAndProvisionHostPool
  • AddVirtualMachinesToHostPool

Figure 1: Visualized DevOps Workflow ARM pipelines

/wp-content/uploads/2020/10/image-29.png

In Figure 1, we can see that the Azure DevOps build pipeline is integrated with Azure Key Vault for secrets management. We are using Service Connection with Azure, so that the ARM templates and PowerShell scripts can run in the context of the service principal. No Password are exposed in clear text to the pipeline!
As part of the automation pipeline, one of my goals is to use Windows 10 image built using a Shared Image Gallery (SIG) built with Azure Image builder (AIB). Pointing to SIG is just part of the parameters file. I recommend using this guide to configure AIB and SIG:
https://techcommunity.microsoft.com/t5/windows-virtual-desktop/building-a-windows-10-enterprise-multi-session-master-image-with/m-p/1503913
If you don’t have SIG ready, you can optionally just use the Windows 10 SKU from Gallery if you just need a quick POC. Just change the parameters

I’ve added the “arm-wvd-CreateAndProvisionHostPool.json” and arm-wvd- to my GitHub repo, this will be used by the pipeline. ****
NB! You will need update the parameters in the “CreateAndProvisionHostPool.parameters.json” yourself. The parameters must be equal to your own environment! I will go deeper into some of the parameters used by the arm template. There are also some PowerShell scripts that the pipelines will use.
I’m by no means any expert in ARM or PowerShell, but I will cover the basics of getting these pipelines working.

The Templates and code used is available from my GitHub repo. Clone the repo, so that you can use the files from https://github.com/alventech/wvd-arm-devops

CreateAndProvisionHostPool

/wp-content/uploads/2020/10/image-31-1024x387.png

AddVirtualMachinesToHostPool

/wp-content/uploads/2020/10/image-41-1024x381.png

Prerequisites

  • Azure Subscription
  • VNET and Subnet
  • Azure Key Vault
  • Azure DevOps Project
  • Active Directory Domain or Azure Domain Services to join
  • Shared Image Gallery (Windows 10 Image)
  • GitHub or any other source control that you prefer.

Create And ProvisionHostPool

Azure DevOps Project

Let’ start by getting our Azure DevOps Project ready for the CreateAndProvisionHostPool.

Go to https://dev.azure.com/ and create your first project
Choose Project Settings to the bottom left.

/wp-content/uploads/2020/10/image-11.png

Service Connections

/wp-content/uploads/2020/10/image-12.png

Add service connection for your GitHub account and Azure Subscription.

/wp-content/uploads/2020/10/image-5-1024x339.png

Go back to the Pipeline tab on the left Side and choose New release pipeline.

/wp-content/uploads/2020/10/image.png

Create an Empty Job

/wp-content/uploads/2020/10/image-1.png

Name your Release pipeline, example “wvd.arm.create.hostpool“, and hit save.

/wp-content/uploads/2020/10/image-2.png

Artifact

From the artifacts, add your GitHub account, or the source control of your choice. Click save When You’re Done.

/wp-content/uploads/2020/10/image-6-1024x530.png

/wp-content/uploads/2020/10/image-7-255x300.png

Variable Groups

Go to the Pipelines Tab – Library and choose the Variable Groups below.

/wp-content/uploads/2020/10/image-13.png

Create a New Variable Group

/wp-content/uploads/2020/10/image-14-1024x635.png

Authorize the Key vault to your subscription and key vault name.

/wp-content/uploads/2020/10/image-15-845x1024.png

When Authorized to the key Vault, remember to add your secret name Variable. This used by the ARM template parameters.

/wp-content/uploads/2020/10/image-17.png

Paramters-CreateAndProvisionHostPool

The ARM parameters values in arm-wvd-CreateAndProvisionHostPool.paramters.json match your environment. Below I’ve just listed all the parameters that simply got from the Azure Portal, so that I could see what parameters are generated the parameter.

/wp-content/uploads/2020/10/image-42.png

I Downloaded the Template and used the parameter file generated to see how the syntax for each parameter needed to be.

/wp-content/uploads/2020/10/image-43.png

I will cover the parameters that is not obvious. So that I could more seamlessly see what parameters needs to be added. You can also “get-AzGalleryImageDefinition”. If we Look more into the Azure Share Image Gallery (SIG) parameters, All the values, was then added to the values in “vmTemplate” parameter.
The “customImageId” SIG can be found in the azure portal as well.

/wp-content/uploads/2020/10/image-9-1024x500.png

With the Parameter “vmCustomImageSourceId“, we also need to add SIG resoruce ID to this value

PowerShell Task ExpirationTime

When we have all the parameter’s updated, we ready to add the PowerShell task. The Task is used to generate the parameter value for “tokenExpirationTime“. The PowerShell task will store the variable to the next DevOps ARM Task. The Script will run “get-date” with correct format. The write-host will bring the variable to the next task.

/wp-content/uploads/2020/10/image-18-1024x342.png

Search for PowerShell, and add the task.

/wp-content/uploads/2020/10/image-19-1024x205.png

Choose File Path – Create the Display Name and choose Script Path to the “createtokenExpirationTime.ps1” script.

It’s located in the https://github.com/alventech/wvd-arm-devops/tree/main/arm-wvd-CreateAndProvisionHostPool

/wp-content/uploads/2020/10/image-20-1024x340.png

Go to Tasks – add tasks – search for ARM, add the ARM template deployment as a task.

/wp-content/uploads/2020/10/image-21-1024x184.png

Resource group and location must be equal to your environment.

/wp-content/uploads/2020/10/image-22.png

In the screenshot below you can see more of the ARM settings.
Template – Change the location to our GitHub artifact for “arm-wvd-CreateAndProvisionHostPool.json” template location.
Template parameters – Change the location to GitHub artifact for “arm-wvd-CreateAndProvisionHostPool.parameters.json” Parameters.
The templates are located in https://github.com/alventech/wvd-arm-devops/tree/main/arm-wvd-CreateAndProvisionHostPool

In the Override template parameters, we will set
administratorAccountPassword” variable and the “tokenExperationTime” is the variable from the PowerShell task we created earlier.

-administratorAccountPassword “$(wvd-ad-join)” -tokenExpirationTime “$(ExpirationTime)”

/wp-content/uploads/2020/10/image-23.png

Pipeline Variables - override “more” parameters

if you don’t like working with the “CreateAndProvisionHostPool.paramters.json“, you can just override even more parameters for example “ouPath” and “administratorAccountUsername” that you down want to be coded in the parameter json. I will recommend choosing Variables – Pipeline Variables and variables to match your needs.

/wp-content/uploads/2020/10/image-28.png

you must remember to override it the arm template as well!

/wp-content/uploads/2020/10/image-30.png

Create a new release and Deploy

If you’re done with updating all the parameters, we should be ready for a release. Create release and deploy.

/wp-content/uploads/2020/10/image-25.png

In the logs you can see that the Agent has finalized the job. Go to the troubleshooting guide at the end if you get any problems.

/wp-content/uploads/2020/10/image-26.png

Pipeline Add Virtual Machines To HostPool

When the ARM template deployment is finished, we can go to the next Pipeline – AddVirtualMachinesToHostPool. This’s probably the one, we’ll use more often for your Maintenace. To get started we must create a new release pipeline, example “wvd.arm.AddVMToHostPool“. Add you Artifact and Stage and click save.

/wp-content/uploads/2020/10/image-35.png

PowerShell Task RdsRegistration Info token

In this Task we will configure a PowerShell task with Azure Powershell.
We will use the https://github.com/alventech/wvd-arm-devops/blob/main/arm-wvd-
AddVirtualMachinesToHostPool/RdsRegistrationInfotoken.ps1 scirpt. I’ve borrowed the script from https://twitter.com/fberson, and added some small modifications. The main goal for the scirpt is to obtain the **RdsRegistrationInfotoken **and send the variable to the next task for the ARM parameter hostpoolToken.
This will ensure that we have a valid token, or generate a new if token has expired. A Token is required from the Host Pool to allow, new VM’s to a Host Pool. The write-host will bring the variable to the next task.

To get stated I will add the “Azure PowerShell”

/wp-content/uploads/2020/10/image-36.png

Before running the pipeline and the script, you will need to update the variables to your own environment. Optionally, you could just use an Inline script a Copy Past scirpt, if you prefer that.

$azureSubscriptionID = “your-wvd-sub-id”
$resourceGroupName = “rg-wvd-Pooled-desktop”
$existingWVDHostPoolName = “HostPool-Test”

Next go to the Authenticate to your Subscription to allow the task to use Service Connection and Service Principal, that will authenticate to PowerShell during the task.

/wp-content/uploads/2020/10/image-37.png

Add your Template and Template parameters, and Override template parameters

-administratorAccountPassword “$(wvd-ad-join)” -hostpoolToken “$(RdsRegistrationInfotoken)”

ARM Template Deployment Task - AddVmsToHoostPool

/wp-content/uploads/2020/11/image-1024x219.png

The last part of the pipeline is to link the variable group, so that pipeline can use the Key Vault credentials authorized to the DevOps Project earlier.

/wp-content/uploads/2020/10/image-39-1024x293.png

Create a new release and Deploy

/wp-content/uploads/2020/10/image-40-1024x343.png

You could also automate the drain Mode for your sessions host.
Like example https://www.nielskok.tech/windows-virtual-desktop/wvd-set-drain-mode-powershell/ in the pipeline. I prefer to schedule, this at a later stage since, I like to know that everything is working as it should with the new image.

Troubleshooting

During this project I’ve failed multiple times because of parameter or value that was in the wrong context. Your DevOps pipeline will give you some details about the error, but it’s not always easy to see what failed for ARM, so I prefer looking into the RAW Error from the Resource Group and Deployments tab. I really recommend investing some time in this ARM video series from https://www.youtube.com/c/SamCogan/ if you need some advice regarding test and validation in arm templates. It’s for sure helped me a lot. In the picture below the task failed because I was using the wrong prefix. Looking into the json file I see that the variable was using rdshPrefix to the vmNamePrefix.

/wp-content/uploads/2020/10/image-33-1024x368.png

Another example the passsword that did not work. A closer look to the varaible group for the pipeline, and I could see that the correct variable group was not linked.

/wp-content/uploads/2020/10/image-34.png

Update 02.06.2021 (thnx to one of my readers Ben! We found that I had a bug with spaces in the Gist Github file!) this file has been updated so that the variable with ExpirationTime will be correct ). If you copied the code prior to 02.06.2021 the variable would cause a space to be generated which could cause some issues with the parameter input.
I’ve also updated the task.setvariable that was wrong in github and gist github.

“Spaces” in DevOps task Varaible with createtokenExpirationTime.ps1

Summary

It was a nice learning curve to configure WVD ARM templates with DevOps. What I like about Azure DevOps with the ARM templates, is that it gives additional security, and flexibility and scalability when you need to do deploy across multiple environments. You can export your templates, so it’s more repeatable in your CI/CD environments. With the override parameters is quick and easy to change parameters at your needs.

Documentation

https://docs.microsoft.com/en-us/powershell/module/az.desktopvirtualization/new-azwvdhostpool?view=azps-4.8.0

https://www.christiaanbrinkhoff.com/2020/05/01/windows-virtual-desktop-technical-2020-spring-update-arm-based-model-deployment-walkthrough/

https://github.com/Azure/RDS-Templates/tree/master/ARM-wvd-templates