이 문서에서는 Terraform을 사용하여 세션 호스트를 빌드하고 AVD 호스트 풀에 배포하는 방법을 보여 줍니다. 이 문서에서는 Azure Virtual Desktop 인프라를 이미 배포했다고 가정합니다.
다음 Terraform 및 Terraform 공급자 버전을 사용하여 테스트한 기사:
Azure에서 Terraform 사용에 대해 자세히 알아보기
이 문서에서는 다음 방법을 알아봅니다.
- Terraform을 사용하여 각 세션 호스트에 대한 NIC 만들기
- Terraform을 사용하여 세션 호스트용 VM 만들기
- VM을 도메인에 조인
- Azure Virtual Desktop에 VM 등록
- 변수 파일 사용
1. 환경 구성
- Azure 구독: Azure 구독이 아직 없는 경우 시작하기 전에 체험 계정을 만듭니다.
Terraform 구성: 아직 구성하지 않은 경우 다음 옵션 중 하나를 사용하여 Terraform을 구성합니다.
2. Terraform 코드 구현
샘플 Terraform 코드를 테스트할 디렉터리를 만들고, 이를 현재 디렉터리로 만듭니다.
providers.tf라는 파일을 만들고 다음 코드를 삽입합니다.terraform { required_providers { azurerm = { source = "hashicorp/azurerm" version = "~>2.0" } azuread = { source = "hashicorp/azuread" } } } provider "azurerm" { features {} }핵심 사항:
- 만들 리소스 수를 나타내는 데 사용합니다
count. - 인프라를 빌드할 때 생성된 리소스(예:
azurerm_subnet.subnet.id및azurerm_virtual_desktop_host_pool.hostpool.name)를 참조합니다. 해당 섹션에서 이러한 리소스의 이름을 변경한 경우 여기에서 참조를 업데이트해야 합니다.
- 만들 리소스 수를 나타내는 데 사용합니다
main.tf라는 파일을 만들고 다음 코드를 삽입합니다.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_1.0.03419.1309.zip", "configurationFunction": "Configuration.ps1\\AddSessionHost", "properties": { "HostPoolName":"${azurerm_virtual_desktop_host_pool.hostpool.name}", "UseAgentDownloadEndpoint": "true" } } 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 ] }variables.tf라는 파일을 만들고 다음 코드를 삽입합니다.
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
}
-
output.tf라는 파일을 만들고 다음 코드를 삽입합니다.
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
}
terraform.tfvars라는 파일을 만들고 다음 코드를 삽입합니다.# 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. Terraform 초기화
terraform init를 실행하여 Terraform 배포를 초기화합니다. 이 명령은 Azure 리소스를 관리하는 데 필요한 Azure 공급자를 다운로드합니다.
terraform init -upgrade
핵심 사항:
-
-upgrade매개 변수는 필요한 공급자 플러그 인을 구성의 버전 제약 조건을 준수하는 최신 버전으로 업그레이드합니다.
4. Terraform 실행 계획 만들기
terraform plan을 실행하여 실행 계획을 만듭니다.
terraform plan -out main.tfplan
핵심 사항:
-
terraform plan명령은 실행 계획을 만들지만 실행하지는 않습니다. 대신 구성 파일에 지정된 구성을 만드는 데 필요한 작업을 결정합니다. 이 패턴을 사용하면 실제 리소스를 변경하기 전에 실행 계획이 예상과 일치하는지 확인할 수 있습니다. - 선택 사항인
-out매개 변수를 사용하여 계획의 출력 파일을 지정할 수 있습니다.-out매개 변수를 사용하면 검토한 계획이 정확하게 적용됩니다.
5. Terraform 실행 계획 적용
terraform apply 명령어를 실행하여 실행 계획을 클라우드 인프라에 적용합니다.
terraform apply main.tfplan
핵심 사항:
- 예시
terraform apply명령은 이전에terraform plan -out main.tfplan를 실행했다고 가정합니다. -
-out매개 변수에 다른 파일 이름을 지정한 경우terraform apply에 대한 호출에서 동일한 파일 이름을 사용합니다. -
-out매개 변수를 사용하지 않은 경우 매개 변수 없이terraform apply를 호출합니다.
6. 결과 확인
- Azure Portal에서 Azure Virtual Desktop을 선택합니다.
- 호스트 풀을 선택한 다음, 만든 리소스 풀의 이름을 선택합니다.
- 세션 호스트를 선택한 다음 세션 호스트가 나열되는지 확인합니다.
7. 리소스 정리
Terraform을 통해 만든 리소스가 더 이상 필요하지 않은 경우 다음 단계를 수행합니다.
terraform 플랜을 실행하고
destroy플래그를 지정합니다.terraform plan -destroy -out main.destroy.tfplan핵심 사항:
-
terraform plan명령은 실행 계획을 만들지만 실행하지는 않습니다. 대신 구성 파일에 지정된 구성을 만드는 데 필요한 작업을 결정합니다. 이 패턴을 사용하면 실제 리소스를 변경하기 전에 실행 계획이 예상과 일치하는지 확인할 수 있습니다. - 선택 사항인
-out매개 변수를 사용하여 계획의 출력 파일을 지정할 수 있습니다.-out매개 변수를 사용하면 검토한 계획이 정확하게 적용됩니다.
-
terraform apply를 실행하여 실행 계획을 적용합니다.
terraform apply main.destroy.tfplan
Azure에서 Terraform 문제 해결
Azure에서 Terraform을 사용할 때 발생하는 일반적인 문제 해결