運用現場で効く「Allocation Failed」対策

今回は、AVDユーザーなら一度は遭遇した事がある「Allocation Failed」対策について考えたいと思います。クラウドの良さをぶち壊しにする”オンデマンドサービスの在庫切れ”は根深いものです。まずは、遭遇率を上げてしまう要因を見ていきましょう。裏を返せば、この構成を採用しなければいいのです!

※AVDと銘打っていますが、すべてのAzureVMが対象です。

Allocation Failed の発生率を上げる構成要因

・近接配置グループ:物理的に近いホストに限定される
・可用性ゾーン:指定したゾーンに限定される
・可用性セット:指定した更新/障害ドメインに限定される
・VM サイズ/SKU:需要の高い、SKUは影響を受けやすい ※特にGPUモデル
・Ultra Disk / Premium SSD v2:対応ホスト、対応SKUに限定される
・高速ネットワーク:SR-IOV対応ホストに限定される
・エフェメラル ディスク:ローカルSSDを搭載したホストに限定される

※複数に該当する場合は、さらに発生率が上がります。

下記のような対策が推奨されています。

①VMの起動を再実行する
②VMのサイズを変更する
③VMのシリーズを変更する
④リージョンを変更する

リージョンを変更するのは、事前に環境を作成しておく必要があるので、かなり難易度が高いと思います。残りの対策、①②③は作業が発生するため対応が容易ではありません。今回は、この作業を自動化するための仕組みを考案しました。

さっそく、構成を見てみましょう!

①Runbookのスケジュール機能により、指定時刻にスクリプトを実行する
②スクリプト内で指定されたリソースグループに対して、指定SKUでの起動を試みる

Runbookスクリプトには、事前に[サブスクリプションID][リソースグループ名][SKU]を記述しておく。スクリプトには、予め対象となるリソースグループ名とSKUを記述しておく。これらの記述が合致しない場合、スキップされます。複数のリソースグループと複数のSKUの組み合わせを同時に処理できます。スクリプトはリソースグループに対して実行するので、割り当て解除状態の全VMが起動対象となります。リソースグループ=ホストプールにしておくとよいでしょう。

【動作例】

ResourceGroupName:RG1,RG2
rgSkuMap:[RG1=SKU1,SKU2][RG2=SKU3,SKU4]
MaxRetryLoops:2

Loop1/2
①リソースグループ単位で、全DeallocatedVMの台数を把握
②RG1にて、1~100台でSKU1起動 → 60秒待機 → 状態確認
③RG1にて、101~200台でSKU1起動 → 60秒待機 → 状態確認(以降繰り返し)
④SKU1が全バッチ完了後、Deallocatedが残っていればSKU2で起動
⑤Deallocatedが残っていれば、Loop2/2にて②③④⑤を実行
⑥同様に、RG2にて②③④⑤を実施


それでは、やってみよう!!

先ずは、Automationアカウントを作成します。

外部からのトリガーは不要。Webhookなどの受口を設けない。
※プライベートアクセスにすると、プライベートエンドポイントの作成を求められる。

作成後ー[ID]ー[Azureロールの割り当て]を選択
※VMへのSKU変更、起動を実行するための権限を付与します。

スコープ:サブスクリプション
サブスクリプション:※対象のリソースグループが存在するサブスクリプションを選択
役割:Desktop Virtualization Virtual Machine Contributor
※権限を絞る場合は、カスタムロールの作成が必要です。

つづいて、Runbookの作成です。

[Runbook]ー[+作成]を選択

Runbook:新規作成
名前:表示名
Runbookの種類:PowerShell
ランタイム環境:PowerShell-7.2

こちらからダウンロードしたスクリプトをペースト。[保存]ー[公開]を選択

※環境に合わせて設定して下さい。
21行:サブスクリプションID
22行:対象となるリソースグループ名を列挙
23行:ループ回数を指定

27行:リソースグループ名と対応するSKU
28行:リソースグループが複数存在する場合は追記していく

[スケジュール]ー[スケジュールの追加]を選択

[スケジュール]を選択

名前:表示名
開始時間:スケジュールを実行する時間
間隔:[2]週間に1回

[パラメータと実行設定]ー[OK]を選択

作成できました。


それでは、確認してみましょう!

既存環境では、2つのホストプールがあり、それぞれ、2台のVMがあります。
全てのVMは[割り当て解除]状態です。
クォーター制限のため、NV6ads_A10_v5は、1台しか起動できません。
D2as_v5には、台数制限はありません。

[ホストプール]
AVD-AllocationFailure [Allocation-0,Allocation-1]
AVD-ADmulti [AVD-ADmulti-2,AVD-ADmulti-3]

[スクリプト]
ResourceGroupName = “AVD-AllocationFailure,AVD-ADmulti”
rgSkuMap =
“AVD-AllocationFailure” = “Standard_NV6ads_A10_v5,Standard_D2as_v5”
“AVD-ADmulti” = “Standard_D2as_v5,Standard_NV6ads_A10_v5”

【実行結果】

1.[Allocation-0][Allocation-1]は、[NV6ads_A10_v5]で起動を試みる
2.[NV6ads_A10_v5]は1台しか起動できないので、[Allocation-0]が起動し、[Allocation-1]は起動に失敗する。
3.次に指定されたSKU[D2as_v5]で[Allocation-1]の起動を試みる
4.[AVD-ADmulti-2][AVD-ADmulti-3]は、[D2as_v5]で起動を試みる

無事に、指定したSKUで全台起動できました!


Accops (アコップス) HyLabs 対応版

Acoops HyLabsでは、授業やシフト勤務のスケジュールに合わせてセッションホストの作成/削除を自動的に行います。また、作成されたアプリケーショングループに対して、ユーザー割り当てを自動的に行う事も可能です。※リソースグループ単位で作成/削除を行う。
この場合、事前にリソースグループ名を指定する事ができません。
そこで、ActivityLogの[AllocationFailed]ログから、リソースグループ名を拾う方法を考えてみました。

①Runbookのスケジュール機能により、指定時刻にスクリプトを実行する
②ActivityLogから、[AllocationFailed]ログを検索し、ログ内から[サブスクリプションID][リソースグループ名]を取得する。
③取得したリソースグループに対して、指定SKUでの起動を試みる

ActivityLog内で指定した時間帯で検索された[AllocationFailed]ログ内のリソースグループ名を収集する。同じリソースグループ名を含むログは重複排除されます。
対象のリソースグループから、[割り当て解除]状態のVMに対して、指定したSKUで100台単位で起動を試みます。このスクリプト実行で出るであろう[AllocationFailed]ログによる再実行を抑止するために、クールダウン時間を指定します。

【動作例】
$LookbackMinutes = 5 ※5分前までのActivityLogを対象に検索
$CooldownMinutes = 10 ※クールダウン時間
$BatchSize = 100 ※1度に起動するVM台数
$SkuRetryCycles = 1 ※SKU起動を繰り返す回数
$SkuCandidates = “Standard_NV6ads_A10_v5″,”Standard_D2as_v5”
$AutomationAccountName = “xxx” ※スクリプトを実行するAutomation名
$AutomationResourceGroupName = “xxx” ※Automationが属するリソースグループ名

①5分前までのActivityLogを対象に検索
②リソースグループ単位で、全DeallocatedVMの台数を把握
③RG1にて、1~100台でSKU1(A10)起動、ダメなら、SKU2(Dv5)起動
※SkuRetryCycles = 2 の場合、割り当て解除]状態のVMに対して再度実行
④RG1にて、101~160台でSKU1(A10)起動、ダメなら、SKU2(Dv5)起動
※SkuRetryCycles = 2 の場合、割り当て解除]状態のVMに対して再度実行
⑤RG2にて、(以降繰り返し)

マネージドIDに対して、下記権限が必要です。
・Desktop Virtualization Virtual Machine Contributor
・Monitoring Data Reader
・Automation 共同作成者