嵌套模板,使用AzureRM在同一vnet中部署不同的子网

时间:2017-08-04 22:55:09

标签: json azure azure-resource-manager azure-virtual-network azure-template

我正在尝试通过模板实现一定程度的容器化。最后,我希望能够在一个模板中定义驻留在虚拟网络和子网(如数据库集群)内的组件(一个或多个服务器)。通过另一个模板,定义一个驻留在虚拟网络和子网内的组件,但可能是另一个组件。

模板A:

  • MY-VNET
    • MY-subnet1
      • 我的接口1

模板B:

  • MY-VNET
    • MY-subnet2
      • 我的接口2

这样,在模板A中嵌套模板B会留给我:

模板AB:

  • MY-VNET
    • MY-subnet1
      • 我的接口1
    • MY-subnet2
      • 我的接口2

相反,我收到以下错误:

New-AzureRmResourceGroupDeployment : 4:56:27 PM - Resource 
 Microsoft.Network/virtualNetworks 'overlayTest-vnet' failed with message '
{
  "error": {
    "code": "InUseSubnetCannotBeDeleted",
    "message": "Subnet overlayTest-subnet2 is in use by  /subscriptions/beep-boop/resourceGroups/d/providers/Microsoft.Network/networkInterfaces/overlayTest-vnet-interface2/ipConfigurations/ipconfig1 and cannot be deleted.",
    "details": []
  }
}

生成的资源组将如下填充(就像部署嵌套模板和嵌套退出后的资源一样)。

模板AB:

  • MY-VNET
    • MY-subnet2
      • 我的接口2

我的模板如下:

azuredeploy.json

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "solutionName": {
      "type": "string",
      "defaultValue": "testing"
    },
    "vmIP": {
      "type": "string",
      "defaultValue": "10.0.100.100"
    },
    "virtualNetworkName": {
      "type": "string",
      "defaultValue": "[concat(parameters('solutionName'), '-vnet')]"
    },
    "vnetAddressPrefix": {
      "type": "string",
      "defaultValue": "10.0.0.0/16"
    },
    "subnetName": {
      "type": "string",
      "defaultValue": "[concat(parameters('solutionName'),'-subnet1')]"
    },
    "subnetAddressPrefix": {
      "type": "string",
      "defaultValue": "10.0.100.0/24"
    },
    "subnetName2": {
      "type": "string",
      "defaultValue": "[concat(parameters('solutionName'),'-subnet2')]"
    },
    "subnetAddressPrefix2": {
      "type": "string",
      "defaultValue": "10.0.101.0/24"
    },
    "_artifactsLocation": {
      "type": "string"
    },
    "_artifactsLocationSasToken": {
      "type": "securestring"
    }
  },
  "variables": {
    "OverlaySubnetTemplateFolder": "nestedtemplates",
    "OverlaySubnetTemplateFileName": "OverlaySubnet.json",
    "OverlaySubnetTemplateParametersFileName": "OverlaySubnet.parameters.json",
    "vnetID": "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]",
    "subnetRef": "[concat(variables('vnetID'), '/subnets/', parameters('subnetName'))]"
  },
  "resources": [
    {
      "name": "OverlaySubnet",
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2016-09-01",
      "dependsOn": [],
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "[concat(parameters('_artifactsLocation'), '/', variables('OverlaySubnetTemplateFolder'), '/', variables('OverlaySubnetTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
          "contentVersion": "1.0.0.0"
        },
        "parameters": {
          "solutionName": {
            "value": "[parameters('solutionName')]"
          }
        }
      }
    },
    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[parameters('virtualNetworkName')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [],
      "properties": {
        "mode": "Incremental",
        "addressSpace": {
          "addressPrefixes": [
            "[parameters('vnetAddressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[parameters('subnetName')]",
            "properties": {
              "mode": "Incremental",
              "addressPrefix": "[parameters('subnetAddressPrefix')]"
            }
          }
        ],
        "virtualNetworkPeerings": []
      }
    },
    {
      "type": "Microsoft.Network/virtualNetworks/subnets",
      "name": "[concat(parameters('virtualNetworkName'), '/', parameters('subnetName'))]",
      "apiVersion": "2017-06-01",
      "properties": {
        "addressPrefix": "[parameters('subnetAddressPrefix')]",
        "privateAccessServices": []
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]"
      ]
    },
    {
      "type": "Microsoft.Network/virtualNetworks/subnets",
      "name": "[concat(parameters('virtualNetworkName'), '/', parameters('subnetName2'))]",
      "apiVersion": "2017-06-01",
      "properties": {
        "addressPrefix": "[parameters('subnetAddressPrefix2')]",
        "privateAccessServices": []
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]"
      ]
    },
    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[concat(parameters('virtualNetworkName'), '-interface1')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              /*
              "privateIPAllocationMethod": "Static",
              // reserved IP address range for /24 is 1-3, so start with [0 + 4] or more
              "privateIPAddress": "[parameters('vmIP')]",
              */
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[variables('subnetRef')]"
              }
            }
          }
        ]
      }
    }
  ],
  "outputs": {}
}

nestedtemplates / OverlaySubnet.json

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "solutionName": {
      "type": "string",
      "defaultValue": "testing"
    },
    "virtualNetworkName": {
      "type": "string",
      "defaultValue": "[concat(parameters('solutionName'), '-vnet')]"
    },
    "vnetAddressPrefix": {
      "type": "string",
      "defaultValue": "10.0.0.0/16"
    },
    "subnetName": {
      "type": "string",
      "defaultValue": "[concat(parameters('solutionName'),'-subnet2')]"
    },
    "subnetAddressPrefix": {
      "type": "string",
      "defaultValue": "10.0.101.0/24"
    }
  },
  "variables": {
    "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]",
    "subnetRef": "[concat(variables('vnetID'),'/subnets/', parameters('subnetName'))]"
  },
  "resources": [
    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[parameters('virtualNetworkName')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [],
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[parameters('vnetAddressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[parameters('subnetName')]",
            "properties": {
              "mode": "Incremental",
              "addressPrefix": "[parameters('subnetAddressPrefix')]"
            }
          }
        ],
        "virtualNetworkPeerings": []
      }
    },
    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[concat(parameters('virtualNetworkName'), '-interface2')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              /*
              "privateIPAllocationMethod": "Static",
              // reserved IP address range for /24 is 1-3, so start with [0 + 4] or more
              "privateIPAddress": "[parameters('vmIP')]",
              */
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[variables('subnetRef')]"
              }
            }
          }
        ]
      }
    }
  ],
  "outputs": {}
}

2 个答案:

答案 0 :(得分:1)

将嵌套模板中的VNet资源更改为子网资源,它将起作用。您要做的是创建一个新的vnet而不是现有的vnet,因此它会尝试更新现有的vnet以匹配您的定义(因此删除所有子网并添加在overlay中定义的1)。

但老实说,整个方法都是错误的,你应该使用属性复制循环并一次完成所有工作。

答案 1 :(得分:0)

最后,我实现了创建嵌套模板的目标,该模板在父模板的虚拟网络中定义了自己的子网,同时保持了在没有父模板的情况下部署嵌套模板的能力。关键是使用条件虚拟网络资源,并确保嵌套模板在嵌套时不会破坏父模板的虚拟网络。感谢@ 4c74356b41让我朝着正确的方向前进。

azuredeploy.json

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "solutionName": {
      "type": "string",
      "defaultValue": "testing"
    },
    "vmIP": {
      "type": "string",
      "defaultValue": "10.0.100.100"
    },
    "virtualNetworkName": {
      "type": "string",
      "defaultValue": "[concat(parameters('solutionName'), '-vnet')]"
    },
    "vnetAddressPrefix": {
      "type": "string",
      "defaultValue": "10.0.0.0/16"
    },
    "subnetName": {
      "type": "string",
      "defaultValue": "[concat(parameters('solutionName'),'-subnet1')]"
    },
    "subnetAddressPrefix": {
      "type": "string",
      "defaultValue": "10.0.100.0/24"
    },
    "subnetName2": {
      "type": "string",
      "defaultValue": "[concat(parameters('solutionName'),'-subnet2')]"
    },
    "subnetAddressPrefix2": {
      "type": "string",
      "defaultValue": "10.0.101.0/24"
    },
    "_artifactsLocation": {
      "type": "string"
    },
    "_artifactsLocationSasToken": {
      "type": "securestring"
    }
  },
  "variables": {
    "OverlaySubnetTemplateFolder": "nestedtemplates",
    "OverlaySubnetTemplateFileName": "OverlaySubnet.json",
    "OverlaySubnetTemplateParametersFileName": "OverlaySubnet.parameters.json",
    "vnetID": "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]",
    "subnetRef": "[concat(variables('vnetID'), '/subnets/', parameters('subnetName'))]"
  },
  "resources": [
    {
      "name": "OverlaySubnet",
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2016-09-01",
      "dependsOn": [],
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "[concat(parameters('_artifactsLocation'), '/', variables('OverlaySubnetTemplateFolder'), '/', variables('OverlaySubnetTemplateFileName'), parameters('_artifactsLocationSasToken'))]",
          "contentVersion": "1.0.0.0"
        },
        "parameters": {
          "solutionName": {
            "value": "[parameters('solutionName')]"
          },
          "createVirtualNetwork": {
            "value": "no"
          }
        }
      }
    },
    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[parameters('virtualNetworkName')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [],
      "properties": {
        "mode": "Incremental",
        "addressSpace": {
          "addressPrefixes": [
            "[parameters('vnetAddressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[parameters('subnetName')]",
            "properties": {
              "mode": "Incremental",
              "addressPrefix": "[parameters('subnetAddressPrefix')]"
            }
          }
        ],
        "virtualNetworkPeerings": []
      }
    },
    {
      "type": "Microsoft.Network/virtualNetworks/subnets",
      "name": "[concat(parameters('virtualNetworkName'), '/', parameters('subnetName'))]",
      "apiVersion": "2017-06-01",
      "properties": {
        "addressPrefix": "[parameters('subnetAddressPrefix')]",
        "privateAccessServices": []
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]"
      ]
    },
    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[concat(parameters('virtualNetworkName'), '-interface1')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              /*
              "privateIPAllocationMethod": "Static",
              // reserved IP address range for /24 is 1-3, so start with [0 + 4] or more
              "privateIPAddress": "[parameters('vmIP')]",
              */
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[variables('subnetRef')]"
              }
            }
          }
        ]
      }
    }
  ],
  "outputs": {}
}

nestedtemplates / OverlaySubnet.json

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "solutionName": {
      "type": "string",
      "defaultValue": "testing"
    },
    "createVirtualNetwork": {
      "type": "string",
      "defaultValue": "yes",
      "allowedValues": [
        "yes",
        "no"
      ]
    },
    "virtualNetworkName": {
      "type": "string",
      "defaultValue": "[concat(parameters('solutionName'), '-vnet')]"
    },
    "vnetAddressPrefix": {
      "type": "string",
      "defaultValue": "10.0.0.0/16"
    },
    "subnetName": {
      "type": "string",
      "defaultValue": "[concat(parameters('solutionName'),'-subnet2')]"
    },
    "subnetAddressPrefix": {
      "type": "string",
      "defaultValue": "10.0.101.0/24"
    }
  },
  "variables": {
    "createVirtualNetwork": "[equals(parameters('createVirtualNetwork'), 'yes')]",
    "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',parameters('virtualNetworkName'))]",
    "subnetRef": "[concat(variables('vnetID'),'/subnets/', parameters('subnetName'))]"
  },
  "resources": [
    {
      "condition": "[variables('createVirtualNetwork')]",
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[parameters('virtualNetworkName')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [],
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[parameters('vnetAddressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[parameters('subnetName')]",
            "properties": {
              "mode": "Incremental",
              "addressPrefix": "[parameters('subnetAddressPrefix')]"
            }
          }
        ],
        "virtualNetworkPeerings": []
      }
    },
    {
      "type": "Microsoft.Network/virtualNetworks/subnets",
      "name": "[concat(parameters('virtualNetworkName'), '/', parameters('subnetName'))]",
      "apiVersion": "2017-06-01",
      "properties": {
        "addressPrefix": "[parameters('subnetAddressPrefix')]",
        "privateAccessServices": []
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]"
      ]
    },
    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[concat(parameters('virtualNetworkName'), '-interface2')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]",
        "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'), '/subnets/', parameters('subnetName'))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              /*
              "privateIPAllocationMethod": "Static",
              // reserved IP address range for /24 is 1-3, so start with [0 + 4] or more
              "privateIPAddress": "[parameters('vmIP')]",
              */
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[variables('subnetRef')]"
              }
            }
          }
        ]
      }
    }
  ],
  "outputs": {}
}