背景と目的
Azure Virtual Desktop (AVD) の Start VM on Connect で VM の自動起動が出来ます。しかしながら、MS のドキュメントを見ると「ユーザーは、クライアントから VM をオフにできますか?」の中で VM の割り当ては解除されない、と書かれています。どうせなら、VM 内でシャットダウンする時に自身で割り当て解除出来たら、使っている時だけ課金されて、無駄なコストが発生しないハッピーな仕組みとなりますよね。
ということで、多少強引で非公式ではありますが、VM のマネージド ID にカスタムロールで割り当て解除権限を付与して自身の VM に権限を割り当て、VM 内で自己割り当て解除する Powershell スクリプトを実行する仕組みを試してみました。
前提条件
以前、私が書いたこちらの記事で作成した 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 割り当て解除処理が進みます。