ARM(Azure Resorce Manager) templateはAzureのリソースをJSON形式で定義したテンプレートで、このテンプレートを使ったデプロイが可能です。ARMはオーケストレーション手法の1つで、TerraformやAnsibleと同様に構造化され非常に視認性が高い特徴があります。ARMと他のツールとの違いは、ARMはMicrosoft純正のツールでExportやImportが非常に容易なメリットがあります。Azureで作成されたリソースはJSON形式で出力する事ができ、このJSONをARMに組み込む事もできます。
ARM templateの作成
基本構造
ARMテンプレートの基本的な構造を以下に示します。テンプレートには、リソースだけでなく、パラメタや変数や出力を含める事ができます。
本記事では、変数と出力の説明は省略します。変数と出力の説明をお求めの方は「ARM テンプレートのドキュメント」を参照ください。
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {}, // パラメタ一覧
"variables": {}, // 変数一覧
"resources": [], // リソース一覧
"outputs": {} // 出力一覧
}
リソースの追加
ARMテンプレートにリソースを追加してみましょう。ポータル(GUI)やazコマンドで作成したリソースをexportして部分的に修正する楽する方法もありますが、まずは基本に忠実に公式マニュアルを読みながらリソースを定義する方法を説明します。
「Define resources with Bicep and ARM templates」をブラウザで開きます。

検索窓に調査したいリソース名を入力します。以下スクリーンショットはStorage Accountを調査する例です。

リソースを操作するAPIには複数のバージョンが存在します。画面上部の「API version」のプルダウンで使用するAPIのバージョンを指定できます。

サンプルのJSONフォーマットが表示されています。これを適宜変更すれば、リソース作成を省力化する事ができるでしょう。

各パラメタの説明は以下スクリーンショットの通りです。「resource declaration」と「required」と書かれているパラメタは入力必須で省略する事ができません。それ以外のパラメタは入力を省略するとデフォルト値が適用されます。

Strage Accountを作成するサンプルのJSONは以下の通りです。Storage Accountの場合はtype, apiVersion, name, location, skuの5つがが省略不可の必須パラメタです。
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageName": {
"type": "string",
"minLength": 3,
"maxLength": 24
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-08-01",
"name": "gokatei01",
"location": "japaneast",
"sku": {
"name": "Standard_LRS"
}
}
]
}
上記のテンプレートファイルをtemplate.jsonという名前で保存します。その後、az deployment group createというコマンドを使用するとARM templateに基づいたデプロイができます。なお、–nameに指定する名前はデプロイ名を指定して下さい。どのようなデプロイが行われたかを、後から「デプロイ名」で振り返る事ができます。
az group create --name MyResourceGroup --location japaneast az deployment group create \ --name deplay-storage-account-01 \ --resource-group MyResourceGroup \ --template-file template.json
デプロイを振り返るには、「リソースグループ」「デプロイ」の画面を参照します。

パラメタの追加
デプロイが固定値ですと柔軟に扱う事ができません。ARM templateは柔軟に操作できるようにパラメタ化する機能もあります。前述の例ではストレージアカウント名を定数として指定していましたが、これをパラメタ化する事もできます。テンプレート例は以下の通りです。
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageName": {
"type": "string",
"minLength": 3,
"maxLength": 24
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-08-01",
"name": "[parameters('storageName')]",
"location": "japaneast",
"sku": {
"name": "Standard_LRS"
}
}
]
}
テンプレート内で定義されているパラメタは–parametersオプションを使って指定します。
az deployment group create \ --name deplay-storage-account-02 \ --resource-group MyResourceGroup \ --template-file template.json \ --parameters storageName=gokatei02
デプロイ操作の説明
説明の都合上、以下のような2つのサブネットを持つ仮想ネットワークのテンプレートを例に挙げて説明します。
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"vnetName": {
"type": "string",
"metadata": {
"description": "仮想ネットワーク名"
}
},
"vnetPrefix": {
"type": "string",
"metadata": {
"description": "仮想ネットワークのアドレス空間"
}
},
"subnetPrivateName": {
"type": "string"
},
"subnetPrivatePrefix": {
"type": "string"
},
"subnetPublicName": {
"type": "string"
},
"subnetPublicPrefix": {
"type": "string"
}
},
"resources": [
{
"type": "Microsoft.Network/virtualNetworks",
"apiVersion": "2021-05-01",
"name": "[parameters('vnetName')]",
"location": "japaneast",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('vnetPrefix')]"
]
},
"subnets": [
{
"type": "Microsoft.Network/virtualNetworks/subnets",
"name": "[parameters('subnetPrivateName')]",
"properties": {
"addressPrefix": "[parameters('subnetPrivatePrefix')]"
}
},
{
"type": "Microsoft.Network/virtualNetworks/subnets",
"name": "[parameters('subnetPublicName')]",
"properties": {
"addressPrefix": "[parameters('subnetPublicPrefix')]"
}
}
]
}
}
]
}
コマンドライン引数で指定する方法
テンプレートに与える引数は–parametersオプションで与えます。引数が複数ある場合は、スペースで区切って指定します。もし、引数が多くて見ずらい場合は、以下のような改行を適度に挟むと良いでしょう。
az deployment group create \
--name deplay-virtual-network-01 \
--resource-group MyResourceGroup \
--template-file template.json \
--parameters vnetName=vnet16 vnetPrefix="172.16.0.0/16" \
subnetPrivateName=vnet16-subnet01 subnetPrivatePrefix="172.16.1.0/24" \
subnetPublicName=vnet16-subnet02 subnetPublicPrefix="172.16.2.0/24"
パラメタファイルで指定する方法
指定するパラメタが多い場合、パラメタを引数で与えるのは見通しが悪いかもしれません。そのような場合はJSONファイルでパラメタを定義する事もできます。以下のJSONファイルをparameters.jsonという名前で保存します。
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"vnetName": {
"value": "vnet17"
},
"vnetPrefix": {
"value": "172.17.0.0/16"
},
"subnetPrivateName": {
"value": "vnet17-subnet01"
},
"subnetPrivatePrefix": {
"value": "172.17.1.0/24"
},
"subnetPublicName": {
"value": "vnet17-subnet02"
},
"subnetPublicPrefix": {
"value": "172.17.2.0/24"
}
}
}
パラメタファイルのファイルパスを–parametersオプションに指定します。
az deployment group create \ --name deplay-virtual-network-02 \ --resource-group MyResourceGroup \ --template-file template.json \ --parameters parameters.json
ポータル(GUI)による操作方法
ARM templateの登録
「Azureポータル」をブラウザで開きます。「全般」「テンプレート」の順に画面遷移します。

「作成」を押下します。

「名前」「説明」を入力し、「次へ」を押下します。

「テンプレート」を記入し、「追加」を押下します。

ARM templateによるデプロイ
「Azureポータル」をブラウザで開きます。「全般」「テンプレート」の順に画面遷移します。

「テンプレート名」「デプロイ」の順に押下します。

metadata.descriptionを定義すれば、以下スクリーンショットのようにデプロイの画面にてヘルプメッセージを表示する事もできます。

パラメタ入力後、画面下の「上記の条件に同意する」にチェックを入れ、「購入」を押下します。

「展開に成功しました」とのメッセージが表示されるまで待ちます。

export機能を併用する方法
JSONビュー
Azure内の全てのリソースはJSON形式で表示する事ができます。「概要」画面の右上の方に「JSONビュー」というリンクがありますので、これを押下します。

この画面に表示されるJSONを利用するとARMテンプレートの作成を省力化する事ができます。なお、「APIバージョン」はARMテンプレートを作成する時に必要になりますので、これもメモに控えておきましょう。

以下のような空のリソースのテンプレートを用意します。そして、resources内に「JSONビュー」の内容を貼り付けます。
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
<ここにJSONビューの内容を貼り付ける>
]
}
apiVersionはJSONビューに含まれていませんので、apiVersionの指定を手作業で加筆します。また、id, etagなどのユニークな値を指定するパラメタがあれば、これを削除します。

以上が「だいたい成功する」操作ですが、場合によってはエラーが発生するかもしれません。ですが、エラーメッセージを冷静に読めば十分対応できるので、省力化する操作例としては十分だと思っています。
以下は「うまくいかない」例のひとつです。Azure Database for PostgreSQLの場合は「JSONビュー」にAdministratorLoginPasswordが入っていないません。エラーメッセージを読めば、AdministratorLoginPasswordを手作業で加筆する必要がある事が分かります。
admin@mac19 ~ % az deployment group create \
--name deplay-storage-account-01 \
--resource-group MyResourceGroup \
--template-file template.json
{"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource deployment operation failed.
Please list deployment operations for details.
Please see https://aka.ms/DeployOperations for usage details.","details":
[{"code":"BadRequest","message":"{\r\n \"error\": {\r\n \"code\": \"InvalidParameterValue\",\r\n
\"message\": \"Invalid value given for parameter 'AdministratorLoginPassword'.
Specify a valid parameter value.\"\r\n }\r\n}"}]}}
以上のような操作で最終的に作成されたテンプレートの例は以下の通りです。earliestRestoreDateのような削除漏れのゴミパラメタも混入していますが、一応はデプロイに成功します。
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"apiVersion": "2017-12-01",
"sku": {
"name": "GP_Gen5_4",
"tier": "GeneralPurpose",
"family": "Gen5",
"capacity": 4
},
"properties": {
"administratorLogin": "AdminPg",
"administratorLoginPassword": "P@ssw0rd123!",
"storageProfile": {
"storageMB": 102400,
"backupRetentionDays": 7,
"geoRedundantBackup": "Disabled",
"storageAutogrow": "Enabled"
},
"version": "11",
"sslEnforcement": "Enabled",
"minimalTlsVersion": "TLSEnforcementDisabled",
"userVisibleState": "Ready",
"fullyQualifiedDomainName": "gokatei-db-01.postgres.database.azure.com",
"earliestRestoreDate": "2022-02-26T16:16:04.397+00:00",
"replicationRole": "None",
"masterServerId": "",
"replicaCapacity": 5,
"byokEnforcement": "Disabled",
"privateEndpointConnections": [],
"infrastructureEncryption": "Disabled",
"publicNetworkAccess": "Enabled"
},
"location": "japaneast",
"tags": {},
//"id": "/subscriptions/2e2f81a9-b030-410f-9784-c582580c932e/resourceGroups/MyResourceGroup/providers/Microsoft.DBforPostgreSQL/servers/gokatei-db-01",
"name": "gokatei-db-01",
"type": "Microsoft.DBforPostgreSQL/servers"
}
]
}
デプロイ履歴の流用
ポータル(GUI)やazコマンドで作成されたリソースは「デプロイ」の履歴としてAzureに記録されています。この記録を部分的に修正する事で、ARM templateのJSONファイルを0から作成するよりも素早く構築する事ができます。
「Azureポータル」をブラウザで開きます。「全般」「リソースグループ」の順に画面遷移します。

「リソースグループ名」「デプロイ」「デプロイ名」の順に押下します。

「テンプレート」を押下すると、ARM templateが閲覧できます。このtemplateを部分的に修正すれば、0からtemplateを作るよりも素早く構築する事ができます。

Automationのテンプレート
ポータル(GUI)でリソースを作成すると、作成前の最終画面の右下に「Automationのテンプレートをダウンロードする」とのリンクがあります。このリンクを押下します。

リンクを押下すると、ARM templateが表示されます。このテンプレートを適宜編集する事によって素早くARM templateを作成する事ができます。

補足
Visual Studio Code
MicrosoftはARM templateを編集するエディタとして「Visual Studio Code」を推奨しています。エディタに特段のこだわりがないならば推奨に従うのが無難かと思います。
例えば、以下スクリーンショットのように「未定義の変数を使用している」などのvalidation errorを実行前に気づく事ができます。

また、全選択の状態で右クリックメニューを表示し「選択範囲のフォーマット」を選択すれば、JSONファイルのインデントを整える事ができます。

