ARM Template の書き方 その2 Prameters,Variables

  • VNet
  • AzureResourceManager
  • 前回「ARM Template の書き方 その1 基本構文」ということで、Templete ファイルの構造や基本的な書き方、構文の説明を行いました。今回は、実際に VirtualNetwork, PublicIP を作って "parameters" と "variables" がどのようなものか確認したいと思います。

    用意するもの

    以下のものを用意します。

    • PowerShell(インストール手順
    • Azure AD Account
    • テンプレートファイル(network.json)
    • パラメータファイル(arm.parameters.json)

    PowerShell をインストールして、Azure AD Account を用意するところまでの説明は省きます。テンプレートファイルとパラメータファイルについて、以下に解説します。

    テンプレートファイル(network.json)

    ポイントは "parameters" と "variables" の使用方法です。

    "parameters" で「データ型(type)」と「デフォルト値(defaultValue)」は定義していますが、「値(value)」は定義していません。これは、パラメータファイル(arm.parameters.json)に書き出しているためです。

    テンプレートファイルで "parameters" を定義するとき、「データ型(type)」の指定は必須です。しかし、中身の「値(value)」は必須ではありません。外部ファイルで定義することが可能となっているためです。その一方、テンプレートファイルで "parameters" を定義しなかった場合、外部ファイルでパラメータを定義することはできません。

    この辺りに仕様は実際に自分で書いてみないと実感できないところでした。

    "variables" の使用方法は、オブジェクト型のデータを定義したり、関数を使った値を記述するときに使用します。詳しくはパラメータ変数の概要を参照ください。

    {
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "location": {
          "type": "string",
          "defaultValue": "[resourceGroup().location]",
          "metadata": {
            "description": "Location for all resources."
          }
        },
        "PublicDNSLabel" : {
          "type": "string",
          "metadata": {
            "description": "Define Public DNS Name"
          }
        }
      },
      "variables": {
        "tags": "[resourceGroup().tags]",
        "virtualNetwork01": {
          "Name": "vnet01",
          "Prefix": "10.1.0.0/16"
        },
        "subnet01": {
          "Name": "subnet01",
          "Prefix": "10.1.1.0/24"
        },
        "subnet02": {
          "Name": "subnet02",
          "Prefix": "10.1.2.0/24"
        },
        "PublicIP": {
          "Name": "public01"
        }
      },
      "resources": [
        {
          "type": "Microsoft.Network/virtualNetworks",
          "name": "[variables('virtualNetwork01').Name]",
          "apiVersion": "2020-05-01",
          "location": "[parameters('location')]",
          "comments": "This will build a Virtual Network.",
          "tags": "[variables('tags')]",
          "properties": {
            "addressSpace": {
              "addressPrefixes": [
                "[variables('virtualNetwork01').Prefix]"
              ]
            },
            "subnets": [
              {
                "name": "[variables('subnet01').Name]",
                "properties": {
                  "addressPrefix": "[variables('subnet01').Prefix]",
                  "privateEndpointNetworkPolicies": "Enabled",
                  "privateLinkServiceNetworkPolicies": "Enabled"
                }
              },
              {
                "name": "[variables('subnet02').Name]",
                "properties": {
                  "addressPrefix": "[variables('subnet02').Prefix]",
                  "privateEndpointNetworkPolicies": "Enabled",
                  "privateLinkServiceNetworkPolicies": "Enabled"
                }
              }
            ]
          }
        },
        {
          "name": "[variables('PublicIP').Name]",
          "type": "Microsoft.Network/publicIPAddresses",
          "apiVersion": "2020-05-01",
          "location": "[parameters('location')]",
          "comments": "Public IP for your Primary NIC",
          "properties": {
            "dnsSettings": {
              "domainNameLabel": "[parameters('PublicDNSLabel')]"
            },
            "publicIPAllocationMethod": "Dynamic"
          },
          "tags": "[variables('tags')]"
        }
      ]
    }

    パラメータファイル(arm.parameters.json)

    こちらのファイルは短い内容となっています。location はリソースグループの値を継承させたいのでそのままです。PublicIP 用の PublicDNSLabel だけ値を定義します。

    {
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
          "PublicDNSLabel": {
              "value": "azwin2019"
          }
      }
    }

    ファイルの準備はこれで完了です。

    試してみる

    デプロイコマンド

    以下の PowerShell コマンドを使って VirtualNetwork をデプロイします。

    1. Connect-AzAccount
    2. New-AzResourceGroup
    3. New-AzResourceGroupDeployment -WhatIf
    4. New-AzResourceGroupDeployment

    3番目の "-WhatIf" とは、デプロイ前のテスト実行を意味しています。このオプションをつけて実行することで、どのような結果が得られるのかを先に知ることができます。その内容から、デプロイが問題ないか判断した上で実行するようにします。

    ただ、これらのコマンドについて毎回手打ちするのは面倒です。そこで、簡単なスクリプト(deployment.ps1)を用意して一連の処理を実行するようにしました。また、処理結果はログファイルに出力するようにしています。これで、デプロイ履歴も自然にログファイルに蓄積されていきます。

    Connect-AzAccount

    まずは、ログインします。

    PS /Users/atsushi/github/azure_arm_v1> Connect-AzAccount Account SubscriptionName TenantId Environment ------- ---------------- -------- ----------- atsushi.koizumi@gmail.com SampleSubName01 000000000-0000-0000-00000000 AzureCloud

    deployment.ps1

    スクリプトの内容は以下です。

    # version 1.0.0
    
    <#
    .SYNOPSIS
    ARM Template を Deploy するにあたって、本スクリプトを実行します。
    
    .DESCRIPTION
    以下の順で処理が実行されます。
      1. リソースグループの作成
      2. $TemplateListに記述したテンプレートに対して順次実施(スキップ可)
        2-1. テンプレートのテスト
        2-2. テンプレートのデプロイ
      3. デプロイ結果をログに保存
    
    .PARAMETER
    デプロイ対象となるのは $TemplateList に記述したテンプレートのみです。
    パラメータファイルは $PrametersFile で固定です。
    #>
    
    # Environments
    $ResouceGroupName = "atsushi.koizumi.arm"
    $location         = "eastus"
    $Owner_tag        = "atsushi.koizumi"
    $Env_tag          = "arm.templete"
    $TemplateList     = ("network","virtualmachine")  # 配列
    $PrametersFile    = "arm.parameters.json"
    $Logfile          = "mydeployments.log"
    
    # error handling
    $ErrorActionPreference = "Stop"
    
    
    ################
    # Script Start #
    ################
    
    
    # create resource group
    try {
        $rgstate = Get-AzResourceGroup -Name $ResouceGroupName
        if ($rgstate.ProvisioningState -eq "Succeeded") {
            Write-Output "Resource Group Exists. Start ARM Templete Deploy."
        } else {
            Write-Output "Resource Group Exists. But State is not Succeeded."
        }
    }
    catch {
        New-AzResourceGroup `
            -Name $ResouceGroupName `
            -Location $location `
            -Tag @{Owner=$Owner_tag; Env=$Env_tag} `
            | Out-File -Append $Logfile
    }
    
    # get datetime
    $Datetime = Get-date -format "yyyyMMddHHmmss"
    
    # deploy
    foreach ($item in $TemplateList) {
        
        $CurrentFiles = Get-ChildItem $PSScriptRoot -Name
        # filecheck
        if($CurrentFiles -ccontains "$item.json") {
    
            # gain permission to test
            Write-Host "Test the templete ""$item.json"" ?"
            $YesNo = Read-Host "yes or no "
            while (($YesNo -ne "yes") -And ($YesNo -ne "no")) {
                $YesNo = Read-Host "yes or no "
            }
            Write-Host ""
    
            # test templete
            if ($YesNo -eq "yes") {
                New-AzResourceGroupDeployment `
                    -Name "$item-$Datetime" `
                    -ResourceGroupName $ResouceGroupName `
                    -WhatIf `
                    -TemplateFile "$item.json" `
                    -TemplateParameterFile $PrametersFile
            } elseif ($YesNo -eq "no") {
                Write-Host "Skip ""$item.json"""
                Continue
            }
    
            # gain permission to deploy
            Write-Host "Deploy the templete ""$item.json"" ?"
            $YesNo = Read-Host "yes or no "
            while (($YesNo -ne "yes") -And ($YesNo -ne "no")) {
                $YesNo = Read-Host "yes or no "
            }
            Write-Host ""
    
            # deeploy start
            if ($YesNo -eq "yes") {
                New-AzResourceGroupDeployment `
                    -Name "$item-$Datetime" `
                    -ResourceGroupName $ResouceGroupName `
                    -Mode Incremental `
                    -TemplateFile "$item.json" `
                    -TemplateParameterFile $PrametersFile `
                | Out-File -Append $Logfile
            } elseif ($YesNo -eq "no") {
                Write-Host "Skip ""$item.json"""
            }
            Write-Host ""
    
        } else {
            Write-Host "[Warning] ""$PSScriptRoot\$item"" does not exist."
        }
    }

    スクリプト実行

    では、スクリプトを実行してみます。

    PS /Users/atsushi/github/azure_arm_v1> ./deployment.ps1 Test the templete "network.json" ? yes or no : yes Note: The result may contain false positive predictions (noise). You can help us improve the accuracy of the result by opening an issue here: https://aka.ms/WhatIfIssues. Resource and property changes are indicated with this symbol: + Create The deployment will update the following scope: Scope: /subscriptions/000000000-0000-0000-00000000/resourceGroups/atsushi.koizumi.arm + Microsoft.Network/publicIPAddresses/public01 [2020-05-01] apiVersion: "2020-05-01" id: "/subscriptions/000000000-0000-0000-00000000/resourceGroups/atsushi.koizumi.arm/providers/Microsoft.Network/publicIPAddresses/public01" location: "eastus" name: "public01" properties.dnsSettings.domainNameLabel: "azwin2019" properties.publicIPAllocationMethod: "Dynamic" tags.Env: "arm.templete" tags.Owner: "atsushi.koizumi" type: "Microsoft.Network/publicIPAddresses" + Microsoft.Network/virtualNetworks/vnet01 [2020-05-01] apiVersion: "2020-05-01" id: "/subscriptions/000000000-0000-0000-00000000/resourceGroups/atsushi.koizumi.arm/providers/Microsoft.Network/virtualNetworks/vnet01" location: "eastus" name: "vnet01" properties.addressSpace.addressPrefixes: [ 0: "10.1.0.0/16" ] properties.subnets: [ 0: name: "subnet01" properties.addressPrefix: "10.1.1.0/24" properties.privateEndpointNetworkPolicies: "Enabled" properties.privateLinkServiceNetworkPolicies: "Enabled" 1: name: "subnet02" properties.addressPrefix: "10.1.2.0/24" properties.privateEndpointNetworkPolicies: "Enabled" properties.privateLinkServiceNetworkPolicies: "Enabled" ] tags.Env: "arm.templete" tags.Owner: "atsushi.koizumi" type: "Microsoft.Network/virtualNetworks" Resource changes: 2 to create. Deploy the templete "network.json" ? yes or no : yes [Warning] "/Users/atsushi/github/azure_arm_v1\virtualmachine" does not exist. PS /Users/atsushi/github/azure_arm_v1>

    処理結果

    ログファイルの中身を参照してみます。

    ResourceGroupName : atsushi.koizumi.arm
    Location          : eastus
    ProvisioningState : Succeeded
    Tags              : 
                        Name   Value          
                        =====  ===============
                        Env    arm.templete   
                        Owner  atsushi.koizumi
                        
    ResourceId        : /subscriptions/000000000-0000-0000-00000000/resourceGroups/atsushi.koizumi.arm
    
    
    
    DeploymentName          : network-20210115214249
    ResourceGroupName       : atsushi.koizumi.arm
    ProvisioningState       : Succeeded
    Timestamp               : 1/15/2021 12:43:38 PM
    Mode                    : Incremental
    TemplateLink            : 
    Parameters              : 
                              Name              Type                       Value     
                              ================  =========================  ==========
                              location          String                     eastus    
                              publicDNSLabel    String                     azwin2019 
                              
    Outputs                 : 
    DeploymentDebugLogLevel : 

    うまく作成できました。

    最後に

    ARM Templete の基本操作はこれで把握できたと思います。あとは、各リソース毎の記述方法を参照しつつ自作テンプレートを書けるようになっていきたいと思います。

  • VNet
  • AzureResourceManager