AVD を ボタン１発でデプロイできるようにする

# はじめに

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

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

今回は、AVD を ARMテンプレートからデプロイできるようにして、さらに ボタン１発でデプロイ画面を表示する機能 **[Deploy to Azure]** までを紹介したいと思います。

加えて AVD を展開する上での課題対応にも取り組み、これらを組み合わせて動作させるまでを検証した結果をお伝えしていきます。

---

# 目標
以下のようなシンプルな手順で、AVD をデプロイできるようにしたい。
1. AVD のデプロイ画面を表示させ、必要な値はあらかじめ入力されている
2. 必要な可変項目だけを修正（既定値のままでも可）
3. パスワードなどのセキュリティ情報は漏洩させない（作業者が知る事も無い）
3. ボタン１発でデプロイを実行

---

# おさらい：通常の AVD をデプロイする際の流れ
通常 AVD をデプロイする際には、以下のような入力項目を ミスなく入力していく必要があります。

一度、AVD のデプロイに成功していれば、その時の値を テキストで用意しておいて、コピペ でも良いっちゃ良いです。

でも、スマートではありませんね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/246bfd4f-6c4e-1984-336f-386b72289a8a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/cfb54f1b-d7f6-81da-635c-c1412cddea00.png)

:::note info
上記の **カスタム構成スクリプトの URL** 欄には、以下の記事で紹介している **全自動日本語化** のスクリプトを割り当てています。
https://qiita.com/carol0226/items/f7770369947aaf4962f7

この仕組みと組み合わせることで、テンプレートからデプロイする際に、イメージ の 日本語化 までを実施してくれるようになります。
:::

AVD のデプロイが終わったら、以下の記事を参考に アプリケーショングループに ユーザーを割り当てる必要があります。

https://qiita.com/carol0226/items/1115fb9f6f13b03dfa8c

---

# ARM テンプレートの入手方法
Azure には、ARM テンプレートと言って、繰り返し運用する場合などに 予め用意されたテンプレートからデプロイを行う機能があります。目標達成のために、この機能を使っていきたいと思います。

AVD 用の ARM テンプレートは AVD のデプロイを行う直前に、以下の赤枠部分 **(Automation のテンプレートをダウンロードする)** を押すことで、ダウンロードすることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/fa86608b-932c-7b46-69f8-03ebc296999b.png)
そのあと、以下のボタンからダウンロードできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/34194ff3-09bd-980c-a8b9-cd9e7a0ec15a.png)

---

# 既定の ARM テンプレートを使う場合の課題と解決策
## 課題１
ARM テンプレートからデプロイする際は、複数ステップのオペレーションが必要であり、実はスマートではありません。

**テンプレートの一般的なデプロイ手順**

0. 下図の ①～③ の順に **カスタムテンプレート のデプロイ** を開き、**エディターで独自のテンプレートを作成する** を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/5b89d103-390e-bf82-1f5e-bcd24e6bcf0b.png)
　<br>
0. 下図の **①：ファイルの読み込み** を押した後、**template.json** を指定して、**②：保存** を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/9df42643-36dd-2952-60ac-c6703f5b8d19.png)
　<br>
0. **template.json** の選択画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/bc4108c0-db4c-53ce-8232-9157a3316a11.png)
　<br>
0. 下図で **パラメーターの編集**（赤枠）を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/6c495ba7-be12-1416-7380-4d72ee9046c8.png)
　<br>
0. 下図の **①：ファイルの読み込み** を押したあと、**parmaters.json** を指定して、**②：保存** を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/18ab1698-c12f-a79e-044f-b3c1533d988d.png)
　<br>
0. **parameters.json** の選択画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/e731f24a-9754-cd6a-025e-f4a4caa1b452.png)
　<br>
0. パスワード欄は、parameters.json では読み込めないため、手入力が必須となります。
**確認と作成** を押して、デプロイを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/3ccdc17e-c28b-8ff2-8668-03e522fdc871.png)

:::note info
この方法でも良いや・・・と思われた場合は、これを採用頂いても構いません。
:::

:::note warn
**課題**
**template.json** の読み込みと、**parameters.json** を別々に読み込ませる必要がありますし、その後で パスワード を手入力する必要があります。
もう少し、スマートにできないかな・・と思いますよね。
:::

:::note alert
かなり調査をしたり、サポートに問い合わせもしてみたのですが、GUI で、**template.json** と **parameters.json** を一度に読み込ませる方法は存在しませんでした。（なお、コマンドだと存在します）

ですが、私がやりたいのは ボタン１発で ARM テンプレートを GUI 表示させて、可変項目だけを修正（または修正せずに そのまま）、デプロイを実施できるような方法です。
:::

---

## 課題１の解決策
結論として、**[Azure にデプロイ] ボタン** を使う事にしました。
これで、いちいち Azure Portal を開いて、カスタムテンプレートのデプロイの画面を呼び出して、テンプレートファイルを読み込ませる・・・という手順を省略できます。

:::note warn
**注意点**
**[Azure にデプロイ] ボタン** でかなり手順を省略できますが、**template.json** を読み込ませることしかできず、**parameters.json** は読み込みできません。
:::

:::note info
**追加のアイデア💡**
**parameters.json** に書かれている内容も、**template.json** に記載して、マージして１本化してしまおう・・・いう戦略で それを回避する事にしました。

完成したマージ済みのソースは公開してあります。最終章のリンクから入手いただき、内容を確認いただけます。 
:::

以下が公開情報で説明されている **[Azure にデプロイ] ボタン** を使う方法です。

**公開情報：[Azure にデプロイ] ボタン**

https://learn.microsoft.com/ja-jp/azure/azure-resource-manager/templates/deploy-to-azure-button

上記の内容のうち、私の場合は **Azure ストレージ アカウントに格納されているテンプレート** の章に書かれている方法を使う事にしました。

>**書式**
>https://{storage-account-name}.blob.core.windows.net/{container-name}/{template-file-name}

以下のように ストレージアカウント に **template.json** を配置しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/a46e3316-ccd3-c402-e44a-677d322e4ead.png)

コンテナのアクセスレベルは、以下のように 匿名 アクセスを許可しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/96dbca49-3822-86ff-1030-879a24c4bbd0.png)

用意した ストレージアカウント上の JSON のパスを踏まえて、以下のように Markdown を記載します。

コロン":" が "%3A"、スラッシュ"/" が "%2F" に置き換わっている点に注意してください。
~~~
[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fnogujapanese.blob.core.windows.net%2Favd-template%2Ftemplate.json)
~~~

上記の内容は、Markdown の書式になっているので Qiita にそのまま貼ると、以下のようなボタンが表示されます。

:::note alert
**（表示されるボタン）**
![Deploy to Azure](https://aka.ms/deploytoazurebutton)
**（注意）**
上記のボタンは、単なる画像なので、押せません。
実際に押せるボタンは　**最終章** に用意してあります。
:::

このボタンを押すと、１発で AVD のデプロイ用のページが表示されるようになります。

---

## 課題２
課題１で終わらせても良いのですが、その場合 管理者パスワードを 手入力 する必要があったり、可変させたい項目の変更がテキストでの手入力になります（リストボックスから選ぶことはできない）
**（可変させたい主な項目）**
・デプロイする VM 数
・VMサイズ
・VM 名（既存VMと被らない名称にする必要があり固定化できない）
・イメージの種類（Win10/11 , Office365有無）
・プール or 固定
・トークンの有効期限（テンプレート内にベタ書きされているので、未来日に修正が必要）

そのため、以下のようなカスタマイズを行いたいです。
・可変させたい項目は 選択肢の一覧から選択させて、固定の値はあらかじめ埋め込む。
・VM名や トークンの有効期限などは、ルールを決めておいて 自動発番させたい。
・パスワードなどのセキュリティ項目は、Azure KeyVault から動的に読み込むような仕掛けを用意する。

---

## 課題２の解決策

**1. パスワードの受け渡しの課題**
　→　パスワードを Azure KeyVault から読み込ませます
**2. パラメータ "tokenExpirationTime" の課題**
　→　トークン有効期限を デプロイ時の２時間後に自動設定します
**3. パラメータ "vmNamePrefix" の課題**
　→　日時をもとに VM 名の自動採番を行います

上記 1.～3. の課題解決策は、以下の記事に纏めてあります。

https://qiita.com/carol0226/items/fee6f2f325c3c342b494

**4. VM イメージ や VM サイズ を選択式にする**
本当は Azure 内に用意されているイメージから自動取得した内容を表示させられるとカッコ良かったのですが、そこまでには至れませんでした。

代替策として、固定値となりますが、選択可能な値の一覧を テンプレートに埋め込んでおき、デプロイ時に選択できるようにしました。

**VM イメージ 選択の例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/92d4a9ab-cb23-1934-0fe9-c88f11fa6a19.png)
~~~
        "vmGalleryImageSKU": {
            "type": "string",
            "allowedValues": [
                "win10-21h2-avd",
                "win10-21h2-avd-g2",
                "win10-21h2-avd-m365",
                "win10-21h2-avd-m365-g2",
                "win10-22h2-avd",
                "win10-22h2-avd-g2",
                "win10-22h2-avd-m365",
                "win10-22h2-avd-m365-g2",
                "win11-21h2-avd",
                "win11-21h2-avd-m365",
                "win11-22h2-avd",
                "win11-22h2-avd-m365"
            ],
            "metadata": {
                "description": "VMイメージ"
            },
            "defaultValue": "win10-22h2-avd-m365-g2"
        },
~~~

**VM サイズ選択の例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/06d82772-321a-07e8-c0ae-432acf0e11eb.png)
~~~
        "vmSize": {
            "type": "string",
            "allowedValues": [
                "Standard_D2s_v3",
                "Standard_D4s_v3",
                "Standard_D8s_v3",
                "Standard_D8s_v4",
                "Standard_D16s_v4",
                "Standard_D32s_v4",
                "Standard_D48s_v4",
                "Standard_D64s_v4"
            ],
            "metadata": {
                "description": "仮想マシンのサイズ"
            },
            "defaultValue": "Standard_D4s_v3"
        },
~~~

**VM ディスク種類の選択の例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/2ec62c12-9028-07c5-3615-442a218ac11a.png)
~~~
        "vmDiskType": {
            "type": "string",
            "allowedValues": [
                "Premium_LRS",
                "StandardSSD_LRS",
                "Standard_LRS"
            ],
            "metadata": {
                "description": "OSディスクの種類"
            },
            "defaultValue": "Premium_LRS"
        },
~~~

---

# ゴール（完成版のボタン）
課題１と２の 解決策をすべて含んだ、完成版の ARM テンプレート を公開しておきます。

**Template.json のソース**
https://nogujapanese.blob.core.windows.net/avd-template/template.json

なお、項目の表示順も使いやすいように入れ替えています。

**完成版の デプロイ ボタン（押せます）**
[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fnogujapanese.blob.core.windows.net%2Favd-template%2Ftemplate.json "Push Me!")

上記のボタンを押すと、１発で デプロイ の画面に遷移することを確認いただけます。
認証画面が出ますので、お手持ちのサブスクリプション のアカウントで認証してください。

値が設定済みのため、そのままデプロイしても良いですし、可変させたい箇所を変更してから、デプロイすることもできます。

:::note warn
**注意**
残念ながら、そのまま実行すると、デプロイに失敗してしまいます。

0. このテンプレートは、あらかじめ オンプレミス の ドメインコントローラーへドメイン参加する仕組みになっています。
そのため、事前に ドメイン環境の構築が必要です。
　<br>
0. リソースグループ名、ドメイン名、仮想ネットワーク名は、オンコーディングされているため、環境に合わせて テンプレートを書き換えてください。
　<br>
0. パスワードを 同一サブスクリプション内の **KeyVault** から読み込むようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/843441e3-75a9-8ea3-36aa-e301a49594e6.png)
**KeyVault** を 課題２ で **パスワード受け渡しの課題** で示された通りに 事前作成していただくと、連動して動くようになります。
https://qiita.com/carol0226/items/36573dbc55d3e6559886
:::

AVD のデプロイが終わったら、以下の記事を参考に アプリケーショングループに ユーザーを割り当てる必要があります。割り当てられたユーザーを使って、AVD にリモートアクセスできるようになります。

https://qiita.com/carol0226/items/1115fb9f6f13b03dfa8c