Azureでポータルを使わずデプロイしてみよう ~ 初めてのAzure Resource Template

Azureで様々なリソースを操作するとき、一番一般的な方法はポータルから操作することだと思います。
一方で、この方法には大きな弱点もあります。それは、手作業でやらざるを得ないという点です。 一連の動作を一気にやってしまうとか、同じことを繰り返すといった場合にはもっと機械的な方法を使う必要があります。

今回はAzure Resource Managerを使い、手作業による仮想マシンの準備を自動化してみたいと思います。 とはいっても、1から作るのは大変なのでサンプルを実行し、サンプルを紐解くことで全体像を把握するというアプローチをとってみます。

サンプルを使ってデプロイしてみよう

何はともあれ公式ドキュメントを見てみよう。まず、この関連のドキュメントとして読むべきものはこちらです。

Azure テンプレートを使用して安全な Linux VM を作成する

こちらを参考に進めてみようと思います。なお、始めるにあたり準備しておくことがあります。

  • Azure CLIのセットアップを済ませ、azure loginコマンドを実行しログインをしておきましょう
    またazure config mode armコマンドも実行しておいてください。

  • SSHのキーを作成しておきましょう
    Azure 上の Linux または Mac における SSH の使用方法を参照のこと。 具体的にはssh-keygen -t rsa -b 2048と実行して、画面に従い出力します
    そのまま作業すれば、通常は~/.ssh/id_rsa.pubに出力されます

  • Ubuntuの場合はcat ~/.ssh/id_rsa.pub | xsel --clipboard --inputでキーをクリップボードにコピーできます。(xselがセットアップされてない時はインストール)

では、やってみましょう。

$ azure group create -n quicksecuretemplate -l eastus --template-uri https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-vm-sshkey/azuredeploy.json

実行するとsshKeyData:で止まります。先ほど準備しておいた、sshキーをクリップボードへコピーするコマンドを別の端末で実施し、貼り付けます。 あとは暫く待つと終わります。こんな感じです。

何が出来上がったかをポータルで確認してみましょう。 ・・・もし意地でもポータルを開かんぞ!という方はazure group show quicksecuretemplateと実行してみてください。同じ内容を端末で見ることができます。

このように、一通り必要なものが出来上がっています。それでは接続してみます。リソースグループにあるsshPublicIPを開くと、DNS名という欄があります。

こちらをコピーしておきます。

SSHコマンドで接続します。この時、ユーザー名はazureuserになるのでご注意を。

$ ssh -i ~/.ssh/id_pub azureuser@DNS名

実際にやってみると、こんな感じです。

はい、接続できました。 ポータルで操作することなく仮想マシンを1台作成し、利用することができましたね。

ここまでの流れを振り返ると

  • Azure CLIからコマンドを実行
  • Azure上にサーバが作成された
  • 接続して利用することができた

というものです。

それでは、ここまでの流れを詳細に見ていきましょう。

Azure Resource Template

まず、最初に実行したコマンドを見ていきます。

$ azure group create  -n quicksecuretemplate -l eastus --template-uri https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-vm-sshkey/azuredeploy.json

azure group createリソースグループ を作成するコマンドです。-nでグループの名前、-lがロケーション、そして--template-uriがテンプレートを取得する先になります。 従って、リソースグループ内に置かれるものは、URIの先を見る必要があります。では、見てみましょう。

ブラウザで表示するとこんな感じです。

以下は、この表示を見ながら読み進めてください。

ここで、TemplateのJSONにおける基本構造をおさえておきましょう。

{
  "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json",
  "contentVersion": "1.0.0.0",
  "parameters": {
  },
  "variables": {
  },
  "resources": [
    {
    }
  ],
    "outputs": {
    } 
  }
}

これが一番何も書かれていない状態のResouce Templateです。

  • parameters
  • variables
  • resources
  • outputs

の4つで構成されております。

プログラムの経験がある人には説明が簡単なのですが、parametersは変数でvariablesは定数という感じです。そして、resources にAzureでのコンピューターリソース群を定義します。

parameters

まず、parametersの一部を見てみましょう。

  "parameters": {
    "adminUserName": {
      "type": "string",
      "defaultValue": "azureuser",
      "metadata": {
        "description": "User name for the Virtual Machine."
      }
    },
    "sshKeyData": {
      "type": "string",
      "metadata": {
        "description": "SSH rsa public key file as a string."
      }
    },

adminUserNameというのが設定されており、typeがstringになっています。そして、defaultValueがazureuserとなっています。 次が、sshKeyDataです。こちらはdefaultValueが設定されていません。

デプロイの時に入力が要求された時にsshKeyData:となっていました。つまり、defaultValueが設定されていない場合は、 デプロイ時に入力が求められることになります。また、SSHで接続した時にユーザー名はazureuserとしました。これは、ここでdefaultとして設定されているためです。

他の部分を見ていくと、vmSizeはStandard_A2になっており、Ubuntuのヴァージョンは14.04.4-LTSとなっています。

ここで、一足先にresourcesの一部を見てみましょう。

    {
      "apiVersion": "[variables('apiVersion')]",
      "type": "Microsoft.Compute/virtualMachines",
      "name": "[parameters('vmName')]",
      "location": "[variables('location')]",
      "dependsOn": [
        "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'))]",
        "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
      ],
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('vmSize')]"
        },
        "osProfile": {
          "computerName": "[parameters('vmName')]",
          "adminUsername": "[parameters('adminUserName')]",

上記の部分を見てみると、随所にparametersというのがあります。そして、ここまで紹介したものと同じ名前があることに気がつくかと思います。

このように、parametersで設定したものは他の場所で設定された内容を呼び出して利用することができます。 defaultValueを設定しなければ、デプロイされるタイミングで質問が行われ、その都度入力をすることができます。

variables

次にvariablesを見てみます。ここでは幾つかの特徴的なものを取り上げます

"nicName": "sshNIC",

まずひとつ目がnicNameです。対応する値としてsshNICとなっています。 ちょっと飛びますが、resourcesの一部もみてみます。

    {
      "apiVersion": "[variables('apiVersion')]",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[variables('nicName')]",
      "location": "[variables('location')]",

まず、nameというところにvariables('nicName') と書かれています。つまり、variablesのnicNameという意味ですから、先ほどのsshNICが ここで呼びだされていることになります。なお、typeを見るとnetworkInterfacesとなっています。では、ポータルで見てみると

確かに、作成されたリソースにネットワークカードがあり、名前はsshNICになっています。 variablesは設定した値が変更されることなく、そのまま使われているのが特徴です。

"location": "[resourceGroup().location]",

次にlocationを見てみます。こちらはresourceGroup().locationとなっており、値を取得して設定しているようです。

デプロイの実行をした時のコマンドにて-lというのがあり、そこでデプロイ先を決めていました。つまり、テンプレートを作る時点ではロケーションは 特定することをしておらず、このように実行後に決まった値を取得して利用するように設定されています。

"uniqueDnsLabelPrefix": "[concat(parameters('dnsLabelPrefix'),uniquestring(resourceGroup().id))]",

最後にuniqueDnsLabelPrefixです。ここではconcatuniquestringが特徴的です。 これらはテンプレートの中で使える関数です。concatは文字列の結合になります。uniquestringは種を受け取って一意の文字列を生成してくれます。 ということで、以上を組み合わせるとuniqueDnsLabelFrefixはパラメータのdnsLablePrefixresourceGroupのIDを元にした文字列が繋がって 作られているということになります。dnsLabelPrefixを探してみると、

    "dnsLabelPrefix": {
      "type": "string",
      "defaultValue": "sshlinux",

となっています。

ではポータルで確認してみましょう。

取得されたグローバルIPアドレスのDNS欄を見ると

sshlinuxk5idvz7wljfy6.eastus.cloudapp.azure.com

となっています。(もちろん、読者が実施した時は違うFQDNになっているはず)

先頭はsshlinuxとなっており、その後ランダムな感じの文字列が並んでいます。その後にロケーション、そしてお決まりのcloudappという流れです。

このように、テンプレート内では関数を使うこともできます。

resources

最後にresourcesを見てみましょう。

ここまでで一部紹介したとおり、parametersやvariablesで設定されている値を呼び出すこともあります。そもそもここでは、 デプロイされるリソースの詳細を定義する部分です。

では、またソースから見てみましょう。一部を抜粋しました。

  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[variables('storageAccountName')]",

    ...

    {
      "apiVersion": "[variables('apiVersion')]",
      "type": "Microsoft.Network/networkSecurityGroups",
      "name": "[variables('networkSecurityGroupName')]",

    ...

    {
      "apiVersion": "[variables('apiVersion')]",
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "[variables('publicIPAddressName')]",

    ...

    {
      "apiVersion": "[variables('apiVersion')]",
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[variables('virtualNetworkName')]",

    ...

    {
      "apiVersion": "[variables('apiVersion')]",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[variables('nicName')]",

    ...

    {
      "apiVersion": "[variables('apiVersion')]",
      "type": "Microsoft.Compute/virtualMachines",
      "name": "[parameters('vmName')]",        

同じ高さで似た部分だけを見てみると、どうやらこのテンプレートでは

  • Microsoft.Storage/storageAccounts
  • Microsoft.Network/networkSecurityGroups
  • Microsoft.Network/publicIPAddresses
  • Microsoft.Network/virtualNetworks
  • Microsoft.Network/networkInterfaces
  • Microsoft.Compute/virtualMachines

と6つのリソースが設定されています。

ポータルで見てみると

確かに6つできあがってます。このようにresourcesではデプロイされる対象を定義することができます。

Azureでデプロイされるリソースには関係性を持つものがあります。ここで、今回使われたテンプレートを可視化してくれるツールを見てみましょう。以下のボタンを押してみてください。


6つのリソースとそれぞれの関係性が表示されたと思います。このツールはJSONを読み込んで可視化してくれるサービスです。 さらに、それぞれのリソースをダブルクリックすると定義を見ることもできます。

Azureの各リソースの関係性については、テンプレートをこの可視化ツールに読み込ませて色々と確かめてみるのが一番勉強になります。

まとめ

いかがでしたでしょうか?

今回はコマンドからマシンを作る一番ベーシックな方法を使いデプロイを行いました。そして、その流れを見ていきました。Azureに置いて非常に重要となる部分の概要を解説しましたので、是非しっかりと確認してみてください。

次回は、今回のテンプレートをカスタマイズ、そして今回とはまた違う方法でデプロイをしてみたいと思います。

参考リンク

Azure リソース マネージャーの概要

Azure リソース マネージャーのテンプレートの関数

Azure Resource Manager Template Visualizer

Azure / azure-quickstart-templates / 101-vm-sshkey