Share via


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 テンプレートを使用します。 この方法では、変数やパラメーターの入力など、さらにいくつかのメリットが得られます。 これらのパラメーターをコマンド ラインから渡すこともできます。

この記事では、コピーして貼り付けながら演習を進めることを想定しています。

Note

アプリをインストールするためのスクリプトは、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/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 のビルドが失敗します。 これはネットワークが切断されるためであり、コメント アウトされます。この問題を調査しています。

前提条件

最新の Azure PowerShell コマンドレットをインストールする必要があります。 詳細については、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"
    

Note

[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 Update が実行されます。

テンプレートを開くと、使用されているイメージがソース プロパティに表示されます。 この例では、Windows 10 マルチセッション イメージを使用します。

Windows 10 イメージ

マルチセッションとシングルセッションの 2 種類のイメージに注意する必要があります。

マルチセッション イメージは、プールして使用することを目的としています。 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

Note

このコマンドは、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) の例を使用します。

リソースをクリーンアップする

このプロセス中に作成されたリソースが不要になった場合は、次の手順を実行してリソースを削除できます。

重要

最初にリソース グループ テンプレートを削除します。 リソース グループのみを削除した場合、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 にアクセスしてください。