😀

Azure Virtual Desktop の Start Virtual Machine on Connect と非公

に公開

背景と目的

Azure Virtual Desktop (AVD) の Start VM on Connect で VM の自動起動が出来ます。しかしながら、MS のドキュメントを見ると「ユーザーは、クライアントから VM をオフにできますか?」の中で VM の割り当ては解除されない、と書かれています。どうせなら、VM 内でシャットダウンする時に自身で割り当て解除出来たら、使っている時だけ課金されて、無駄なコストが発生しないハッピーな仕組みとなりますよね。

ということで、多少強引で非公式ではありますが、VM のマネージド ID にカスタムロールで割り当て解除権限を付与して自身の VM に権限を割り当て、VM 内で自己割り当て解除する Powershell スクリプトを実行する仕組みを試してみました。

前提条件

https://qiita.com/mnrst/items/63c6b9b77d58a557493d

以前、私が書いたこちらの記事で作成した Azure Virtual Desktop (AVD) 環境を前提とします。

Start Virtual Machine on Connect

自動起動用のカスタムロールを作成します

bash
cat <<EOF > avd-startvm.json
{
    "Name": "Start VM on connect",
    "Description": "Start VM on connect with AVD",
    "IsCustom": true,
    "Actions": [
        "Microsoft.Compute/virtualMachines/start/action",
        "Microsoft.Compute/virtualMachines/read",
        "Microsoft.Compute/virtualMachines/instanceView/read"
    ],
    "DataActions": [
    ],
    "NotDataActions": [
    ],
    "AssignableScopes": [
        "/subscriptions/$(az account show --query id --output tsv)"
    ]
}
EOF

az role definition create \
  --role-definition @avd-startvm.json

作成したカスタムロールを Windows Virtual Desktop に割り当てます

bash
az role assignment create \
  --assignee $(az ad sp list \
  --display-name "Windows Virtual Desktop" \
  --query "[?displayName == 'Windows Virtual Desktop'].objectId" \
  --output tsv) \
  --role "Start VM on connect" \
  --resource-group ${prefix}-rg

ホストプールのプロパティ「接続時に VM を起動する」を「はい」にします

bash
az rest \
  --method patch \
  --uri https://management.azure.com/subscriptions/$(az account show --query id --output tsv)/resourceGroups/${prefix}-rg/providers/Microsoft.DesktopVirtualization/hostPools/${prefix}-hp?api-version=2021-01-14-preview \
  --body '{
    "properties": {
        "startVMOnConnect": true
    }
  }'

これで停止済み (割り当て解除)の VM を自動で起動出来るようになります。

非公式な VM 内自己割り当て解除

「割り当て解除」権限のみのカスタムロールを作成します

bash
cat <<EOF > avd-deallocateSvm.json
{
    "Name": "Self Deallocate for VM",
    "Description": "Self Deallocate for VM",
    "IsCustom": true,
    "Actions": [
        "Microsoft.Compute/virtualMachines/deallocate/action"
    ],
    "DataActions": [
    ],
    "NotDataActions": [
    ],
    "AssignableScopes": [
        "/subscriptions/$(az account show --query id --output tsv)"
    ]
}
EOF

az role definition create \
  --role-definition @avd-deallocateSvm.json

VM 自身にカスタムロールを割り当てます

bash
az role assignment create \
  --assignee $(az vm show \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm \
  --query identity.principalId \
  --output tsv) \
  --role "Self Deallocate for VM" \
  --scope $(az vm show \
  --resource-group ${prefix}-rg \
  --name ${prefix}-vm \
  --query id \
  --output tsv)

VM 内に下記のスクリプトを用意して実行します

powershell
$metadata = (Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/instance?api-version=2021-02-01")
$resourceId = $metadata.compute.resourceId

$content = (Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F")
$access_token = $content.access_token

Invoke-RestMethod -Headers @{"Authorization"="Bearer $access_token"} -Method POST -Uri "https://management.azure.com$resourceId/deallocate?api-version=2021-03-01"

すぐに「シャットダウン」と画面に表示されて、VM 割り当て解除処理が進みます。

参考

Start Virtual Machine on Connect

Azure PowerShell を使用してトークンを取得する

Discussion