Configurare gli host di sessione di Desktop virtuale Azure con Terraform

Questo articolo illustra come creare host sessione e distribuirli in un pool di host AVD con Terraform. Questo articolo presuppone che l'infrastruttura di Desktop virtuale Azure sia già stata distribuita.

Articolo testato con le versioni del provider Terraform e Terraform seguenti:

Vedere altre informazioni sull'uso di Terraform in Azure

In questo articolo vengono illustrate le operazioni seguenti:

  • Usare Terraform per creare una scheda di interfaccia di rete per ogni host di sessione
  • Usare Terraform per creare una macchina virtuale per l'host sessione
  • Aggiungere una macchina virtuale al dominio
  • Registrare una macchina virtuale con Desktop virtuale Azure
  • Usare il file delle variabili

1. Configurare l'ambiente

  • Sottoscrizione di Azure: se non si ha una sottoscrizione di Azure, creare un account gratuito prima di iniziare.

2. Implementare il codice Terraform

  1. Creare una directory in cui testare il codice Terraform di esempio e impostarla come directory corrente.

  2. Creare un file denominato providers.tf e inserire il codice seguente.

    terraform {
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~>2.0"
        }
        azuread = {
          source = "hashicorp/azuread"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    

    Punti principali:

    • Usare count per indicare il numero di risorse che verranno create
    • Fa riferimento alle risorse create al momento della compilazione dell'infrastruttura, ad esempio azurerm_subnet.subnet.id e azurerm_virtual_desktop_host_pool.hostpool.name. Se è stato modificato il nome di queste risorse da tale sezione, è necessario aggiornare anche i riferimenti qui.
  3. Creare un file denominato main.tf e inserire il codice seguente:

    locals {
      registration_token = azurerm_virtual_desktop_host_pool_registration_info.registrationinfo.token
    }
    
    resource "random_string" "AVD_local_password" {
      count            = var.rdsh_count
      length           = 16
      special          = true
      min_special      = 2
      override_special = "*!@#?"
    }
    
    resource "azurerm_resource_group" "rg" {
      name     = var.rg
      location = var.resource_group_location
    }
    
    resource "azurerm_network_interface" "avd_vm_nic" {
      count               = var.rdsh_count
      name                = "${var.prefix}-${count.index + 1}-nic"
      resource_group_name = azurerm_resource_group.rg.name
      location            = azurerm_resource_group.rg.location
    
      ip_configuration {
        name                          = "nic${count.index + 1}_config"
        subnet_id                     = azurerm_subnet.subnet.id
        private_ip_address_allocation = "dynamic"
      }
    
      depends_on = [
        azurerm_resource_group.rg
      ]
    }
    
    resource "azurerm_windows_virtual_machine" "avd_vm" {
      count                 = var.rdsh_count
      name                  = "${var.prefix}-${count.index + 1}"
      resource_group_name   = azurerm_resource_group.rg.name
      location              = azurerm_resource_group.rg.location
      size                  = var.vm_size
      network_interface_ids = ["${azurerm_network_interface.avd_vm_nic.*.id[count.index]}"]
      provision_vm_agent    = true
      admin_username        = var.local_admin_username
      admin_password        = var.local_admin_password
    
      os_disk {
        name                 = "${lower(var.prefix)}-${count.index + 1}"
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
      }
    
      source_image_reference {
        publisher = "MicrosoftWindowsDesktop"
        offer     = "Windows-10"
        sku       = "20h2-evd"
        version   = "latest"
      }
    
      depends_on = [
        azurerm_resource_group.rg,
        azurerm_network_interface.avd_vm_nic
      ]
    }
    
    resource "azurerm_virtual_machine_extension" "domain_join" {
      count                      = var.rdsh_count
      name                       = "${var.prefix}-${count.index + 1}-domainJoin"
      virtual_machine_id         = azurerm_windows_virtual_machine.avd_vm.*.id[count.index]
      publisher                  = "Microsoft.Compute"
      type                       = "JsonADDomainExtension"
      type_handler_version       = "1.3"
      auto_upgrade_minor_version = true
    
      settings = <<SETTINGS
        {
          "Name": "${var.domain_name}",
          "OUPath": "${var.ou_path}",
          "User": "${var.domain_user_upn}@${var.domain_name}",
          "Restart": "true",
          "Options": "3"
        }
    SETTINGS
    
      protected_settings = <<PROTECTED_SETTINGS
        {
          "Password": "${var.domain_password}"
        }
    PROTECTED_SETTINGS
    
      lifecycle {
        ignore_changes = [settings, protected_settings]
      }
    
      depends_on = [
        azurerm_virtual_network_peering.peer1,
        azurerm_virtual_network_peering.peer2
      ]
    }
    
    resource "azurerm_virtual_machine_extension" "vmext_dsc" {
      count                      = var.rdsh_count
      name                       = "${var.prefix}${count.index + 1}-avd_dsc"
      virtual_machine_id         = azurerm_windows_virtual_machine.avd_vm.*.id[count.index]
      publisher                  = "Microsoft.Powershell"
      type                       = "DSC"
      type_handler_version       = "2.73"
      auto_upgrade_minor_version = true
    
      settings = <<-SETTINGS
        {
          "modulesUrl": "https://wvdportalstorageblob.blob.core.windows.net/galleryartifacts/Configuration_09-08-2022.zip",
          "configurationFunction": "Configuration.ps1\\AddSessionHost",
          "properties": {
            "HostPoolName":"${azurerm_virtual_desktop_host_pool.hostpool.name}"
          }
        }
    SETTINGS
    
      protected_settings = <<PROTECTED_SETTINGS
      {
        "properties": {
          "registrationInfoToken": "${local.registration_token}"
        }
      }
    PROTECTED_SETTINGS
    
      depends_on = [
        azurerm_virtual_machine_extension.domain_join,
        azurerm_virtual_desktop_host_pool.hostpool
      ]
    }
    
  4. Creare un file denominato variables.tf e inserire il codice seguente:

variable "resource_group_location" {
  default     = "eastus"
  description = "Location of the resource group."
}

variable "rg" {
  type        = string
  default     = "rg-avd-compute"
  description = "Name of the Resource group in which to deploy session host"
}

variable "rdsh_count" {
  description = "Number of AVD machines to deploy"
  default     = 2
}

variable "prefix" {
  type        = string
  default     = "avdtf"
  description = "Prefix of the name of the AVD machine(s)"
}

variable "domain_name" {
  type        = string
  default     = "infra.local"
  description = "Name of the domain to join"
}

variable "domain_user_upn" {
  type        = string
  default     = "domainjoineruser" # do not include domain name as this is appended
  description = "Username for domain join (do not include domain name as this is appended)"
}

variable "domain_password" {
  type        = string
  default     = "ChangeMe123!"
  description = "Password of the user to authenticate with the domain"
  sensitive   = true
}

variable "vm_size" {
  description = "Size of the machine to deploy"
  default     = "Standard_DS2_v2"
}

variable "ou_path" {
  default = ""
}

variable "local_admin_username" {
  type        = string
  default     = "localadm"
  description = "local admin username"
}

variable "local_admin_password" {
  type        = string
  default     = "ChangeMe123!"
  description = "local admin password"
  sensitive   = true
}
  1. Creare un file denominato output.tf e inserire il codice seguente:
output "location" {
  description = "The Azure region"
  value       = azurerm_resource_group.rg.location
}

output "session_host_count" {
  description = "The number of VMs created"
  value       = var.rdsh_count
}

output "dnsservers" {
  description = "Custom DNS configuration"
  value       = azurerm_virtual_network.vnet.dns_servers
}

output "vnetrange" {
  description = "Address range for deployment vnet"
  value       = azurerm_virtual_network.vnet.address_space
}
  1. Creare un file denominato terraform.tfvars e inserire il codice seguente:

    # Customized the sample values below for your environment and either rename to terraform.tfvars or env.auto.tfvars
    
    deploy_location      = "west europe"
    rg_name              = "avd-resources-rg"
    prefix               = "avdtf"
    local_admin_username = "localadm"
    local_admin_password = "ChangeMe123$"
    vnet_range           = ["10.1.0.0/16"]
    subnet_range         = ["10.1.0.0/24"]
    dns_servers          = ["10.0.1.4", "168.63.129.16"]
    aad_group_name       = "AVDUsers"
    domain_name          = "infra.local"
    domain_user_upn      = "admin"     # do not include domain name as this is appended
    domain_password      = "ChangeMe123!"
    ad_vnet              = "infra-network"
    ad_rg                = "infra-rg"
    avd_users = [
      "avduser01@infra.local",
      "avduser01@infra.local"
    ]
    

3. Inizializzare Terraform

Per inizializzare la distribuzione di Terraform, eseguire terraform init. Questo comando scarica il provider di Azure necessario per gestire le risorse di Azure.

terraform init -upgrade

Punti principali:

  • Il parametro -upgrade aggiorna i plug-in del provider necessari alla versione più recente conforme ai vincoli di versione della configurazione.

4. Creare un piano di esecuzione terraform

Eseguire terraform plan per creare un piano di esecuzione.

terraform plan -out main.tfplan

Punti principali:

  • Il comando terraform plan consente di creare un piano di esecuzione, ma non di eseguirlo. Determina invece le azioni necessarie per creare la configurazione specificata nei file di configurazione. Questo modello consente di verificare se il piano di esecuzione corrisponde alle aspettative prima di apportare modifiche alle risorse effettive.
  • Il parametro -out facoltativo consente di specificare un file di output per il piano. L'uso del parametro -out garantisce che il piano esaminato sia esattamente quello che viene applicato.

5. Applicare un piano di esecuzione terraform

Eseguire terraform apply per applicare il piano di esecuzione all'infrastruttura cloud.

terraform apply main.tfplan

Punti principali:

  • Il comando terraform apply di esempio presuppone che in precedenza sia stato eseguito terraform plan -out main.tfplan.
  • Se è stato specificato un nome di file diverso per il parametro -out, usare lo stesso nome di file nella chiamata a terraform apply.
  • Se non è stato usato il parametro -out, chiamare terraform apply senza parametri.

6. Verificare i risultati

  1. Nella portale di Azure selezionare Desktop virtuale Azure.
  2. Selezionare Pool di host e quindi nome della risorsa creata dal pool.
  3. Selezionare Host sessione e quindi verificare che l'host di sessione sia elencato.

7. Pulire le risorse

Quando le risorse create tramite Terraform non sono più necessarie, eseguire i passaggi seguenti:

  1. Eseguire il piano Terraform e specificare il flag destroy.

    terraform plan -destroy -out main.destroy.tfplan
    

    Punti principali:

    • Il comando terraform plan consente di creare un piano di esecuzione, ma non di eseguirlo. Determina invece le azioni necessarie per creare la configurazione specificata nei file di configurazione. Questo modello consente di verificare se il piano di esecuzione corrisponde alle aspettative prima di apportare modifiche alle risorse effettive.
    • Il parametro -out facoltativo consente di specificare un file di output per il piano. L'uso del parametro -out garantisce che il piano esaminato sia esattamente quello che viene applicato.
  2. Eseguire terraform apply per applicare il piano di esecuzione.

    terraform apply main.destroy.tfplan
    

Risolvere i problemi di Terraform in Azure

Risolvere i problemi comuni relativi all'uso di Terraform in Azure

Passaggi successivi