ARMテンプレートからデプロイする#2

この記事は更新から24ヶ月以上経過しているため、最新の情報を別途確認することを推奨いたします。

パーソルプロセス&テクノロジーの内田です。

ARMテンプレートを用いて仮想マシンを作成、作成後に仮想マシン拡張機能を用いてADにドメイン参加するテンプレートを作成、解説していきたいと思います。

前回の記事はこちら。

ARMテンプレートからデプロイする#1 – Cloud Steady | パーソルプロセス&テクノロジー株式会社

また、Bicepを用いて、ドメインに参加したWindowsVMを作成するためのコード記述方法については下記記事に記載しています。

Bicepでドメインに参加したWindowsVMのコード記述方法 – Cloud Steady | パーソルプロセス&テクノロジー株式会社

ドメイン参加するためのリソースは何か

まず大前提として、ARMテンプレート ファイルは宣言型ですので、リソースがどのような設定であることが望ましいかという、状態を定義するものになります。

そのためARMテンプレートでできることは、仮想マシンやNIC、ディスクといったAzureリソースに対して特定のプロパティを設定した上でできることに焦点が置かれています。

ドメイン参加は仮想マシンのプロパティの話ではなく、OS上の操作となりますので、少し変わったリソースをデプロイします。

具体的にはMicrosoft.Computeリソース プロバイダーが提供する拡張機能リソースをデプロイします。拡張機能リソースのリソース タイプは「Microsoft.Compute/virtualMachines/extensions」であり、このリソース タイプによって、仮想マシン リソースに対する様々な追加設定を構成することが可能です。

今回は「仮想マシンのドメイン参加」を拡張機能リソースで設定することになりますが、他にも「Log Analytics Agentのインストール」などが可能です。

拡張機能リソースのテンプレート

それでは、拡張機能リソースのARMテンプレートを確認していきましょう。

仮想マシン拡張機能リソースのテンプレート

まずdependOnを用いてドメイン参加をする仮想マシンリソースとの依存関係を示しています。

次にproperties.settings配下のオブジェクトにて、ドメイン名やOUパス、ドメイン参加する際の管理者ユーザーの指定をしています。

そして、properties.protectedSettings配下のオブジェクトにて、ドメイン参加する際の管理者ユーザーのパスワードを指定しています。

またもう一つ着目すべき点は拡張機能リソースのリソース名です。拡張機能リソースのリソースタイプは「Microsoft.Compute/virtualMachines/extensions」であり、仮想マシンのサブリソースであることがわかります。サブリソースのリソース名は「<親リソース名>/<サブリソース名>」という形式である必要がありますので、「<VM名>/domainJoin」というリソース名となっていることに注意しておきましょう。

実際にデプロイする

VMやNICのテンプレートを追加した後、実際にこのリソースをデプロイしていきたいと思います。なお、デプロイ先のVnetにはあらかじめDNS設定をしておきます。

ドメイン参加の拡張機能リソースと、VM、NICがデプロイされていることが確認できます。

デプロイ先のリソースグループにアクセスして「非表示の型の表示」をオンにすると、拡張機能サブリソースがデプロイされていることが確認できます。

ADサーバを確認してみると、指定したOU上にコンピュータ オブジェクトが存在することが確認できます。

最後に今回のARMテンプレートをサンプルとして下記に公開いたします。デプロイするリソースの構成情報をオブジェクト化して、ループ処理を付け加えれば、複数の仮想マシンを1度のデプロイ処理で作成でき、なおかつそれらのドメイン参加が自動的に行われますので、構築に掛かる工数を削減することが見込めます。

今回の内容は以上となります。

蛇足ですが、現在のIaCの主流はARMテンプレートからBicepに置き換わりつつあると考えます。今回のARMテンプレートにおいても、Bicepから作成をしております。ARMと遜色なくBicepを利用可能であることを最後に補足しておきます。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
      "adminUserName": {
          "type": "String"
      },
      "adminPassword": {
          "type": "SecureString"
      },
      "domainName": {
          "type": "String"
      },
      "ouPath": {
          "type": "String",
          "metadata": {
              "description": "OU=xxx,OU=xxx,DC=xxx,DC=xxx という形式で入力する。"
          }
      },
      "domainAdminUserName": {
          "type": "String",
          "metadata": {
              "descriptipn": "UPN形式で入力する必要がある。username@domainname"
          }
      },
      "domainAdminPassword": {
          "type": "SecureString"
      }
  },
  "variables": {
      "hostNameClassification": "test"
  },
  "resources": [
      {
          "type": "Microsoft.Compute/virtualMachines/extensions",
          "apiVersion": "2021-07-01",
          "name": "[format('{0}/{1}', format('vm-{0}-1', variables('hostNameClassification')), 'domainJoin')]",
          "location": "[resourceGroup().location]",
          "dependsOn": [
              "[resourceId('Microsoft.Compute/virtualMachines', format('vm-{0}-1', variables('hostNameClassification')))]"
          ],
          "properties": {
              "publisher": "Microsoft.Compute",
              "type": "JsonADDomainExtension",
              "typeHandlerVersion": "1.3",
              "autoUpgradeMinorVersion": true,
              "settings": {
                  "name": "[parameters('domainName')]",
                  "ouPath": "[parameters('ouPath')]",
                  "user": "[parameters('domainAdminUserName')]",
                  "restart": "true",
                  "options": "3"
              },
              "protectedSettings": {
                  "password": "[parameters('domainAdminPassword')]"
              }
          }
      },
      {
          "type": "Microsoft.Compute/virtualMachines",
          "apiVersion": "2021-07-01",
          "name": "[format('vm-{0}-1', variables('hostNameClassification'))]",
          "location": "[resourceGroup().location]",
          "dependsOn": [
              "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}-1', variables('hostNameClassification')))]"
          ],
          "zones": [],
          "properties": {
              "hardwareProfile": {
                  "vmSize": "Standard_A2_v2"
              },
              "osProfile": {
                  "computerName": "[format('vm-{0}-1', variables('hostNameClassification'))]",
                  "adminUsername": "[parameters('adminUserName')]",
                  "adminPassword": "[parameters('adminPassword')]"
              },
              "storageProfile": {
                  "imageReference": {
                      "publisher": "MicrosoftWindowsServer",
                      "offer": "WindowsServer",
                      "sku": "2019-Datacenter",
                      "version": "latest"
                  },
                  "osDisk": {
                      "name": "[format('disk-{0}-OsDisk', variables('hostNameClassification'))]",
                      "caching": "ReadWrite",
                      "createOption": "FromImage"
                  }
              },
              "networkProfile": {
                  "networkInterfaces": [
                      {
                          "id": "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}-1', variables('hostNameClassification')))]"
                      }
                  ]
              },
              "diagnosticsProfile": {
                  "bootDiagnostics": {
                      "enabled": true
                  }
              }
          }
      },
      {
          "type": "Microsoft.Network/networkInterfaces",
          "apiVersion": "2020-11-01",
          "name": "[format('nic-{0}-1', variables('hostNameClassification'))]",
          "location": "[resourceGroup().location]",
          "properties": {
              "ipConfigurations": [
                  {
                      "name": "ipConfiguration1",
                      "properties": {
                          "privateIPAllocationMethod": "Dynamic",
                          "subnet": {
                              "id": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', subscription().subscriptionId, 'RGNAME'), 'Microsoft.Network/virtualNetworks/subnets', 'VNETNAME', 'SUBNETNAME')]"
                          }
                      }
                  }
              ]
          }
      }
  ]
}
いいね (この記事が参考になった人の数:5)
(↑参考になった場合はハートマークを押して評価お願いします)
読み込み中...

注意事項・免責事項

※技術情報につきましては投稿日時点の情報となります。投稿日以降に仕様等が変更されていることがありますのでご了承ください。

※公式な技術情報の紹介の他、当社による検証結果および経験に基づく独自の見解が含まれている場合がございます。

※これらの技術情報によって被ったいかなる損害についても、当社は一切責任を負わないものといたします。十分な確認・検証の上、ご活用お願いたします。

※当サイトはマイクロソフト社によるサポートページではございません。パーソルプロセス&テクノロジー株式会社が運営しているサイトのため、マイクロソフト社によるサポートを希望される方は適切な問い合わせ先にご確認ください。
 【重要】マイクロソフト社のサポートをお求めの方は、問い合わせ窓口をご確認ください