AVD を ARMテンプレートでデプロイする際の３つの課題を解決する

# はじめに

現在は、Azure Virtual Desktop (AVD) で、ホストプールと仮想マシンを作成する際に、どれだけシンプルな画面からデプロイさせられるか？ を研究しています。
その際には、いくつかのハードルがあったのですが、そこで得られたノウハウを記事にしていこうと思っています。
AVDに関する記事は、以下のリンク先で シリーズ化 していますので併せて参照ください。

https://qiita.com/carol0226/items/7318fdd7aff780f5177c

今回は、AVD を ARMテンプレートからデプロイする際に、３つの課題を提起し、それぞれの回避策を案内したいと思います。

---

# ３つの課題とは
1. パスワードの受け渡しの課題
1. パラメータ "tokenExpirationTime" の課題
1. パラメータ "vmNamePrefix" の課題

この３つの課題をクリアすることで、AVD の ARM テンプレートでの展開が現実的になると思います。

---

## 1. パスワードの受け渡しの課題
AVD の ARM テンプレート (Template.json) には、"administratorAccountPassword" と "vmAdministratorAccountPassword" という項目があり、仮想マシンをデプロイする際には、必須項目となっています。
通常では、画面からパスワードを入力する必要があり、ここで 入力ミスをすると VM がドメイン参加に失敗したり、あとで管理者が ローカル管理者権限で VM に入ることができなかったりします。

Parameters.json ファイルに 固定値のパスワードを記載すれば簡単なのですが、デプロイを運用者の人にやってもらうようなシチュエーションを考えると、セキュリティ的に問題があります。
そんなこともあって、KeyVault から パスワードを読み込ませる事を考えました。

この課題解決は ボリュームがあるため、以下の記事にまとめましたので、別途 参照ください。

https://qiita.com/carol0226/items/36573dbc55d3e6559886

---

## 2. パラメータ "tokenExpirationTime" の課題
Template.json には、 "tokenExpirationTime" という項目があります。

        "tokenExpirationTime": {
            "type": "string",
            "metadata": {
                "description": "Hostpool token expiration time"
            }
        },

この項目は、入力必須項目になっています。空欄のままだとデプロイできません。
しかし、ここって、どういう表記で 値を入力すれば良いのかわかりません。
調査のために、Azure Portal から AVD をデプロイした際にダウンロードした Parameters.json を見てみると、以下の内容になっていました。

        "tokenExpirationTime": {
            "value": "2023-07-31T11:56:50.618Z"
        },

つまり、上記の表記に倣って "西暦-月-日T時-分-秒-ミリ秒Z" というフォーマットで設定すれば良いことが分かります。
しかし、このフォーマットで 毎回手入力するのは 非現実的だと思いますよね・・・

これを回避する手段として、数年先の日付を固定で設定すれば ひとまず良いじゃん・・という考え方はあると思うのですが、今回は テンプレート関数の学習を兼ねて、有効期限が２時間後に設定された期限を発行してみたいと思います。

具体的には、以下のように ARM テンプレート用の日付関数 を応用します。
"utcNow()" という関数を使うと、現在日時が取得でき、"dateTimeAdd" という関数を使うと、元となる日時に 時間を加算することができます。

実際に Template.json へ 以下の記述をおこない Portal へ読み込ませてみると、下図の赤枠のように表示されます。

        "tokenExpirationTime": {
            "type": "string",
            "metadata": {
                "description": "Hostpool token expiration time"
            },
            "defaultValue": "[dateTimeAdd(utcNow('f'), 'PT2H')]"
        },

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/41daf7cb-152a-0aec-b2f3-9b166fef3fce.png)

これで、テンプレートをデプロイすれば、"tokenExpirationTime" には、現在時刻に ２時間加算された値が引き渡されるようになります。（PT2H が ２時間加算という意味）
なぜ、＋２時間にしたのかですが、それ未満の時間では トークンの有効期限が切れるというワーニングが出て デプロイできなくなるため、少し余裕を持たせました。

https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/templates/template-functions-date

---

## 3. パラメータ "vmNamePrefix" の課題
Template.json には、 "vmNamePrefix" という項目があります。
この欄に記入した文字列が VM名 のプレフィックスとして採用され その後ろに -0 -1 -2 という感じで、デプロイした台数分のサフィックスが追加されてデプロイされます。
例えば、"vmNamePrefix" を "avd" という名称にしておき、VM を 5台 デプロイすると 以下の名称になります。
avd-0
avd-1
avd-2
avd-3
avd-4

この vmNamePrefix について、毎回 手動で設定する必要があるのですが、別途 ホストプール上に VM を追加でデプロイしようとした場合に、同じ文字列を入力した場合でも バカ正直に avd-0 から発番されてしまいます。
すると、VM名が被ってしまい 問題が生じます。実際に これで デプロイは行われるのですが 利用できない VM としてデプロイされてしまいました。
リソースグループ名が違ければ 同一名の VM でも別々のものになりますが、同じ名称の VMだらけになります。

この問題を どうやって回避しようかと考えたのですが、日時から VM名を生成することで回避することにしました。

Tempalte.json の "vmNamePrefix" を以下のように記述しておくことで、AVDという文字列の後に 月日時分 が追記されたプレフィックスになります。
"PT9H" は、UTC時間に対して ９時間加算して日本時間となるようにしています。

        "vmNamePrefix": {
            "type": "string",
            "metadata": {
                "description": "VM名のプレフィックス"
            },
            "defaultValue": "[dateTimeAdd(utcNow('f'), 'PT9H','AVDMMddhhmm')]"
        },

そして、VM を 5台 デプロイすれば 8月30日 15時56分 だったとすれば、以下の VM名 で生成されます。
AVD08301556-0
AVD08301556-1
AVD08301556-2
AVD08301556-3
AVD08301556-4

こうすることで、別のタイミングで VM をデプロイすれば、日時が異なっているため VM名 が被ってしまうことを回避することが可能になります。
なお、Azure の VM名は 長いものでも受け付けられますが、Windows のコンピューター名は 15文字以下になってしまうので、ココでは サフィックスの -0 の番号まで含めて 15文字以下になるように 考慮しておく必要があります。

実際に Portal から、テンプレートを使ってデプロイしてみると、以下のような感じになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/188655f3-6db5-864b-a5d4-58e4f04daae0.png)

---

# まとめ
以上のような工夫で、AVD の ARMテンプレート を運用時に利用できるようにカスタマイズすることができました。
あとは、応用で さまざまな値を テンプレートの変数に 初期設定することができると思いますので、お試しください。