ARM 配下のマスターイメージをVMに展開するためのリソーステンプレートを作成する

前回までの投稿は以下の通りです。

インフラエンジニアのための ARM シリーズ

  1. Azure Resource Manager で作成した仮想マシンをキャプチャーする
    http://blogs.technet.com/b/junichia/archive/2015/11/25/3657462.aspx
  2. リソーステンプレートを作成する~超基礎編http://blogs.technet.com/b/junichia/archive/2015/11/25/3657470.aspx

今回は、キャプチャーしたマスターイメージをVMに展開するためのリソーステンプレートを作成します。

作成後のリソーステンプレートはこちらからダウンロードしてください。

以下のオペレーションは動画で実際に確認することができますので、実際に試すことができない方は是非ご覧ください。

まずは、作成しなければならないリソースを把握しておきます。

今回作成する仮想マシンをリソースに分解した図が以下の通りです。

image

既に、マスターイメージと仮想ネットワーク、サブネットは作成済みなので、作成しなければならないのは、以下の4つのリソースです。リソースを識別するには「リソースタイプ」を使用します。()内の文字列がそれぞれのリソースタイプです。

  • Public IP(Microsoft.Network/publicIPAddresses)
  • NIC(Microsoft.Network/networkInterfaces)
  • VM(Microsoft.Compute/virtualMachines)
  • OS Disk(Microsoft.Storage/storageAccounts)

もちろん、ただ作成するだけでなく、リソース間の関連付けや依存関係も定義しなければなりません。

OS Disk は本来ストレージアカウントから作成する必要があるのですが、今回は既存のストレージアカウントに展開します。そのため、今回は明に作成する必要はありません。仮想マシンを作成する際に OS のディスクパスがどこか?を指定すれば、そこに自動的にディスクを作成してOSを展開してくれます。

Local IP アドレスはリソースではなく、これは NIC のプロパティとして位置づけられています。

リソーステンプレートの大まかな構造については前回解説した通りです。Parameters、Variables、Resourcesの3つが重要だと書きました。上記のリソースを作成するには Resources 句を使用しますが、まずは Parameters 句から順に読み解きましょう。

■ Parameter 句

仮想マシンを展開するには、以下のように多くの引数が必要です。このことは、実際に仮想マシンを作ったことがある方ならばお分かりかと思います。

  • マスターイメージの URI(要はディスクが格納されているパスのことです)
  • 仮想マシンの名前
  • 展開する OS のタイプ(Linux or Windows)
  • 管理者のユーザーID
  • 管理者のパスワード
  • 仮想マシンのサイズ(A1とかDS1とかいうやつ)
  • ストレージアカウント(仮想マシンのOSディスクを格納するためのストレージを指定する必要があります)
  • 仮想マシンを展開する仮想ネットワーク
  • 仮想マシンを展開する仮想ネットワーク内のサブネット

上記を固定値にするのであれば Variables 句でもよいのですが、せっかく「テンプレート」を作っているのに値を埋め込んでしまうなんてナンセンスです。よって、上記は Parameter 句に引数として定義します。

実際の定義は以下の通りです。特徴的な部分を赤字にしましたので確認してください。

"parameters": { "osMasterImageUri": { "type": "string", "metadata": { "description": "マスターイメージのURI" } }, "vmName": { "type": "string", "metadata": { "description": "仮想マシンの名前" } }, "osType": { "type": "string",    "allowedValues": [ "Windows", "Linux" ], "defaultValue" :"Windows" , "metadata": { "description": "OSのタイプ" } }, "adminUserName": { "type": "string", "metadata": { "description": "管理者ユーザーID" } }, "adminPassword": { "type": "securestring", "metadata": { "description": "管理者ユーザーIDのパスワード" } }, "vmSize": { "type": "string", "allowedValues": [ "Standard_A1", "Standard_A2" ], "defaultValue" :"Standard_A1", "metadata": { "description": "仮想マシンのサイズ" } }, "StorageAccountName": { "type": "string", "metadata": { "description": "ストレージアカウントの名前" } }, "existingVirtualNetworkName": { "type": "string", "metadata": { "description": "仮想ネットワーク" } }, "subnetName": { "type": "string", "metadata": { "description": "サブネット名" } }}

AllowdValue を使用すると、ユーザーに選択肢を提示することができます。OSのタイプには Windows と Linux しかありませんから、直接入力させるよりも親切ですね。このとき、defautValue を使用して、規定値を定義しておくこともできます。

引数のタイプとして、String の代わりに SecureString を使用すると、入力を ***** のようにアスタリスクに変換することができます。また、値は自動的に Base64 でエンコードされます。今回はパスワードに対して SecureString を使用しています。

■ Variables 句

  "variables": { "api-version": "2015-06-15", "location": "[resourceGroup().location]", "publicIPAddressType": "Dynamic", "vnetID": "[resourceId('Microsoft.Network/virtualNetworks', parameters('existingVirtualNetworkName'))]", "subnetRef": "[concat(variables('vnetID'),'/subnets/', parameters('subnetName'))]", "nicName": "[concat(parameters('vmName'),'-nic')]", "publicIPAddressName": "[concat(parameters('vmName'),'-pip')]", "osDiskVhdName": "[concat('http://',parameters('StorageAccountName'),'.blob.core.windows.net/vhds/',parameters('vmName'),'osDisk.vhd')]"}

前回解説したように、Variables 句では、Parameters 句では得られなかった変数を作成します。今回は上から以下の変数を作成しています。

  • API のバージョン:
    これは Resources 句で各リソースを作成する際に必ず必要になる値です。共通の値なので、定数として定義しています。
  • リソースを作成する場所:
    resourceGroup() はリソースグループのインスタンスで、その属性である location から場所を取り出しています。
  • パブリックIPアドレスのタイプ:
    動的に取得するため、Dynamic を指定しています。
  • 仮想ネットワークの ID:
    仮想マシンを作成する際、どの仮想ネットワークの、どのサブネットに展開するかを指定する必要があります。その際、仮想ネットワークの名前を指定するのではなく、リソース ID で指定します。リソース ID を取得するには、上記のように resourceId 関数を使用します。resourceId 関数の書式は以下の通りです。
    resourceId ( <リソースタイプ>, <リソースの名前>)
    リソースの名前は、Parameters 句で指定した引数から取得しています。
  • サブネットの参照用パス:
    仮想マシンを展開するサブネットのパスを指定しています。concat 関数は複数の文字列を結合するための関数です。
  • NIC の名前:
    NIC は独立したリソースであるため、リソースの名前を決める必要があります。今回は、仮想マシン名に –nic を付加して NIC 名にしています。
  • パブリックIPアドレスの名前:
    パブリックIPアドレスもリソースの1つです。そのため、識別するための名前が必要です。
  • OS ディスクのパス:
    OSをインストールする VHD ファイルのフルパスを指定します。もしここで指定したストレージアカウントが存在しない場合には、他のリソース同様、Resources 句で作成する必要があります。

■ Resources 句

いよいよ Resources 句です。ここでは、これまでに用意した変数を使用してリソースを作成していきます。一気に全部見るのは疲れるので、リソースごとに分割してみていきましょう。

  • パブリック IP アドレス
{ "apiVersion": "[variables('api-version')]", "type": "Microsoft.Network/publicIPAddresses", "name": "[variables('publicIPAddressName')]", "location": "[variables('location')]", "properties": { "publicIPAllocationMethod": "[variables('publicIPAddressType')]" }}

apiVersion はリソースを作成するときに必ず指定しなければならない値です。既に Variables 句で定義しているので、その値を取得しています。

type には作成するリソースのタイプを指定します。パブリックIPアドレスの場合は、Microsoft.Network/publicIPAddresses を指定します。

name はリソースの名前です。くどいようですが、リソースには必ず名前を指定して識別できるようにする必要があります。なので、くれぐれも適当な名前は付けないでください。きちんと命名規約を定義しておきましょう。

location はリソースを作成する場所です。仮想マシンを作成する場合には、関連するリソースは同じ場所でなければなりません。

Properties には、リソースの属性を定義します。ここでは パブリックIPアドレスのアロケーションメソッドを Dynamic に設定しています。

  • NIC

{ "apiVersion": "[variables('api-version')]", "type": "Microsoft.Network/networkInterfaces", "name": "[variables('nicName')]", "location": "[variables('location')]", "dependsOn": [ "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]" ], "properties": { "ipConfigurations": [ { "name": "ipconfig1", "properties": { "privateIPAllocationMethod": "Dynamic", "publicIPAddress": { "id": "[ resourceId ( 'Microsoft.Network/publicIPAddresses', variables( 'publicIPAddressName' ) ) ]" }, "subnet": { "id": "[variables('subnetRef')]" } } } ] }}

次に NIC を作成します。注目していただきたいのは dependsOn です。これは、リソース生成時の依存関係を示しています。この場合は、NIC を作成するには パブリックIP が作成されている必要があることを示しています。というのも、パブリック IP は NIC の属性の1つであり、NIC を作成するにはパブリック IP が存在していなければならないからです。dependsOn を使用すると、dependsOn に指定されたリソースの作成が完了するまで、当該リソースの作成は開始されません。逆にいえば、依存関係のないリソースはパラレルに作成されます。

  • VM

{ "apiVersion": "[variables('api-version')]", "type": "Microsoft.Compute/virtualMachines", "name": "[parameters('vmName')]", "location": "[variables('location')]", "dependsOn": [ "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]" ], "properties": { "hardwareProfile": { "vmSize": "[parameters('vmSize')]" }, "osProfile": { "computername": "[parameters('vmName')]", "adminUsername": "[parameters('adminUsername')]", "adminPassword": "[parameters('adminPassword')]" }, "storageProfile": { "osDisk": { "name": "[concat(parameters('vmName'),'-osDisk')]",g "osType": "[parameters('osType')]", "caching": "ReadWrite", "createOption": "FromImage", "image": { "uri": "[parameters('osMasterImageUri')]" }, "vhd": { "uri": "[variables('osDiskVhdName')]" } } }, "networkProfile": { "networkInterfaces": [ { "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]" } ] } }}

ここでも dependsOn に注目しましょう。今回は、NICが指定されています。つまり、仮想マシンを作成するには NIC が事前に作成されている必要があることを示しています。

仮想マシンを作成するには、少なくとも以下の 4つの Profile を指定する必要があります。

  • hardwareProfile
  • osProfile
  • storageProfile
  • networkProfile

hardwareProfile は仮想マシンのサイズを指定します。

osProfile には OS のコンピューター名と管理者ID、パスワードを指定します。パスワードは Base64 でエンコードされた値を指定する必要がありますが、Parameters 句で secureString を使用していると、自動的に Base64 エンコードされます。

storageProfile は OS 用のディスク(osDisk)、およびデータディスク(dataDisk)を指定しますが、今回は OS 用ディスクだけを指定しています。osDisk には以下のパラメタを指定しなければなりません。

  • name
    OS ディスクのパスを URI で指定する
  • osType
    Windows か Linux を指定する。今回は当然 Windows。
  • caching
    OSディスクのキャッシュ設定。OS ディスクは基本的に ReadWrte にする。
  • createOption
    OS を展開する際のオプション。今回はマスターイメージから展開するので、FromImage を指定する。
  • image
    FromImageを指定したので、ソースとなるマスターイメージのパスをURLで指定する。
    image
  • vhd
    image の複製先となるハードディスクのパスを URL で指定する。

networkProfile には仮想マシンにインストールする NIC を指定する。NIC は既に仮想ネットワークにマウントされているので、仮想マシンに対して仮想ネットワークを指定する必要はない。

以上でリソーステンプレートが完成しました。

これを展開するには、前回同様、「テンプレートのデプロイ」画面から展開します。

image

image

展開が始まると、以下のような画面が表示されます。

image

ARM 配下の仮想マシンは、以下のようにリソース単位で進捗状況を確認することができます。エラーが発生した場合も、どのリソースの作成でエラーになったのかが明白なため原因を追究しやすくて便利です。

image