Terraform is a tool that enables you to completely automate infrastructure builds through configuration files. It provides versioning for configurations, which makes it easy to deploy and maintain your existing Windows Virtual Desktop deployments on Microsoft Azure.
The following guide below describes how to deploy a new host pool or modify an existing host pool within Windows Virtual Desktop using Terraform.
Note: Terraform is an open source tool hosted in GitHub. As such, it is published "as is" with no implied support from Microsoft or any other organization. However, we would like to welcome you to open issues using GitHub issues to collaborate toward future improvements to the tool. Special thanks to Matt Betts for his major contribution.
Overview and requirements
The steps listed below must be completed in order to deploy a Windows Virtual Desktop host pool with Terraform.
- Ensure that you meet the requirements for Windows Virtual Desktop.
- DC/AAD DS
- WVD tenant must be created
- TenantCreator role must be assigned
- VNET configured with Layer 3 access to DC/AAD DS
- Terraform must be installed and configured as outlined here.
- Terraform code from GitHub repository is downloaded to a local folder.
- Terraform files variables.tf and variables_tags.tf are update.
- Terraform deployment is started. A sample process for deploying available here.
- terraform init
- terraform plan
- terraform apply
- Validate session host VMs are deployed and heart beating via Get-RdsSessionHost.
Setting up Terraform
When you are new to Terraform. Please have a look at this article outlines the steps needed to get started with Visual Studio Code, Terraform and Azure.
Preparing Azure subscription and WVD for Terraform
Preparing the Azure subscription mean that we need to make sure that the account we are going to be used has the necessary permission to deploy new resources. Additionally, prior to updating the Terraform scripts create a resource group that will be tied to the Terraform deployment.
When it comes to WVD the preparation steps cover:
- Granting TenantCreator to the user account we are going to be using
- Creating a WVD tenant
Getting access to Terraform templates
To start all files that are listed in the folder must be downloaded to a local folder. All Terraform files needed for deployment are available at this repository.
Below is a brief description for each file and its purpose.
Availability_set.tf
This file contains the setting needed to set the availability set of VMs. In most basic deployments this file does not require changes.
Outputs.tf
This file displays certain variables that should be captured at the end of the execution. A detailed description of outputs in Terraforms can be found here. In most basic deployments this file does not require changes.
Variables.tf
This file contains all the modifiable input variables that define the behavior and outcome of running terraforms.
Variables_tags.tf
This file contains can be used to define custom tags as they are used throughout Terraforms. In most basic deployments this file does not require changes. This document outlines the benefits of using tags.
Virtual_machine.tf
This file contains code needed for setting up the individual VMs and their configuration. In most basic deployments this file does not require changes.
Virtual_machine_extensions.tf
This file contains code needed for running the customer script extensions that perform:
- Domain join
- Registration of the VM with the WVD service.
Configuring Terraform
Prior to running the Terraform variables.tf must be modified to reflect your environment. The table that follows outlines each input parameter and what is to be set to when deploying Windows Virtual Desktop.
Name |
Description |
Type |
Default |
Required |
subnet_id |
ID of the Subnet in which the machines will exist. |
String |
- |
Yes |
tenant_app_password |
The password of the tenant app. |
String |
- |
Yes |
tenant_app_id |
UPN for the user with permissions in WVD allowing for creation of a host pool (RD Contributor and/or RD Owner). |
String |
- |
Yes |
aad_tenant_id |
Azure tenant ID. |
String |
- |
Yes |
ou_path |
OU path to use when domain joining. |
String |
- |
Yes |
log_analytics_workspace_id |
Workspace ID of the Log Analytics Workspace to associate the session host VMs to. |
String |
- |
Yes |
vm_timezone |
Defines the time zone which a VM is going to use. List of time zone names available here. |
String |
- |
Yes |
log_analytics_workspace_primary_shared_key |
Primary Shared Key of the Log Analytics Workspace to associate the VMs with. |
String |
- |
Yes |
resource_group_name |
Name of the resource group in which Terraform will deploy resources. This group must be created manually before deploying. |
String |
- |
Yes |
region |
The region in which to deploy the resources. The region must be such that the newly provisioned VM can communicate with the domain controller. |
String |
- |
Yes |
host_pool_name |
Name of the session host pool. |
String |
- |
Yes |
vm_prefix |
Prefix to be added to each VM as host name. |
String |
- |
Yes |
tenant_name |
Name of WVD tenant. |
String |
- |
Yes |
rdsh_count |
Number of session host VM to be deployed. |
Int |
1 |
Only if deploying more than 1 |
managed_disk_type |
The type of managed disk(s) to attach. |
String |
Standard_LRS |
No |
tenantLocation |
The region in which the RDS tenant exists. |
String |
eastus |
No |
vm_size |
VM size. Full list of SKUs available here. |
String |
Standard_F2s |
No |
nsg_id |
The ID of the NSG to associate the network interface. |
String |
- |
No |
existing_tenant_group_name |
(deprecated) Name of the WVD tenant group. |
String |
Default Tenant Group |
No |
base_url |
The URL in which the RDS components exists. This will need to be modified if the Github repo is forked. |
String |
https://raw.githubusercontent.com/Azure/RDS-Templates/master/wvd-templates |
No |
managed_disk_sizes |
The sizes of the optional managed data disks. |
List (String) |
- |
No |
host_pool_description |
Description of the session host pool. |
String |
Created through Terraform template |
No |
is_service_principal |
Is a service principal being used for configuring WVD. |
String |
true |
No |
RDBrokerURL |
URL of the RD Broker. |
String |
No |
|
as_platform_fault_domain_count |
Int |
3 |
No |
|
as_platform_update_domain_count |
Int |
5 |
No |
|
extension_bginfo |
Should BGInfo be attached to all servers. |
String |
true |
No |
extension_loganalytics |
Should Log Analytics agent be attached to all servers. |
String |
true |
No |
extension_custom_script |
Should a custom script extension be run on all servers. |
String |
false |
No |
local_admin_username |
Name of the local admin account that will be created on each of the VM. |
String |
rdshadm |
No |
domain_joined |
Defines if a domain join is to be performed. |
String (Bool) |
true |
No |
registration_expiration_hours |
The registration token expiration window (in hours). |
String |
48 |
No |
vm_storage_os_disk_size |
The size of the OS disk. |
String |
128 |
No |
vm_version |
Version of the VM image. |
String |
- |
If vm_image_id is not set |
vm_sku |
The SKU of the VM image. |
String |
- |
If vm_image_id is not set |
vm_offer |
Offer of the VM image. |
String |
- |
If vm_image_id is not set |
vm_publisher |
Publisher of the base image to be used for provisioning the session host VMs. |
String |
- |
If vm_image_id is not set |
extensions_custom_script_fileuris |
File URIs to be consumed by the custom script extension |
List (String) |
- |
If extension_custom_script is set to true |
extensions_custom_command |
Command for the custom script extension to run |
String |
- |
If extension_custom_script is set to true |
domain_name |
Domain name of the domain to which the session host VMs are to be joined. |
String |
- |
If domain_joined is set to true |
domain_user_upn |
UPN of domain account that has permissions to perform domain join. |
String |
- |
If domain_joined is set to true |
domain_password |
Password of the domain account that will perform the domain join. |
String |
- |
If domain_joined is set to true |
vm_image_id |
ID of the custom image to use. |
String |
- |
If no vm image attributes are set |
Deploying with Terraform
This is the main section of this document as it covers the core steps needed to deploy WVD host pool with Terraform:
- Download or “fork” all Terraform scripts in a local directory.
- Open Visual Studio Code (VSC) and select File > Open Folder, and then point to the local folder where Terraform scripts have been downloaded.
- Update variables.tf.
- In VSC press Ctrl + Shift + P and select Azure Terraform: Init
- Once this completes Ctrl + Shift + P and select Azure Terraform: Init
- Press Ctrl + Shift + P and select Azure Terraform: Plan
- Review the generated plan
- Press Ctrl + Shift + P and select
- Azure Terraform: Apply
Troubleshooting Terraform deployment
Terraform deployment can fail in two main categories:
- Issues with Terraform code
- Issues with Desired State Configuration (DSC)
Issues with Terraform code
While it is rare to have issues with the Terraform code it is still possible, however most often errors are due to bad input in variables.tf.
- If there are errors in the Terraform code, please file a GitHub issue.
- If there are warning in the Terraform code feel free to ignore or address for your own instance of that code.
- Using Terraform error messages it's a good starting point towards identifying issues with input variables
Issues with DSC
To troubleshoot this type of issue, navigate to the Azure portal and if needed reset the password on the VM that failed DSC. Once you are able to log in to the VM review the log files in the following two folders:
Note: XXX, YY, and ZZ are version numbers that will change based.
- C:\Packages\Plugins\Microsoft.Compute.CustomScriptExtension\XXX\Downloads\YY
- C:\WindowsAzure\Logs\Plugins\Microsoft.Compute.CustomScriptExtension\ZZZ
To walk you through the processes outlined in this post, please watch my video tutorial: