こんにちは。青木です。
Azure のリソース作成の自動化といえば Azure Resource Manager Template (ARM Template) や Terraform があるかと思いますが、今回は Azure Blueprints を使用した Azure のリソース作成の方法を紹介します。
注意:当記事に記載している Azure Portal の画面名や画面項目名は 2021 年 9 月時点の情報です。
Azure Blueprints は ARM Template を使用した Azure リソースの作成を自動化できます。
	ARM Template 自体は 1 つのリソースグループに対してリソース作成を行いますが、Azure Blueprints では、「リソースグループの作成、ARM Template でのリソース作成」のセットを複数定義できるため、複数のリソースグループを使用する Azure アーキテクチャーの Azure リソースの構築を自動化できます。
Azure Blueprints を使用した環境構築の利点として、システム開発時に環境構築にかかる時間が、手作業による Azure リソース作成や、ARM Template のみを使用した Azure リソース作成に比べて短くなります。
	特に複数の環境構築時は、Azure Blueprintsのパラメーターを変更してデプロイする作業のみで環境が構築できるため、効率的に環境構築が行えます。
注意:Azure Blueprints は 2021 年 9 月時点ではプレビュー版として提供されています。
Azure Blueprints での操作は次のような流れになります。
ブループリント定義には以下の「成果物」を定義することができます。
	(公式ドキュメントには「アーティファクト」と記載されていますが、Azure Portal では「成果物」と表記されているため当記事では「成果物」と記載しています)
Azure Blueprints では以下の機能をサポートしています。
    (代表的な機能を記載しています)
成果物(ARM Template 等)でパラメーターが定義されている場合、ブループリント定義から成果物に対してパラメーターとしてリソース作成に必要な情報を渡すことができます。
次の2種類のパラメーターがあります。
ブループリントの発行時、ブループリントのバージョンを指定します。
    ブループリントの割り当て時に発行済みのバージョンを指定して割り当てを行います。
ブループリントを使用して作成したリソースグループ、リソースにロックを適用できます。
実際に Azure Blueprints を使用してAzure のリソースを作成してみます。
	次の図のような構成のリソースを作成します。
 
		この構成で Azure のリソースを作成するための Azure Blueprints 定義は以下になります。
 
		ブループリントを作成していきます。
	Azure Portal の「ブループリント」画面の「ブループリントの定義」より「ブループリントの作成」をクリックします。
 
		ブループリントの作成画面が表示されるので、「空白のブループリントで始める」をクリックします。
ブループリントの作成画面の基本タブが表示されるので各項目を入力し、「次へ:成果物」をクリックします。
定義の場所では、「…」をクリックし表示される定義の場所画面より、リソース作成先のサブスクリプションを選択し、「選択」ボタンをクリックします。
 
		ブループリントの作成画面の「成果物」タブでは、ブループリントで作成するリソースの定義を行います。
まず、リソースグループを作成する定義を追加します。
	「成果物の追加」をクリックし、表示された画面の「成果物の種類」より「リソースグループ」を選択し、「追加」をクリックします。
	 この画面でリソースグループ名、場所を指定することも可能ですが、ブループリントの割り当て時にこれらの項目を入力する定義とします。(動的パラメーターとして定義します)
 
		次に、リソースグループに ARM Template でストレージアカウントを作成する定義を追加します。
リソースグループの下の「成果物の追加」をクリックし、成果物の追加画面で各項目を入力し、「追加」をクリックします。
	    「Parameter」は、リソースグループ同様動的なパラメーターとするため、ここではデフォルトのままとします。
 
		Template には、ストレージアカウントを作成するための ARM Template の JSON を入力します。
{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "storageAccountName": {
            "type": "string"
        },
        "storageAccountType": {
            "type": "string",
            "defaultValue": "Standard_LRS",
            "allowedValues": [
                "Standard_LRS",
                "Standard_GRS",
                "Standard_ZRS",
                "Premium_LRS"
            ],
            "metadata": {
                "description": "Storage Account type"
            }
        },
        "location": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]",
            "metadata": {
                "description": "Location for all resources."
            }
        }
    },
    "variables": {
    },
    "resources": [{
        "type": "Microsoft.Storage/storageAccounts",
        "name": "[parameters('storageAccountName')]",
        "location": "[parameters('location')]",
        "apiVersion": "2018-07-01",
        "sku": {
            "name": "[parameters('storageAccountType')]"
        },
        "kind": "StorageV2",
        "properties": {}
    }],
    "outputs": {
        "storageAccountName": {
            "type": "string",
            "value": "[parameters('storageAccountName')]"
        }
    }
}
	次に、リソースグループへのロールの割り当ての定義を追加します。
	    ここでは、共同作成者権限を割り当てる定義を追加しています。
 
		ここまでの作業で、リソースグループの作成、リソースグループへのロールの割り当て、リソースグループにストレージアカウントを作成する定義ができました。
 
		続いて、別のリソースグループの作成と、作成したリソースグループに Web Apps を作成する定義を行います。
	    操作の流れは先ほど作成したストレージアカウントの作成と同じです。
リソースグループを作成する定義を追加します。
 
		リソースグループに ARM Template で Web Appsを作成する定義を追加します。
 
		Template には、Web Apps を作成するための ARM Template の JSON を入力します。
{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "webSiteName": {
            "type": "string"
        },
        "hostingPlanName": {
            "type": "string",
            "minLength": 1
        },
        "skuName": {
            "type": "string",
            "defaultValue": "F1",
            "allowedValues": [
                "F1",
                "D1",
                "B1",
                "B2",
                "B3",
                "S1",
                "S2",
                "S3",
                "P1",
                "P2",
                "P3",
                "P4"
            ],
            "metadata": {
                "description": "Describes plan's pricing tier and capacity. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/"
            }
        },
        "skuCapacity": {
            "type": "int",
            "defaultValue": 1,
            "minValue": 1,
            "metadata": {
                "description": "Describes plan's instance count"
            }
        },
        "SampleAppSettingValue": {
            "type": "string"
        }
    },
    "variables": {
    },
    "resources": [
        {
            "apiVersion": "2015-08-01",
            "name": "[parameters('hostingPlanName')]",
            "type": "Microsoft.Web/serverfarms",
            "location": "[resourceGroup().location]",
            "tags": {
                "displayName": "HostingPlan"
            },
            "sku": {
                "name": "[parameters('skuName')]",
                "capacity": "[parameters('skuCapacity')]"
            },
            "properties": {
                "name": "[parameters('hostingPlanName')]"
            }
        },
        {
            "apiVersion": "2015-08-01",
            "name": "[parameters('webSiteName')]",
            "type": "Microsoft.Web/sites",
            "location": "[resourceGroup().location]",
            "tags": {
                "[concat('hidden-related:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
                "displayName": "Website"
            },
            "dependsOn": [
                "[resourceId('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
            ],
            "properties": {
                "name": "[parameters('webSiteName')]",
                "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
                "siteConfig": {
                    "appSettings": [
                        {
                            "name": "SampleKey1",
                            "value": "[parameters('SampleAppSettingValue')]"
                        }
                    ]
                }
            }
        },
        {
            "apiVersion": "2014-04-01",
            "name": "[concat(parameters('hostingPlanName'), '-', resourceGroup().name)]",
            "type": "Microsoft.Insights/autoscalesettings",
            "location": "[resourceGroup().location]",
            "tags": {
                "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
                "displayName": "AutoScaleSettings"
            },
            "dependsOn": [
                "[resourceId('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
            ],
            "properties": {
                "profiles": [
                    {
                        "name": "Default",
                        "capacity": {
                            "minimum": 1,
                            "maximum": 2,
                            "default": 1
                        },
                        "rules": [
                            {
                                "metricTrigger": {
                                    "metricName": "CpuPercentage",
                                    "metricResourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
                                    "timeGrain": "PT1M",
                                    "statistic": "Average",
                                    "timeWindow": "PT10M",
                                    "timeAggregation": "Average",
                                    "operator": "GreaterThan",
                                    "threshold": 80.0
                                },
                                "scaleAction": {
                                    "direction": "Increase",
                                    "type": "ChangeCount",
                                    "value": 1,
                                    "cooldown": "PT10M"
                                }
                            },
                            {
                                "metricTrigger": {
                                    "metricName": "CpuPercentage",
                                    "metricResourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
                                    "timeGrain": "PT1M",
                                    "statistic": "Average",
                                    "timeWindow": "PT1H",
                                    "timeAggregation": "Average",
                                    "operator": "LessThan",
                                    "threshold": 60.0
                                },
                                "scaleAction": {
                                    "direction": "Decrease",
                                    "type": "ChangeCount",
                                    "value": 1,
                                    "cooldown": "PT1H"
                                }
                            }
                        ]
                    }
                ],
                "enabled": false,
                "name": "[concat(parameters('hostingPlanName'), '-', resourceGroup().name)]",
                "targetResourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
            }
        },
        {
            "apiVersion": "2014-04-01",
            "name": "[parameters('webSiteName')]",
            "type": "Microsoft.Insights/components",
            "location": "East US",
            "dependsOn": [
                "[resourceId('Microsoft.Web/sites/', parameters('webSiteName'))]"
            ],
            "tags": {
                "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', parameters('webSiteName'))]": "Resource",
                "displayName": "AppInsightsComponent"
            },
            "properties": {
                "applicationId": "[parameters('webSiteName')]"
            }
        }
    ]
}
	リソースグループへのロールの割り当ての定義を追加します。
 
		ここまでの作業でブループリント定義が完成しました。下書き保存します。
 
		下書き保存状態のブループリントを発行することで、ブループリントの割り当てができるようになります。
	ブループリントの定義画面より、先ほど作成したブループリントをクリックします。
 
		ブループリントの画面で「ブループリントを発行する」をクリックします。
 
		ブループリントを発行する画面で、バージョンを入力後、「公開」をクリックすることでブループリントを発行します。
	    バージョンには任意のバージョン番号を指定します。
 
		Azure Portal 上で「ブループリント定義が正常に発行されました」が通知されれば発行は完了です。
ブループリントの割り当てを行うことで、ブループリント定義より Azure のリソースが作成されます。
	先ほど発行したブループリントの画面で「ブループリントの割り当て」をクリックします。
 
		ブループリントの割り当て画面で各項目を入力し「割り当て」をクリックすると割り当て作業が開始されます。
	    「アーティファクト パラメーター」では、リソースグループ名、リソース名等リソース作成に必要な情報を入力します。これらは割り当て時に指定する動的パラメーターとなります。
パラメーターには次の値を指定しました。(一部のみ抜粋して記載)
リソースグループ1
| 項目名 | 設定値 | 
|---|---|
| リソースグループ:名前 | rg-blueprint-storage1 | 
| [ユーザー名またはアプリケーション名]([ユーザー名またはアプリケーション名]:共同作成者名) | テスト一郎 | 
| storageAccountName (ストレージアカウント) | stblueprint1 | 
リソースグループ2
| 項目名 | 設定値 | 
|---|---|
| リソースグループ:名前 | rg-blueprint-web | 
| [ユーザー名またはアプリケーション名]([ユーザー名またはアプリケーション名]:共同作成者名) | テスト一郎 | 
| webSiteName(Web Apps) | app-blueprint1 | 
| SampleAppSettingValue(Web Apps)※1 | Value1 | 
※1 アプリケーション設定の設定値です(キーは ARM Template で定義)
 
 		 
 		Azure Portal 上で「ブループリント割り当てが正常に完了しました」が通知されれば割り当て成功です。
 
 		通知にも記載されていますが、デプロイ作業が開始されているため、デプロイが完了するまで待ちます。
        割り当てられたブループリント画面で、デプロイの状況が確認できます。デプロイが完了すると、プロビジョニング状態が「成功」と表示されます。
 
		デプロイが完了したので、作成されたリソースを確認していきます。
リソースグループ1、ストレージアカウントがブループリント割り当て時のパラメーターの内容で作成されていることがわかります。
 
		リソースグループ2、Web Apps も同様に作成されています。
 
		 
		リソースグループへのロールの割り当ても正常に行えています。
 
		先ほど発行したブループリント定義を使用し、別環境として Azure リソースを作成する場合は以下の操作となります。
        (ブループリントの割り当ての操作は先ほど実施した操作とほぼ同じです)
 
		割り当て名は重複できないので先ほど異なる値を入力します。
            別環境として Azure リソースを作成するので、パラメーター値も先ほどと異なる値を入力します。
操作は以上です。
Azure Blueprints を使用した Azure のリソース作成を試してみました。
	    Azure を使用したシステム開発時に環境構築の一連の作業を Azure Blueprints に定義できるため、環境構築にかかる時間が大幅に軽減されることを実感できました。
今回紹介した内容は Azure Portal からの操作となりますが、Azure PowerShell や REST API での Azure Blueprints の操作や、ブループリント定義のコード化等面白そうな機能がそろっていますので、今後はよりディープに Azure Blueprints を学んでいこうと思います。