ARMTemplateデプロイ用のJsonをイジる

#はじめに
AzureResourceManagerのTemplateデプロイを初めて触りました。
jsonベースは初めてだったのと構成が複雑だったので少し手こずりました。

あるシステムでサーバー群Aとサーバー群Bを負荷に応じて増設することを想定し、Powershellを使用しTemplateベースで増やしていく形です。
#作成イメージ
####リソースの構成
#####リソースAx
サーバーA、及びそのサーバーのPIP、NIC、Discを1台につき１リソースグループで増設していきます
#####リソースB
サーバーB、及びそのサーバーのPIP、NIC、Disc
こちらはサーバーを増設しても同じリソースグループ内に増設していきます。
#####リソースC
サーバーA、サーバーBのNSG、リソースBのサーバーはイメージから作成するのでそのイメージ
、それぞれのサーバーはVnet上に配置するのでVnetとそれぞれの用途別にsubnetを作成します。
その他、redisキャッシュなどを配置します。
#####その他
RM版Vnetはもとから可動しているオンプレと接続されたClassicのVnetとPeeringします

#Json

``` TemplateA.json
{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "vmname": {
            "type": "string"
        },
        "vmsize": {
            "type": "string"
        },
        "adminusername": {
            "type": "string"
        },
        "adminpassword": {
            "type":"securestring"
        },
        "rgnameresource": {
            "type": "string"
        },
        "subscriptionid":{
            "type": "string"
        },
        "vnetname":{
            "type": "string"
        },
        "subnetname":{
            "type": "string"
        },
        "nsgname":{
            "type": "string"
        },
        "osdiskname":{
            "type": "string"
        },
        "nicname":{
            "type": "string"
        },
        "ipname":{
            "type": "string"
        }
    },
    "variables": {},
    "resources": [
        {
            "type": "Microsoft.Compute/virtualMachines",
            "name": "[parameters('vmname')]",
            "apiVersion": "2017-03-30",
            "location": "[resourceGroup().location]",
            "scale": null,
            "properties": {
                "hardwareProfile": {
                    "vmSize": "[parameters('vmsize')]"
                },
                "storageProfile": {
                    "imageReference": {
                        "publisher": "MicrosoftWindowsServer",
                        "offer": "WindowsServer",
                        "sku": "2012-R2-Datacenter",
                        "version": "latest"
                    },
                    "osDisk": {
                        "name": "[parameters('osdiskname')]",
                        "createOption": "FromImage",
                        "caching": "ReadWrite",
                        "diskSizeGB": 128
                    }
                },
                "osProfile": {
                    "computerName": "[parameters('vmname')]",
                    "adminUsername": "[parameters('adminusername')]",
                    "adminPassword": "[parameters('adminpassword')]",
                    "windowsConfiguration": {
                        "provisionVMAgent": true,
                        "enableAutomaticUpdates": true
                    }
                },
                "networkProfile": {
                    "networkInterfaces": [
                        {
                            "id": "[resourceId('Microsoft.Network/networkInterfaces', parameters('nicname'))]"
                        }
                    ]
                }
            },
            "dependsOn": [
                "[resourceId('Microsoft.Network/networkInterfaces', parameters('nicname'))]"
            ]
        },
        {
            "name": "[parameters('nicname')]",
            "type": "Microsoft.Network/networkInterfaces",
            "apiVersion": "2018-01-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "ipConfigurations": [
                    {
                        "name": "ipconfig1",
                        "properties": {
                            "privateIPAllocationMethod": "Dynamic",
                            "publicIPAddress": {
                                "id": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('ipname'))]"
                            },
                            "subnet": {
                                "id": "[concat('/subscriptions/', parameters('subscriptionid'), '/resourceGroups/', parameters('rgnameresource'), '/providers/Microsoft.Network/virtualNetworks/', parameters('vnetname'),'/subnets/',parameters('subnetname'))]"
                            }
                        }
                    }
                ],
                "networkSecurityGroup": {
                    "id": "[concat('/subscriptions/', parameters('subscriptionid'), '/resourceGroups/', parameters('rgnameresource'), '/providers/Microsoft.Network/networkSecurityGroups/', parameters('nsgname'))]"
                },
                "virtualMachine": {
                    "id": "[resourceId('Microsoft.Compute/virtualMachines', parameters('vmname'))]"
                }
            },
            "dependsOn": [
                "[resourceId('Microsoft.Network/publicIPAddresses', parameters('ipname'))]"
            ]
        },
        {
            "type": "Microsoft.Network/publicIPAddresses",
            "name": "[parameters('ipname')]",
            "apiVersion": "2017-10-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "publicIPAllocationMethod": "Static"
            }
        }
    ]
}
```

``` TemplateB.json
{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "vmname": {
            "type": "string"
        },
        "vmsize": {
            "type": "string"
        },
        "vmimagename": {
            "type": "string"
        },
        "osdiskname": {
            "type": "string"
        },
        "adminusername":{
            "type": "string"
        },
        "adminpassword":{
            "type": "securestring"
        },
        "nicname": {
            "type": "string"
        },
        "ipname": {
            "type": "string"
        },
        "subscriptionid":{
            "type": "string"
        },
        "rgnameresource": {
            "type": "string"
        },
        "vnetname": {
            "type": "string"
        },
        "subnetname": {
            "type": "string"
        },
        "nsgname": {
            "type": "string"
        }
    },
    "variables": {},
    "resources": [
        {
            "type": "Microsoft.Compute/virtualMachines",
            "name": "[parameters('vmname')]",
            "apiVersion": "2017-03-30",
            "location": "[resourceGroup().location]",
            "properties": {
                "hardwareProfile": {
                    "vmSize": "[parameters('vmsize')]"
                },
                "storageProfile": {
                    "imageReference": {
                        "id": "[resourceId('Microsoft.Compute/images', parameters('vmimagename'))]"
                    },
                    "osDisk": {
                        "name": "[parameters('osdiskname')]",
                        "createOption":"FromImage"
                    }
                },
                "osProfile": {
                    "computerName": "[parameters('vmname')]",
                    "adminUsername": "[parameters('adminusername')]",
                    "adminPassword": "[parameters('adminpassword')]",
                    "windowsConfiguration":{
                        "provisionVMAgent":true
                    }
                },
                "networkProfile": {
                    "networkInterfaces": [
                        {
                            "id": "[resourceId('Microsoft.Network/networkInterfaces', parameters('nicname'))]"
                        }
                    ]
                }
            },
            "dependsOn": [
                "[resourceId('Microsoft.Network/networkInterfaces', parameters('nicname'))]"
            ]
        },
        {
            "name": "[parameters('nicname')]",
            "type": "Microsoft.Network/networkInterfaces",
            "apiVersion": "2018-01-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "ipConfigurations": [
                    {
                        "name": "ipconfig1",
                        "properties": {
                            "privateIPAllocationMethod": "Dynamic",
                            "publicIPAddress": {
                                "id": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('ipname'))]"
                            },
                            "subnet": {
                                "id": "[concat('/subscriptions/', parameters('subscriptionid'), '/resourceGroups/', parameters('rgnameresource'), '/providers/Microsoft.Network/virtualNetworks/', parameters('vnetname'),'/subnets/',parameters('subnetname'))]"
                            }
                        }
                    }
                ],
                "networkSecurityGroup": {
                    "id": "[concat('/subscriptions/', parameters('subscriptionid'), '/resourceGroups/', parameters('rgnameresource'), '/providers/Microsoft.Network/networkSecurityGroups/', parameters('nsgname'))]"
                },
                "virtualMachine": {
                    "id": "[resourceId('Microsoft.Compute/virtualMachines', parameters('vmname'))]"
                }
            },
            "dependsOn": [
                "[resourceId('Microsoft.Network/publicIPAddresses', parameters('ipname'))]"
            ]
        },
        {
            "type": "Microsoft.Network/publicIPAddresses",
            "name": "[parameters('ipname')]",
            "apiVersion": "2018-01-01",
            "sku": {
                "name": "Basic"
            },
            "location": "[resourceGroup().location]",
            "properties": {
                "publicIPAllocationMethod": "Dynamic",
                "dnsSettings": {
                    "domainNameLabel": "[parameters('vmname')]",
                    "fqdn": "[concat(parameters('vmname'), '.', resourceGroup().location, '.cloudapp.azure.com')]"
                }
            }
        }
    ]
}
```

``` templateC.json
{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "vnetname": {
            "type": "string"
        },
        "addrprefix": {
            "type": "string"
        },
        "peeringname": {
            "type": "string"
        },
        "subscriptionid":{
            "type": "string"
        },
        "classicvnetname":{
            "type": "string"
        },
        "wssubnetname": {
            "type": "string"
        },
        "wssubnetprefix": {
            "type": "string"
        },
        "xmsubnetname": {
            "type": "string"
        },
        "xmsubnetprefix": {
            "type": "string"
        },
        "wsnsgname":{
            "type": "string"
        },
        "srcaddrprefixssl":{
            "type": "array"
        },
        "redisname": {
            "type": "string"
        },
        "skuname":{
            "type": "string"
        },
        "skufamily":{
            "type": "string"
        },
        "skucapacity":{
            "type": "int"
        },
        "xmnsgname": {
            "type": "string"
        }
    },
    "variables": {},
    "resources": [
        {
            "type": "Microsoft.Network/virtualNetworks",
            "name": "[parameters('vnetname')]",
            "apiVersion": "2017-06-01",
            "location": "[resourceGroup().location]",
            "scale": null,
            "properties": {
                "addressSpace": {
                    "addressPrefixes": [
                        "[parameters('addrprefix')]"
                    ]
                },
                "virtualNetworkPeerings":[
                    {
                        "name": "[parameters('peeringname')]",
                        "properties":{
                            "allowForwardedTraffic":false,
                            "allowGatewayTransit":false,
                            "allowVirtualNetworkAccess":true,
                            "remoteVirtualNetwork":{
                                "id": "[concat('/subscriptions/', parameters('subscriptionid'), '/resourceGroups/Default-Networking/providers/Microsoft.ClassicNetwork/virtualNetworks/', parameters('classicvnetname'))]"
                            },
                            "useRemoteGateways":false
                        }
                    }
                ],
                "subnets":[
                    {
                        "name": "[parameters('wssubnetname')]",
                        "properties":{
                            "addressPrefix": "[parameters('wssubnetprefix')]"
                        }
                    },
                    {
                        "name": "[parameters('xmsubnetname')]",
                        "properties": {
                            "addressPrefix": "[parameters('xmsubnetprefix')]"
                          }
                    }
                ]
            }
        },
        {
            "type": "Microsoft.Cache/Redis",
            "name": "[parameters('redisname')]",
            "apiVersion": "2016-04-01",
            "location": "[resourceGroup().location]",
            "tags": {},
            "scale": null,
            "properties": {
                "redisVersion": "3.2.7",
                "sku": {
                    "name": "[parameters('skuname')]",
                    "family": "[parameters('skufamily')]",
                    "capacity": "[parameters('skucapacity')]"
                },
                "enableNonSslPort": true,
                "redisConfiguration": {
                    "maxclients": "256",
                    "maxmemory-reserved": "2",
                    "maxfragmentationmemory-reserved": "12",
                    "maxmemory-delta": "2"
                }
            },
            "dependsOn": []
        },
        {
            "type": "Microsoft.Network/networkSecurityGroups",
            "name": "[parameters('wsnsgname')]",
            "apiVersion": "2017-10-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "securityRules": [
                    {
                        "name": "default-allow-rdp",
                        "properties": {
                            "provisioningState": "Succeeded",
                            "protocol": "Tcp",
                            "sourcePortRange": "*",
                            "destinationPortRange": "3389",
                            "sourceAddressPrefix": "VirtualNetwork",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 1000,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "HTTPS",
                        "properties": {
                            "protocol": "Tcp",
                            "sourcePortRange": "*",
                            "destinationPortRange": "443",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 1010,
                            "direction": "Inbound",
                            "sourceAddressPrefixes":
                                "[parameters('srcaddrprefixssl')]"     
                        }
                    }
                ],
                "defaultSecurityRules": [
                    {
                        "name": "AllowVnetInBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "VirtualNetwork",
                            "destinationAddressPrefix": "VirtualNetwork",
                            "access": "Allow",
                            "priority": 65000,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "AllowAzureLoadBalancerInBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "AzureLoadBalancer",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 65001,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "DenyAllInBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Deny",
                            "priority": 65500,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "AllowVnetOutBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "VirtualNetwork",
                            "destinationAddressPrefix": "VirtualNetwork",
                            "access": "Allow",
                            "priority": 65000,
                            "direction": "Outbound"
                        }
                    },
                    {
                        "name": "AllowInternetOutBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "Internet",
                            "access": "Allow",
                            "priority": 65001,
                            "direction": "Outbound"
                        }
                    },
                    {
                        "name": "DenyAllOutBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Deny",
                            "priority": 65500,
                            "direction": "Outbound"
                        }
                    }
                ]
            }
        },
        {
            "type": "Microsoft.Network/networkSecurityGroups",
            "name": "[parameters('xmnsgname')]",
            "apiVersion": "2017-10-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "securityRules": [
                    {
                        "name": "default-allow-rdp",
                        "properties": {
                            "protocol": "Tcp",
                            "sourcePortRange": "*",
                            "destinationPortRange": "3389",
                            "sourceAddressPrefix": "Internet",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 1000,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "HTTPS",
                        "properties": {
                            "protocol": "Tcp",
                            "sourcePortRange": "*",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 1010,
                            "direction": "Inbound",
                            "destinationPortRanges": [
                                "80",
                                "443"
                            ]
                        }
                    }
                ],
                "defaultSecurityRules": [
                    {
                        "name": "AllowVnetInBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "VirtualNetwork",
                            "destinationAddressPrefix": "VirtualNetwork",
                            "access": "Allow",
                            "priority": 65000,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "AllowAzureLoadBalancerInBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "AzureLoadBalancer",
                            "destinationAddressPrefix": "*",
                            "access": "Allow",
                            "priority": 65001,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "DenyAllInBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Deny",
                            "priority": 65500,
                            "direction": "Inbound"
                        }
                    },
                    {
                        "name": "AllowVnetOutBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "VirtualNetwork",
                            "destinationAddressPrefix": "VirtualNetwork",
                            "access": "Allow",
                            "priority": 65000,
                            "direction": "Outbound"
                        }
                    },
                    {
                        "name": "AllowInternetOutBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "Internet",
                            "access": "Allow",
                            "priority": 65001,
                            "direction": "Outbound"
                        }
                    },
                    {
                        "name": "DenyAllOutBound",
                        "properties": {
                            "protocol": "*",
                            "sourcePortRange": "*",
                            "destinationPortRange": "*",
                            "sourceAddressPrefix": "*",
                            "destinationAddressPrefix": "*",
                            "access": "Deny",
                            "priority": 65500,
                            "direction": "Outbound"
                        }
                    }
                ]
            }
        }
    ]
}
```

これらのJsonをPowershellコマンドの```New-AzureRmResourceGroupDeployment```でデプロイしていきます。
その際にPSないで必要なパラメーターをObjectで渡してあげます。
サーバーが複数の場合はPS内でループします。


#終わり
基本的にはじめてやったので、まずはポータルで作成し、それをエクスポートして雛形をつくったのですが、名前も全入れ替えだし、設定しなくてはいけない項目といらない項目の判別がとても複雑でした。Jsonにそもそもなれていなくて苦労したこともありました。

実際の内容については、Peeringの設定が全然うまくいきませんでした。また、あとからsubnetを追加したのですが、はじめはリソースCでサーバーごとに2json作る想定でしたが、増分更新のはずが、subnetだけなぜか完全更新になっていたので泣く泣く1jsonにまとめることにしました。

いろいろ苦労はしましたが、慣れるとPSとちがいコード量も少なくなし管理も楽そうなのでメリットは多そうだと思います。