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 및 역할
사용자 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
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 만들기
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_)이 정리되지 않습니다.
VM Image Builder 템플릿을 제거합니다.
Remove-AzImageBuilderTemplate -ResourceGroupName $imageResourceGroup -Name vd10ImageTemplate
역할 할당을 삭제합니다.
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
해당 리소스 그룹을 삭제합니다.
Remove-AzResourceGroup $imageResourceGroup -Force
다음 단계
더 많은 VM Image Builder 예제를 시도하려면 GitHub로 이동합니다.