VM Image Builder 및 PowerShell을 사용하여 Azure Virtual Desktop 이미지 만들기

적용 대상: ✔️ Windows VM

이 문서에서는 다음과 같은 사용자 지정을 사용하여 Azure Virtual Desktop 이미지를 만드는 방법을 알아봅니다.

이 문서에서는 Azure VM Image Builder를 사용하여 사용자 지정을 자동화하는 방법에 대해 설명합니다. 그런 다음, 이미지를 Azure Compute Gallery(이전의 Shared Image Gallery)에 배포하여 다른 지역에 복제하고, 규모를 제어하고, 조직 내부 및 외부에서 이미지를 공유할 수 있습니다.

VM Image Builder 구성의 배포를 간소화하기 위해 다음 예제에서는 VM Image Builder 템플릿이 내부에 중첩된 Azure Resource Manager 템플릿을 사용합니다. 이 방법은 변수 및 매개 변수 입력과 같은 몇 가지 추가 이점을 제공합니다. 명령줄에서 매개 변수를 전달할 수도 있습니다.

이 문서는 복사하여 붙여넣기 연습으로 작성되었습니다.

참고 항목

GitHub에서 앱을 설치하기 위한 스크립트를 찾을 수 있습니다. 이러한 스크립트는 일러스트레이션 및 테스트 목적으로만 사용됩니다. 프로덕션 워크로드에는 사용하지 마세요.

Windows 이미지를 빌드하기 위한 팁

  • VM 크기: Windows의 경우 Standard_D2_v2 이상을 사용합니다. 기본 크기는 Windows에 적합하지 않은 Standard_D1_v2입니다.

  • 이 문서에서는 PowerShell 사용자 지정자 스크립트를 사용합니다. 다음 설정을 사용합니다. 그렇지 않으면 빌드에서 응답을 중지합니다.

      "runElevated": true,
      "runAsSystem": true,
    

    예시:

      {
          "type": "PowerShell",
          "name": "installFSLogix",
          "runElevated": true,
          "runAsSystem": true,
          "scriptUri": "https://raw.githubusercontent.com/azure/azvmimagebuilder/main/solutions/14_Building_Images_WVD/0_installConfFsLogix.ps1"
    
  • 코드 주석 달기: VM Image Builder 빌드 로그인 customization.log는 자세한 정보입니다. 'write-host'를 사용하여 스크립트에 주석을 달면 로그로 보내지므로 문제 해결이 더 쉬워집니다.

     write-host 'AIB Customization: Starting OS Optimizations script'
    
  • 종료 코드: VM Image Builder는 모든 스크립트에서 0 종료 코드를 반환한다고 예상합니다. 0이 아닌 종료 코드를 사용하는 경우 VM Image Builder에서 사용자 지정에 실패하고 빌드를 중지합니다. 복잡한 스크립트가 있는 경우 계측을 추가하고 종료 코드를 내보냅니다. 그러면 customization.log 파일에 표시됩니다.

     Write-Host "Exit code: " $LASTEXITCODE
    
  • 테스트: 독립 실행형 VM에서 코드를 테스트하고 다시 테스트합니다. 사용자 프롬프트가 없는지, 올바른 권한을 사용하고 있는지 등을 확인합니다.

  • 네트워킹: Set-NetAdapterAdvancedProperty가 최적화 스크립트에서 설정되지만 VM Image Builder 빌드에 실패합니다. 네트워크 연결이 끊어지므로 주석 처리됩니다. Microsoft는 이 문제를 조사하고 있습니다.

필수 조건

최신 Azure PowerShell cmdlet이 설치되어 있어야 합니다. 자세한 내용은 Azure PowerShell 개요를 참조하세요.

# Check to ensure that you're registered for the providers and RegistrationState is set to 'Registered'
Get-AzResourceProvider -ProviderNamespace Microsoft.VirtualMachineImages
Get-AzResourceProvider -ProviderNamespace Microsoft.Storage 
Get-AzResourceProvider -ProviderNamespace Microsoft.Compute
Get-AzResourceProvider -ProviderNamespace Microsoft.KeyVault
Get-AzResourceProvider -ProviderNamespace Microsoft.ContainerInstance

# If they don't show as 'Registered', run the following commented-out code

## Register-AzResourceProvider -ProviderNamespace Microsoft.VirtualMachineImages
## Register-AzResourceProvider -ProviderNamespace Microsoft.Storage
## Register-AzResourceProvider -ProviderNamespace Microsoft.Compute
## Register-AzResourceProvider -ProviderNamespace Microsoft.KeyVault
## Register-AzResourceProvider -ProviderNamespace Microsoft.ContainerInstance

환경 및 변수 설정

# Step 1: Import module
Import-Module Az.Accounts

# Step 2: get existing context
$currentAzContext = Get-AzContext

# Destination image resource group
$imageResourceGroup="avdImageDemoRg"

# Location (see possible locations in the main docs)
$location="westus2"

# Your subscription. This command gets your current subscription
$subscriptionID=$currentAzContext.Subscription.Id

# Image template name
$imageTemplateName="avd10ImageTemplate01"

# Distribution properties object name (runOutput). Gives you the properties of the managed image on completion
$runOutputName="sigOutput"

# Create resource group
New-AzResourceGroup -Name $imageResourceGroup -Location $location

권한, 사용자 ID 및 역할

  1. 사용자 ID를 만듭니다.

    # setup role def names, these need to be unique
    $timeInt=$(get-date -UFormat "%s")
    $imageRoleDefName="Azure Image Builder Image Def"+$timeInt
    $identityName="aibIdentity"+$timeInt
    
    ## Add Azure PowerShell modules to support AzUserAssignedIdentity and Azure VM Image Builder
    'Az.ImageBuilder', 'Az.ManagedServiceIdentity' | ForEach-Object {Install-Module -Name $_ -AllowPrerelease}
    
    # Create the identity
    New-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName -Location $location
    
    $identityNameResourceId=$(Get-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName).Id
    $identityNamePrincipalId=$(Get-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName).PrincipalId
    
    
  2. ID에서 이미지를 배포하기 위한 권한을 할당합니다. 다음 명령은 이전에 지정된 매개 변수를 사용하여 템플릿을 다운로드하고 업데이트합니다.

    $aibRoleImageCreationUrl="https://raw.githubusercontent.com/azure/azvmimagebuilder/main/solutions/12_Creating_AIB_Security_Roles/aibRoleImageCreation.json"
    $aibRoleImageCreationPath = "aibRoleImageCreation.json"
    
    # Download the config
    Invoke-WebRequest -Uri $aibRoleImageCreationUrl -OutFile $aibRoleImageCreationPath -UseBasicParsing
    
    ((Get-Content -path $aibRoleImageCreationPath -Raw) -replace '<subscriptionID>',$subscriptionID) | Set-Content -Path $aibRoleImageCreationPath
    ((Get-Content -path $aibRoleImageCreationPath -Raw) -replace '<rgName>', $imageResourceGroup) | Set-Content -Path $aibRoleImageCreationPath
    ((Get-Content -path $aibRoleImageCreationPath -Raw) -replace 'Azure Image Builder Service Image Creation Role', $imageRoleDefName) | Set-Content -Path $aibRoleImageCreationPath
    
    # Create a role definition
    New-AzRoleDefinition -InputFile  ./aibRoleImageCreation.json
    
    # Grant the role definition to the VM Image Builder service principal
    New-AzRoleAssignment -ObjectId $identityNamePrincipalId -RoleDefinitionName $imageRoleDefName -Scope "/subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup"
    

참고 항목

“New-AzRoleDefinition: 역할 정의 한도가 초과되었습니다. 더 이상 역할 정의를 만들 수 없습니다.” 오류가 표시되면 Azure RBAC(역할 기반 액세스 제어) 문제 해결을 참조하세요.

Azure Compute Gallery가 아직 없는 경우 새로 만들어야 합니다.

$sigGalleryName= "myaibsig01"
$imageDefName ="win10avd"

# Create the gallery
New-AzGallery -GalleryName $sigGalleryName -ResourceGroupName $imageResourceGroup  -Location $location

# Create the gallery definition
New-AzGalleryImageDefinition -GalleryName $sigGalleryName -ResourceGroupName $imageResourceGroup -Location $location -Name $imageDefName -OsState generalized -OsType Windows -Publisher 'myCo' -Offer 'Windows' -Sku '10avd'

VM Image Builder 템플릿 구성

이 예제에서는 이전에 지정한 매개 변수를 사용하여 VM Image Builder 템플릿을 다운로드하고 업데이트하는 템플릿을 준비했습니다. 템플릿은 FSLogix, 운영 체제 최적화 및 Microsoft Teams를 설치하고, 마지막에 Windows 업데이트를 실행합니다.

템플릿을 열면 원본 속성에서 사용 중인 이미지를 볼 수 있습니다. 이 예제에서는 Windows 10 다중 세션 이미지를 사용합니다.

Windows 10 이미지

다중 세션과 단일 세션이라는 두 가지 주요 유형의 이미지를 알고 있어야 합니다.

다중 세션 이미지는 풀링된 사용을 위한 것입니다. Azure의 이미지 세부 정보에 대한 예제는 다음과 같습니다.

"publisher": "MicrosoftWindowsDesktop",
"offer": "Windows-10",
"sku": "20h2-avd",
"version": "latest"

단일 세션 이미지는 개별 사용을 위한 것입니다. Azure의 이미지 세부 정보에 대한 예제는 다음과 같습니다.

"publisher": "MicrosoftWindowsDesktop",
"offer": "Windows-10",
"sku": "19h2-ent",
"version": "latest"

사용 가능한 Windows 10 이미지를 변경할 수도 있습니다.

Get-AzVMImageSku -Location westus2 -PublisherName MicrosoftWindowsDesktop -Offer windows-10

템플릿을 다운로드하고 구성합니다.

이제 템플릿을 다운로드하고 사용자의 용도에 맞게 구성합니다.

$templateUrl="https://raw.githubusercontent.com/azure/azvmimagebuilder/main/solutions/14_Building_Images_WVD/armTemplateWVD.json"
$templateFilePath = "armTemplateWVD.json"

Invoke-WebRequest -Uri $templateUrl -OutFile $templateFilePath -UseBasicParsing

((Get-Content -path $templateFilePath -Raw) -replace '<subscriptionID>',$subscriptionID) | Set-Content -Path $templateFilePath
((Get-Content -path $templateFilePath -Raw) -replace '<rgName>',$imageResourceGroup) | Set-Content -Path $templateFilePath
((Get-Content -path $templateFilePath -Raw) -replace '<region>',$location) | Set-Content -Path $templateFilePath
((Get-Content -path $templateFilePath -Raw) -replace '<runOutputName>',$runOutputName) | Set-Content -Path $templateFilePath

((Get-Content -path $templateFilePath -Raw) -replace '<imageDefName>',$imageDefName) | Set-Content -Path $templateFilePath
((Get-Content -path $templateFilePath -Raw) -replace '<sharedImageGalName>',$sigGalleryName) | Set-Content -Path $templateFilePath
((Get-Content -path $templateFilePath -Raw) -replace '<region1>',$location) | Set-Content -Path $templateFilePath
((Get-Content -path $templateFilePath -Raw) -replace '<imgBuilderId>',$identityNameResourceId) | Set-Content -Path $templateFilePath

템플릿을 자유롭게 살펴봅니다. 모든 코드를 볼 수 있습니다.

템플릿 제출

템플릿을 서비스에 제출해야 합니다. 이렇게 하면 스크립트와 같은 종속 아티팩트를 다운로드하고, 유효성을 검사하고, 권한을 확인하고, IT_ 접두사가 붙은 준비 리소스 그룹에 저장합니다.

New-AzResourceGroupDeployment -ResourceGroupName $imageResourceGroup -TemplateFile $templateFilePath -TemplateParameterObject @{"api-Version" = "2020-02-14"; "imageTemplateName" = $imageTemplateName; "svclocation" = $location}

# Optional - if you have any errors running the preceding command, run:
$getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $imageResourceGroup -Name $imageTemplateName)
$getStatus.ProvisioningErrorCode 
$getStatus.ProvisioningErrorMessage

이미지 빌드

Start-AzImageBuilderTemplate -ResourceGroupName $imageResourceGroup -Name $imageTemplateName -NoWait

참고 항목

이 명령은 VM Image Builder 서비스에서 이미지 빌드를 완료할 때까지 기다리지 않으므로 여기에 표시한 대로 상태를 쿼리할 수 있습니다.

$getStatus=$(Get-AzImageBuilderTemplate -ResourceGroupName $imageResourceGroup -Name $imageTemplateName)

# Shows all the properties
$getStatus | Format-List -Property *

# Shows the status of the build
$getStatus.LastRunStatusRunState 
$getStatus.LastRunStatusMessage
$getStatus.LastRunStatusRunSubState

VM 만들기

이제 이미지가 빌드되었으므로 이 이미지에서 VM을 빌드할 수 있습니다. New-AzVM(Az PowerShell module.Compute)의 예제를 사용합니다.

리소스 정리

이 프로세스 중에 만든 리소스가 더 이상 필요하지 않은 경우 다음을 수행하여 삭제할 수 있습니다.

Important

먼저 리소스 그룹 템플릿을 삭제합니다. 리소스 그룹만 삭제하면 VM Image Builder에서 사용하는 준비 리소스 그룹(IT_)이 정리되지 않습니다.

  1. VM Image Builder 템플릿을 제거합니다.

    Remove-AzImageBuilderTemplate -ResourceGroupName $imageResourceGroup -Name vd10ImageTemplate
    
  2. 역할 할당을 삭제합니다.

    Remove-AzRoleAssignment -ObjectId $identityNamePrincipalId -RoleDefinitionName $imageRoleDefName -Scope "/subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup"
    
    ## Remove the definitions
    Remove-AzRoleDefinition -Name "$identityNamePrincipalId" -Force -Scope "/subscriptions/$subscriptionID/resourceGroups/$imageResourceGroup"
    
    ## Delete the identity
    Remove-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName -Force
    
  3. 해당 리소스 그룹을 삭제합니다.

    Remove-AzResourceGroup $imageResourceGroup -Force
    

다음 단계

더 많은 VM Image Builder 예제를 시도하려면 GitHub로 이동합니다.