Azure Resource Manager の template の How-to


こんにちは。

最近は、訳あって ISV 企業の方とお会いする機会が多いのですが、Azure Resource Manager の template (resource template) を使って ISV 企業のカスタム ソリューションを展開する際に、「自分達のソリューションは展開できるか」、「どのようなことが可能か」などのご質問をよく受けます。
そこで今回は、Azure Resource Manager の template を使用したソリューション展開 (配置) の実践的ノウハウのいくつかを解説します。

 

概要

Azure Resource Manager は、Microsoft Azure、Azure Stack で使用可能な Azure 上の resource (service instance) 管理の基盤で、本稿で紹介するように、JSON ベースの Template-driven な展開 (宣言的な記述と展開) を提供します。後述の通り、複雑な構成も template を使って 1 つのまとまった resource group として展開と削除が可能です。

本投稿では template 作成のノウハウのみにフォーカスし、「Azure Resource Manager とは何か」、「Azure Service Management との違い何か」などのベースの解説は省略しますが、これらについては、MSDN のドキュメントでも解説されていますので参考にしてください。(下記で従来の Azure Service Management との比較も掲載しています。)

Azure Compute, Network & Storage Providers under the Azure Resource Manager
https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-azurerm-versus-azuresm/

重要な注意点として、現在の Azure Resource Manager はまだ最終形ではなく、対応 resource の種類も今後増えていく予定であり、下記では扱いませんが、今後は、Azure Service Bus、HDInsight、Azure Machine Learning などの他 resource も利用可能になる予定です。(一部は Azure Portal では利用可能になっています。)
下記はあくまでも現時点での確認結果ですので、その点に留意してください。

 

template 作成の基礎

いきなり template の中身の説明に入る前に、まず準備として、基本的な template 作成と展開の方法を紹介します。

基本的に、作成する template は UTF-8 の json ファイルなので、テキスト編集が可能なエディタであればツールは問いません。(ただし、「メモ帳」は、BOM の関係で使用しないほうが良いかもしれません。。。)

もし、Visual Studio と最新の Azure SDK をお使いの場合、プロジェクト テンプレートの [Cloud] – [Azure リソース グループ] (Azure Resource Group) を使って、ツールの補助を受けながら作成できます。

このツールを使うと、template の Json ファイルは、下図のような Visual な UI (Json Outline Tool Window) を使って resource (VM, VNet, Storage, DB 等々) の追加が可能なので、ある程度のひな形であれば、要素を手書きで編集せずに作成可能です。(細かな編集は Json を直接編集しますが、その場合も Intellisense を使って迅速に設定できます。)

 

template 展開の基礎

作成した json フォーマットの template を展開 (配置) すると、各 resource は Resource Group と呼ばれる単一の入れ物に入ります。(resource は、必ず、ただ 1 つの resource group に所属します。)

template を運用担当者に渡して配置する場合、Azure PowerShell Commandlet や Azure CLI を使うことができます。
例えば、Windows PowerShell を使って template を配置する場合は下記の通りです。(上述の Visual Studio のプロジェクトには、この Windows PowerShell の Script も含まれています。)
なお、コマンドラインから実行する場合は、入力パラメーター (後述の通り、template に parameter を渡すことができます) もあらかじめ指定するケースが多いと思いますが、そのような場合は、下記の通り parameter file を別で用意して指定できます。

New-AzureResourceGroup -Name MyResourceGroup -Location “West US” -TemplateFile mytemplate.json -TemplateParameterFile myparam.json -Force -Verbose

Node.js の Azure CLI を使った場合は下記の通りです。

azure group create “MyResourceGroup” “West US” -f mytemplate.json -d “myTest” -e myparam.json

カスタム アプリケーションなどにこの配置 (展開) 処理を組み込む場合は、例えば、.NET library を使うことも可能です。(詳細は省略します。)

また、Azure Portal (UI) から配置する場合は、[New] – [Web + Mobile] – [Template Deployment] を使用して、Json フォーマットの構成情報を展開できます。

また、下記の URL にアクセスすることで、下図の通り Azure Portal を使ったビジュアルな template 展開も可能で、Github の azure-quickstart-templates は、この方法を使って、Github (Wiki) 上のボタンをクリックすることで配置できるようになっています。

https://portal.azure.com/#create/Microsoft.Template/uri/{location url of json}

なお、Visual Studio を使っている開発者の方は、Visual Studio から [New Deployment] (新しい配置) を選択して配置が可能です。

Idempotent な性質も持っていますので、以降、展開に失敗した場合などには、再展開により続きから展開をおこなうこともできます。

 

template の歩き方 (基本から応用まで)

では、本題に入ります。
Azure Resource Manager template (resource template) を使って、どこまでのことが可能でしょう ?

 

基本構文

まず、resource template の基本的な構成ですが、下記の通り、4 つの要素で構成されています。

{
 "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
 "contentVersion": "1.0.0.0",
 "parameters": {
 ...
 },
 "variables": {
 ...
 },
 "resources": [
 ...
 ],
 "outputs": {
 ...
 }
}

上記の resources が本体となる記述部分で、ここに、Azure Virtual Machine (仮想マシン)、Azure Web App (Web アプリ)、Azure Storage、Azure SQL Database、Azure Redis Cache 等々の配置する resource 情報を定義します。(前述の通り、今後、Azure Machine Learning など他の resource も順次 対応予定です。)
例えば、Virtual Network を配置する場合には、下記のように記述します。

下記の通り、各 resource ごとに location (region) を個別に指定できるので、Disaster Recovery (災害対策) 構成のように、異なる location を単一の resource group に配置することも可能です。

{
 "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
 "contentVersion": "1.0.0.0",
 "parameters": {
 },
 "variables": {
 },
 "resources": [
  {
   "name": "testvnet01",
   "type": "Microsoft.Network/virtualNetworks",
   "location": "West US",
   "apiVersion": "2015-06-15",
   "properties": {
    "addressSpace": {
     "addressPrefixes": [
      "10.0.0.0/16"
     ]
    },
    "subnets": [
     {
      "name": "testsubnet01",
      "properties": {
       "addressPrefix": "10.0.0.0/24"
      }
     }
    ]
   }
  }
 ],
 "outputs": {
 }
}

同様に、Azure Storage Account を作成する場合は以下になります。

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
  },
  "variables": {
  },
  "resources": [
    ...,

    {
      "name": "tsmatsuzteststorage01",
      "type": "Microsoft.Storage/storageAccounts",
      "location": "West US",
      "apiVersion": "2015-06-15",
      "properties": {
        "accountType": "Standard_GRS"
      }
    }
  ],
  "outputs": {
  }
}

 

Parameter の受け取り

配置をおこなう template の利用者が値を設定できるようにするには、上記の parameters を指定します。
例えば、上記で作成した Virtual Network や Storage で、Location を利用者に選択させて配置したい場合、下記の通り記述します。

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "test01loc": {
      "type": "string",
      "defaultValue": "West US",
      "allowedValues": [
        "East US",
        "West US",
        "West Europe",
        "East Asia"
      ]
    }
  },
  "variables": {
  },
  "resources": [
    {
      "name": "testvnet01",
      "type": "Microsoft.Network/virtualNetworks",
      "location": "[parameters('test01loc')]",
      "apiVersion": "2015-06-15",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "10.0.0.0/16"
          ]
        },
        "subnets": [
          {
            "name": "testsubnet01",
            "properties": {
              "addressPrefix": "10.0.0.0/24"
            }
          }
        ]
      }
    },
    ...

  ],
  "outputs": {
  }
}

この template を上述の URI を使った方法 (Azure Portal のウィザードを使用する方法) で展開した場合、下図の通り、parameter の入力が UI で促されます。(なお、Windows PowerShell や Azure CLI を使った場合は、上述の通り parameter file を作成して指定できます。)

 

リソースどうしの依存関係

どんどん行きましょう!
上記の Storage Account に Disk (OS Disk) を作成し、さらに、上記の Virtual Network に接続する Virtual Machine を作成するには、下記の通り記述します。
なお、作成している Virtual Machine は v2 (resource manager based) で、下記の通り NIC の resource も必要です。

複数の resource を依存させる場合は、作成後の resource id が必要になることがあります。例えば、Virtual Machine を Virtual Network (の Subnet) に接続するために Virtual Network の resource id が必要ですが、下記の通り resourceId 関数を使って作成後の id を指定できます。

また、「作成の順序によっては失敗するのではないか」と気になるかもしれませんが、こうした点を解決するために、下記の通り dependsOn に依存関係を記述します。

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
  },
  "variables": {
  },
  "resources": [
    {
      "name": "testvnet01",
      "type": "Microsoft.Network/virtualNetworks",
      ...

    },
    {
      "name": "tsmatsuzteststorage01",
      "type": "Microsoft.Storage/storageAccounts",
      ...

    },
    {
      "name": "testnic01",
      "type": "Microsoft.Network/networkInterfaces",
      "location": "West US",
      "apiVersion": "2015-06-15",
      "dependsOn": [
        "Microsoft.Network/virtualNetworks/testvnet01"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig01",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', 'testvnet01'), '/subnets/testsubnet01')]"
              }
            }
          }
        ]
      }
    },
    {
      "name": "testwin01",
      "type": "Microsoft.Compute/virtualMachines",
      "location": "West US",
      "apiVersion": "2015-06-15",
      "dependsOn": [
        "Microsoft.Storage/storageAccounts/tsmatsuzteststorage01",
        "Microsoft.Network/networkInterfaces/testnic01"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "Basic_A1"
        },
        "osProfile": {
          "computername": "mycomputer01",
          "adminUsername": "demouser",
          "adminPassword": "P@ssw0rd01"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "MicrosoftWindowsServer",
            "offer": "WindowsServer",
            "sku": "2012-R2-Datacenter",
            "version": "latest"
          },
          "osDisk": {
            "name": "testdisk01",
            "vhd": {
              "uri": "http://tsmatsuzteststorage01.blob.core.windows.net/vhds/test01.vhd"
            },
            "caching": "ReadWrite",
            "createOption": "FromImage"
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', 'testnic01')]"
            }
          ]
        }
      }
    }
  ],
  "outputs": {
  }
}

上記で Virtual Machine や Virtual Network は構成されましたが、この構成では外界 (internet) との接続ポイントがないため、 RDP (Windows の場合) や SSH (Linux の場合) を使った接続は不可能です。

この問題を解決するには、さらに Public IP の resource を作成して、下記の通り関連付けます。このように構成すると、割り当てられた IP アドレスや、下記の domainNameLabel を使って、既定で {domainNameLabel}.{location}.cloudapp.azure.com (よって今回の場合は endpointtest01.westus.cloudapp.azure.com) のマシン名 (FQDN) で外からアクセスできます。

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
  },
  "variables": {
  },
  "resources": [
    ...

    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "testip01",
      "location": "West US",
      "properties": {
        "publicIPAllocationMethod": "Dynamic",
        "dnsSettings": {
          "domainNameLabel": "endpointtest01"
        }
      }
    },
    ...

    {
      "name": "testnic01",
      "type": "Microsoft.Network/networkInterfaces",
      ...

      "dependsOn": [
        "Microsoft.Network/virtualNetworks/testvnet01",
        "Microsoft.Network/publicIPAddresses/testip01"
      ],
      ...

      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig01",
            "properties": {
              ...

              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses', 'testip01')]"
              }
            }
          }
        ]
      }
    },
    ...

この他に、複数台構成の場合には、Load Balancer (Microsoft.Network/loadBalancers) や Availability Set (Microsoft.Compute/availabilitySets) などの resource も必要になるので、随時、追加してください。(2016/01 追記 : これらの構成方法については「Azure (ARM) の Load Balancer, Auto-Scaling の構成」に記載しました。)

つまり、現実の resource template の記述は、そこそこ複雑になってきますので、ここで紹介している基礎を抑えながら眺めておいてください。

 

Custom Image の利用

では、ISV 企業が、自社のソフトウェアなどをプレインストールされた形で展開したい場合はどのようにすれば良いでしょう ?

まず、上記構成の imageReference を見てください。(上記のサンプルでは、Windows Server 2012 R2 Datacenter Edition をインストールしています。)
Virtual Machine の展開の際、このように Azure (Marketplace) に登録されているイメージを指定できるため、この方法で、例えば、SharePoint のインストールされた Windows イメージ、SQL Server のインストールされた Windows イメージ、Puppet (Master) のインストールされた Linux イメージなどを展開できます。

補足 : 利用可能な Image Publisher, Offer, Sku は PowerShell で確認できます。下記は、利用可能な Image Publisher を取得します。
Get-AzureRmVMImagePublisher -Location eastus | Where-Object { $_.PublisherName -match "oracle" }
下記は、取得した Image Publisher から、利用可能な Offer を取得します。
Get-AzureRmVMImageOffer -Location eastus -PublisherName Oracle
下記は、取得した Image Publisher と Offer から Sku を取得します。
Get-AzureRmVMImageSku -Location eastus -PublisherName Oracle -Offer Oracle-Linux-7

補足 : Microsoft 以外の 3rd party が提供する Image (Certified の Image) を展開する場合には、いくつかの注意点があります。この留意事項については「ARM template で Azure Marketplace の 3rd party image を展開する」にまとめましたので参照してください。(2016/02 追記)

また、独自に作成したカスタムの VM Image (.vhd ファイル) を元に VM を作成することもできます。下記の通り記述します。(この場合、imageReference は不要なので削除してください。)

注意 : Custom の VM Image (.vhd) を配置する場合、配置元の custom image (.vhd) は、配置先と同じ (Azure Resource Manager の管理下にある) Storage Account を使用する必要があります。このため、いったん Storage を作成しておいてから vhd を upload して、その後で配置をおこなう必要があります。(つまり、単一の template ファイルで記述することは不可能で、Windows PowerShell などと組み合わせて展開する必要があります。) また、Azure Service Manager (v1, Azure Classic Portal) で capture した image は展開できません。(Azure から capture する場合は、ARM の REST API などを使って ARM ベースで capture をおこなってください。)

. . .

{
  "name": "testwin01",
  "type": "Microsoft.Compute/virtualMachines",
  ...

  "properties": {
    ...

    "storageProfile": {
      "osDisk": {
        "name": "testdisk01",
        "osType": "windows",
        "image": {
          "uri": "http://sourcestorage01.blob.core.windows.net/vhds/originalsource.vhd"
        },
        "vhd": {
          "uri": "http://sourcestorage01.blob.core.windows.net/vhds/test01.vhd"
        },
        "caching": "ReadWrite",
        "createOption": "FromImage"
      }
    },
    ...

  }
}
. . .

 

Extension (カスタム セットアップの組み込み)

また、ほとんどのソフトウェアはインストールするだけでは不充分で、インストール後に必要なセットアップや構成作業などをおこなう必要があります。

こうしたセットアップは、CustomScriptForLinux (sh コマンド)、CustomScriptExtension (Windows コマンド)、DSC (Windows の PowerShell Desired State Configuration) といった Azure Virtual Machine の extension resource が使用できます。実は、この方法で、ネットワーク インストールから構成までのすべてをセットアップする方法もアリです。

補足 : Windows におけるバイナリ コマンドの配置と実行や、Ubuntu、CoreOS における cloud-config の送信の際には、customData を使うこともできます。詳細は「Microsoft Azure : Injecting custom data into an Azure virtual machine」を参照してください。(ARM template でも使えます。)

例えば、OS の設定変更、SQL の実行 (データベースの provisioning) など、簡単なスクリプトを実行したいだけなら下記の通り記述できます。(前者は Windows、後者は Linux です。) inline コマンドの記述だけでなく、下記の通り、スクリプト ファイル (.ps1, .sh) を準備して実行し、parameter はコマンドの引数として渡すことができます。(例えば、配置したデータベースと Web サーバー間の接続を構成するケースなど、現実の構成では、こうした parameter 情報の受け渡しは必要不可欠です。)

Windows の場合

. . .

{
  "type": "Microsoft.Compute/virtualMachines/extensions",
  "name": "testwin01/somesetup01",
  "apiVersion": "2015-06-15",
  "location": "West US",
  "dependsOn": [
    "[resourceId('Microsoft.Compute/virtualMachines', 'testwin01')]"
  ],
  "properties": {
    "publisher": "Microsoft.Compute",
    "type": "CustomScriptExtension",
    "typeHandlerVersion": "1.4",
    "settings": {
      "fileUris": [
        "http://tsmatsuz-demo01.azurewebsites.net/somesetup.ps1"
      ],
      "commandToExecute": "[concat('powershell -ExecutionPolicy Unrestricted -file somesetup.ps1 -paramTest ', parameters('testdata01'))]"
    }
  }
}
. . .

Linux の場合

. . .

{ 
  "type": "Microsoft.Compute/virtualMachines/extensions",
  "name": "testubuntu01/somesetup01",
  "apiVersion": "2015-06-15",
  "location": "West US",
  "dependsOn": [
    "[resourceId('Microsoft.Compute/virtualMachines', 'testubuntu01')]"
  ],
  "properties": {
    "publisher": "Microsoft.OSTCExtensions", 
    "type": "CustomScriptForLinux", 
    "typeHandlerVersion": "1.2", 
    "settings": {
      "fileUris": [
        "http://tsmatsuz-demo01.azurewebsites.net/somesetup.sh"
       ],
       "commandToExecute": "[concat('sh somesetup.sh ', parameters('testdata01'))]"
    }
  } 
} 
. . .

また、依存関係のある複数コンポーネント (ソフトウェア) のインストールや構成など、複雑なセットアップをおこなう場合は、PowerShell DSC、Puppet、Chef などの構成管理用の extension が使用できます。

補足 : PowerShell DSC は Linux でも使用できます (PowerShell DSC for Linux を参照)。

例えば、上記で配置した Windows Server 2012 R2 に、IIS と ASP.NET 4.5 をインストールするには、まず、PowerShell DSC を使って以下のスクリプト ファイル (.ps1 ファイル) を準備し、このファイルを zip 化して見える場所に置いておきます。(作成したアプリを展開する場合、Microsoft Web Deployment (msdeploy) の Package (zip ファイル) の展開も可能です。) なお、今回はサンプルを簡単にする目的で、Built-in Resource (下記の WindowsFeature) のみを使って 単に IIS と ASP.NET 4.5 をインストールしていますが、現実の構成では、例えば、Active Directory インストール後のドメイン昇格 (dcpromo) や、独自の構成 (configuration) などが必要になるでしょう。こうした場合、DSC の composite resource や custom resource を作成して、一緒に配置 (および zip 化) します。
つまり、今回は あえて簡単なサンプルにしていますが、通常は (現実の DSC の構成は)、もっと複雑になるので注意してください。

補足 : よく使う DSC resource (例えば、上述の AD の構成など) は、下記に open source として公開されているので活用してください。
https://github.com/PowerShell/DscResources

補足 : PowerShell DSC for Linux で使用可能な Built-in resource については「Built-In Desired State Configuration Resources for Linux」を参照してください。

configuration ConfigureAspNet
{
### Specify parameters like this (This time, not needed)
#  param
#  (
#    [Parameter(Mandatory)]
#    [String]$MyParam01
#  )

### Specify additional DSC resource (This time, not needed)
#  Import-DscResource -ModuleName xMyCustomResource01, xMyCustomResource02

  Node localhost
  {
    ### Install IIS
    WindowsFeature IIS
    {
      Name = "Web-Server"
      Ensure = "Present"
    }

    ### Install ASP.NET 4.5
    WindowsFeature AspNet45
    {
      Name = "Web-Asp-Net45"
      Ensure = "Present"
    }

    ### When using custom resource
    #xMyCustomResource01 MySetup01
    #{
    #  XXX = YYY
    #  . . .
    #}

  }
}

あとは、この zip ファイル (今回は InstallASPNET.zip と仮定します) を PowerShell DSC extension resource として template に設定します。
Virtual Machine に展開するため、下記の通り Virtual Machine resource に extension resource を記述します。

. . .

{
  "name": "testwin01",
  "type": "Microsoft.Compute/virtualMachines",
  ...

  "resources": [
    {
      "type": "Microsoft.Compute/virtualMachines/extensions",
      "name": "testwin01/installaspnet",
      "apiVersion": "2015-06-15",
      "location": "West US",
      "dependsOn": [
        "[resourceId('Microsoft.Compute/virtualMachines', 'testwin01')]"
      ],
      "properties": {
        "publisher": "Microsoft.Powershell",
        "type": "DSC",
        "typeHandlerVersion": "2.19",
        "settings": {
          "ModulesUrl": "http://tsmatsuz-demo01.azurewebsites.net/InstallASPNET.zip",
          "ConfigurationFunction": "InstallASPNET.ps1\\ConfigureAspNet",
          "Properties": {
          }
        }
      }
    }
  ]
}
. . .

下記の通り、DSC の extension に対して parameter を渡すことも可能です。(DSC 側は、上述のコメント アウトの通り記述して、この parameter を受け取ります。)

. . .

{
  "name": "testwin01",
  "type": "Microsoft.Compute/virtualMachines",
  ...

  "resources": [
    {
      "type": "Microsoft.Compute/virtualMachines/extensions",
      "name": "testwin01/installaspnet",
      "apiVersion": "2015-06-15",
      "location": "West US",
      "dependsOn": [
        "[resourceId('Microsoft.Compute/virtualMachines', 'testwin01')]"
      ],
      "properties": {
        "publisher": "Microsoft.Powershell",
        "type": "DSC",
        "typeHandlerVersion": "2.19",
        "settings": {
          "ModulesUrl": "http://tsmatsuz-demo01.azurewebsites.net/InstallASPNET.zip",
          "ConfigurationFunction": "InstallASPNET.ps1\\ConfigureAspNet",
          "Properties": {
            "MyParam01": "test data 01",
            "MyParam02": "test data 02"
          }
        }
      }
    }
  ]
}
. . .

また、例えば、(Linux に対する) Docker container の配置の際には、MSOpenTech の DockerExtension が使用できます。

このように、既存の extension で使えるものも多数あるので、上記のように  CustomScript や DSC でカスタムの構成 (セットアップ) を記述する前に、使用可能なイメージ (imageReference) や使える extension があるかどうか確認しておくと良いでしょう。

 

Template の Nest

resource を分けたい場合は template file のネスト (入れ子) も可能です。

例えば、下記は、上述と同様 Virtual Machine のセットアップをおこないますが、ネットワーク関連 (サブネット、IP アドレス、NIC など) の設定を netdeploy.json という子供の Template にわけて設定しています。

下記の通り、親の Template から子の Template に parameter を渡すことも可能ですし、逆に、outputs を使用して子の Template の結果を親の Template に渡すこともできます。下記では、作成された NIC の resourceId を親に渡しています。(作成された NIC のリソースそのものを渡すこともできます。この場合、Json Object として親に渡されます。)

Parent Template (.json)

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
  },
  "variables": {
  },
  "resources": [
    {
      "name": "netdeploy",
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2015-06-15",
      "dependsOn": [ ],
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "http://testdeploy.com/netdeploy.json",
          "contentVersion": "1.0.0.0"
        },
        "parameters": {
          "location": {
            "value": "East US"
          }
        }
      }
    },
    . . .

    {
      "name": "testwin",
      "type": "Microsoft.Compute/virtualMachines",
      "location": "East US",
      "apiVersion": "2015-06-15",
      "dependsOn": [
        "Microsoft.Resources/deployments/netdeploy",
        . . .
      ],
      "properties": {
        . . .
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[reference('netdeploy').outputs.networkInterfaceResourceId.value]"
            }
          ]
        }
      }
    }
  ],
  "outputs": {
  }
}

Child Template (.json)

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "location": { 
      "type": "string"
    }
  },
  "variables": {
  },
  "resources": [
    {
      "name": "testvnet",
      "type": "Microsoft.Network/virtualNetworks",
      "location": "[parameters('location')]",
      "apiVersion": "2015-06-15",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "10.0.0.0/16"
          ]
        },
        "subnets": [
          {
            "name": "testsubnet",
            "properties": {
              "addressPrefix": "10.0.0.0/24"
            }
          }
        ]
      }
    },
    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "testip",
      "location": "[parameters('location')]",
      "properties": {
        "publicIPAllocationMethod": "Dynamic",
        "dnsSettings": {
          "domainNameLabel": "endpointtest"
        }
      }
    },
    {
      "name": "testnic",
      "type": "Microsoft.Network/networkInterfaces",
      "location": "[parameters('location')]",
      "apiVersion": "2015-06-15",
      "dependsOn": [
        "Microsoft.Network/virtualNetworks/testvnet",
        "Microsoft.Network/publicIPAddresses/testip"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', 'testvnet'), '/subnets/testsubnet')]"
              },
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses', 'testip')]"
              }
            }
          }
        ]
      }
    }
  ],
  "outputs": {
    "networkInterfaceResourceId" : {
      "type" : "string",
      "value" : "[resourceId('Microsoft.Network/networkInterfaces', 'testnic')]"
    }
  }
}

なお、Azure Resource Manager template では、方針上の理由から if などの条件分岐はできないようになっていますが (宣言的な性質や意味が薄れるためでしょう。。。)、実は、上記のネストを使うと、例えば、ユーザーの入力結果 (parameter) に応じてネストする template の uri を変えることができるため、事実上の条件分岐が可能です。(お行儀の良し悪しは別として。。。)

 

copy / copyIndex による複数展開 (Resource Loop)

また、同じ構成を複数展開したい場合は、上記のネストではなく copy を使う方法もあります。
例えば、下記の通り記述すると、ユーザーが指定した台数の Virtual Machine を展開できます。(それぞれ、testwin0, testwin1, testwin2, … とネーミングしています。)

. . .

{
  "name": "[concat('testwin', copyIndex())]",
  "type": "Microsoft.Compute/virtualMachines",
  ...

  "copy": {
    "name": "vmCopy",
    "count": "[parameters('vmCount')]"
  }
}
. . .

下記では、10 個の IP、10 個の NIC を作成して、10 台の Virtual Machine を作成しています。(ただし、Load Balancer と Availability Set は作成していませんのでご注意ください。)

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
  },
  "variables": {
  },
  "resources": [
    {
      "name": "testvnet",
      "type": "Microsoft.Network/virtualNetworks",
      "location": "East US",
      "apiVersion": "2015-06-15",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "10.0.0.0/16"
          ]
        },
        "subnets": [
          {
            "name": "testsubnet",
            "properties": {
              "addressPrefix": "10.0.0.0/24"
            }
          }
        ]
      }
    },
    {
      "name": "tsmatsuzteststorage",
      "type": "Microsoft.Storage/storageAccounts",
      "location": "East US",
      "apiVersion": "2015-06-15",
      "properties": {
        "accountType": "Standard_GRS"
      }
    },

    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "[concat('testip', copyIndex())]",
      "location": "East US",
      "properties": {
        "publicIPAllocationMethod": "Dynamic",
        "dnsSettings": {
          "domainNameLabel": "[concat('endpointtest', copyIndex())]"
        }
      },
      "copy": {
        "name": "testipcopy",
        "count": 10
      }
    },

    {
      "name": "[concat('testnic', copyIndex())]",
      "type": "Microsoft.Network/networkInterfaces",
      "location": "East US",
      "apiVersion": "2015-06-15",
      "dependsOn": [
        "Microsoft.Network/virtualNetworks/testvnet",
        "[concat('Microsoft.Network/publicIPAddresses/testip', copyIndex())]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "[concat('ipconfig', copyIndex())]",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', 'testvnet'), '/subnets/testsubnet')]"
              },
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses', concat('testip', copyIndex()))]"
              }
            }
          }
        ]
      },
      "copy": {
        "name": "testniccopy",
        "count": 10
      }
    },
    {
      "name": "[concat('testwin', copyIndex())]",
      "type": "Microsoft.Compute/virtualMachines",
      "location": "East US",
      "apiVersion": "2015-06-15",
      "dependsOn": [
        "Microsoft.Storage/storageAccounts/tsmatsuzteststorage",
        "[concat('Microsoft.Network/networkInterfaces/testnic', copyIndex())]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "Basic_A1"
        },
        "osProfile": {
          "computername": "[concat('mycomputer', copyIndex())]",
          "adminUsername": "demouser",
          "adminPassword": "P@ssw0rd01"
        },
        "storageProfile": {
          "imageReference": {
            "publisher": "MicrosoftWindowsServer",
            "offer": "WindowsServer",
            "sku": "2012-R2-Datacenter",
            "version": "latest"
          },
          "osDisk": {
            "name": "[concat('testdisk', copyIndex())]",
            "vhd": {
              "uri": "[concat('http://tsmatsuzteststorage.blob.core.windows.net/vhds/test',copyIndex(),'.vhd')]"
            },
            "caching": "ReadWrite",
            "createOption": "FromImage"
          }
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', concat('testnic',copyIndex()))]"
            }
          ]
        }
      },
      "copy": {
        "name": "testwincopy",
        "count": 10
      }
    }
  ],
  "outputs": {
  }
}

上記の copy の名前 (testipcopy, testniccopy, testwincopy) をdependsOn に設定すると、この copy 関数で作成した複数の resource すべてに対して依存関係を設定できます。

 

なお、Azure Resource Explorer というツールを使用すると、既存の構成から resource 定義の確認も可能です。
また、下記に豊富なサンプルが提供されていますので、是非こちらも参考にいろいろと応用してみてください。

Github – azure-quickstart-templates

https://github.com/Azure/azure-quickstart-templates

Azure Resource Manager に対するニーズと開発状況 (検討中の新機能など) は フィードバック にまとめられており、現在のステータスも確認できます。ISV 企業の方は自分達のソリューション構成が可能か確認していただき、Release までの間、是非、みなさんの声 (要望) も反映してください。(きっと、他の方も必要としているはずです。)

 

2016/01 追記 : ARM template を Azure Marketplace に登録 (発行) できるようになりました ! (ガイダンスが出てきました)

https://azure.microsoft.com/ja-jp/documentation/articles/marketplace-publishing-getting-started/

 

Comments (0)

Skip to main content