使用 VM 映像生成器创建 Azure 虚拟桌面映像

已完成

本单元介绍如何使用 Azure VM 映像生成器自动执行自定义。 然后,你可以将映像分发到 Azure Compute Gallery(以前称为共享映像库),在那里你可以将其复制到其他区域、控制规模并在组织内外共享映像。

在本单元中,你将了解如何使用以下自定义创建 Azure 虚拟桌面映像:

为了简化 VM 映像生成器配置的部署,我们的示例使用嵌套了 VM 映像生成器模板的 Azure 资源管理器模板。 此方法还有更多优势,例如变量和参数输入。

注意

你将在 GitHub 上找到用于安装应用的脚本。 请勿将这些脚本用于生产工作负载。

有关创建 Windows 映像的建议

  • VM 大小:对于 Windows,请使用 Standard_D2_v2 或更高版本。 默认大小为 Standard_D1_v2(不适合 Windows)。

  • 本单元使用 PowerShell 定制器脚本。 请使用以下设置,否则生成将停止响应。

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

    例如:

    "type": "PowerShell",
    "name": "installFSLogix",
    "runElevated": true,
    "runAsSystem": true,
    "scriptUri": "https://raw.githubusercontent.com/azure/azvmimagebuilder/master/solutions/14_Building_Images_WVD/0_installConfFSLogix.ps1"
    
  • 为代码添加注释:VM 映像生成器生成日志 customization.log 的内容很详细。 如果你使用“write-host”来注释你的脚本,则脚本将被发送到日志中,这将使故障排除更容易。

    write-host 'AIB Customization: Starting OS Optimizations script'
    
  • 退出代码:VM 映像生成器期望所有脚本返回 0 退出代码。 如果使用非零退出代码,VM 映像生成器将导致自定义失败并停止生成。 如果脚本复杂,请添加检测并发出退出代码,这些代码将显示在 customization.log 中。

    Write-Host "Exit code: " $LASTEXITCODE
    
  • 在独立 VM 上测试和重新测试代码。 确保没有用户提示、使用正确的权限等。

  • 网络:在优化脚本中设置了 Set-NetAdapterAdvancedProperty,但 VM 映像生成器生成失败。 由于此代码导致网络连接断开,因此已注释禁止此代码。

Azure PowerShell cmdlet

你必须安装最新的 Azure PowerShell cmdlet。

# 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

# 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

环境和变量

使用以下脚本设置环境和变量。

# 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

权限、用户标识和角色

使用以下脚本设置权限和用户标识。

# setup role def names 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

$identityNameResourceId=$(Get-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName).Id
$identityNamePrincipalId=$(Get-AzUserAssignedIdentity -ResourceGroupName $imageResourceGroup -Name $identityName).PrincipalId


为标识分配权限以分发映像。 以下命令下载模板,并使用之前指定的参数更新模板。

$aibRoleImageCreationUrl="https://raw.githubusercontent.com/azure/azvmimagebuilder/master/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/$imageResourceGrouprol).

如果还没有 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 映像生成器模板

你有一个模板,该模板将下载 VM 映像生成器模板,并使用之前指定的参数进行更新。 该模板安装 FSLogix、操作系统优化和 Microsoft Teams,最后运行 Windows 更新。

如果你打开模板,你可以在源属性中看到正在使用的映像。 在此示例中,它使用 Windows 10 多会话映像。

Windows 10 映像

应注意两种关键类型的映像:多会话和单会话。

多会话映像适用于共用使用。 Azure 中的映像详细信息示例如下:

"publisher": "MicrosoftWindowsDesktop",
"offer": "Windows-10",
"sku": "20h2-evd",
"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/master/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 映像生成器服务完成映像生成,因此可以查询状态,如下所示。

$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) 中的示例。