【问题标题】:Can I loop over properties in ARM templates?我可以遍历 ARM 模板中的属性吗?
【发布时间】:2017-01-26 20:55:58
【问题描述】:

我有一个 ARM 模板,我在其中设置了一个负载均衡器,我想通过向 LB 添加规则和探测来添加多个端口开放。

这是我目前拥有的模板:

    {
        "type": "Microsoft.Network/loadBalancers",
        "name": "LB-front",
        "apiVersion": "2016-03-30",
        "location": "westeurope",
        "tags": { },
        "properties": {
            "frontendIPConfigurations": [
                {
                    "name": "LoadBalancerIPConfig",
                    "properties": {
                        "privateIPAllocationMethod": "Dynamic",
                        "publicIPAddress": {
                            "id": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddresses_lbipdev_0_name'))]"
                        }
                    }
                }
            ],
            "backendAddressPools": [
                {
                    "name": "LoadBalancerBEAddressPool"
                }
            ],
            "loadBalancingRules": [
                {
                    "name": "AppPortLBRule1",
                    "properties": {
                        "frontendIPConfiguration": {
                            "id": "[parameters('loadBalancers_LB_dev_id_6')]"
                        },
                        "frontendPort": 80,
                        "backendPort": 80,
                        "enableFloatingIP": false,
                        "idleTimeoutInMinutes": 5,
                        "protocol": "Tcp",
                        "loadDistribution": "Default",
                        "backendAddressPool": {
                            "id": "[parameters('loadBalancers_LB_dev_id_7')]"
                        },
                        "probe": {
                            "id": "[parameters('loadBalancers_LB_dev_id_8')]"
                        }
                    }
                },
                {
                    "name": "AppPortLBRule2",
                    "properties": {
                        "frontendIPConfiguration": {
                            "id": "[parameters('loadBalancers_LB_dev_id_9')]"
                        },
                        "frontendPort": 81,
                        "backendPort": 81,
                        "enableFloatingIP": false,
                        "idleTimeoutInMinutes": 5,
                        "protocol": "Tcp",
                        "loadDistribution": "Default",
                        "backendAddressPool": {
                            "id": "[parameters('loadBalancers_LB_dev_id_10')]"
                        },
                        "probe": {
                            "id": "[parameters('loadBalancers_LB_dev_id_11')]"
                        }
                    }
                },
                {
                    "name": "AppPortLBRule3",
                    "properties": {
                        "frontendIPConfiguration": {
                            "id": "[parameters('loadBalancers_LB_dev_id_12')]"
                        },
                        "frontendPort": 82,
                        "backendPort": 82,
                        "enableFloatingIP": false,
                        "idleTimeoutInMinutes": 5,
                        "protocol": "Tcp",
                        "loadDistribution": "Default",
                        "backendAddressPool": {
                            "id": "[parameters('loadBalancers_LB_dev_id_13')]"
                        },
                        "probe": {
                            "id": "[parameters('loadBalancers_LB_dev_id_14')]"
                        }
                    }
                }
            ],
            "probes": [
                {
                    "name": "AppPortProbe1",
                    "properties": {
                        "protocol": "Tcp",
                        "port": 80,
                        "intervalInSeconds": 5,
                        "numberOfProbes": 2
                    }
                },
                {
                    "name": "AppPortProbe2",
                    "properties": {
                        "protocol": "Tcp",
                        "port": 81,
                        "intervalInSeconds": 5,
                        "numberOfProbes": 2
                    }
                },
                {
                    "name": "AppPortProbe3",
                    "properties": {
                        "protocol": "Tcp",
                        "port": 82,
                        "intervalInSeconds": 5,
                        "numberOfProbes": 2
                    }
                }
            ],
            "inboundNatRules": [],
            "outboundNatRules": [],
            "inboundNatPools": []
        },
        "resources": [],
        "dependsOn": [
            "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddresses_lbipdev_1_name'))]"
        ]
    },

(省略了一些细节)

我想要做的是拥有一个端口号数组,我想为其创建规则和探测并循环这些端口号,而不是显式地编写每个规则和探测作为资源的属性。

基本上我希望我的模板中有一个参数或变量,如下所示:

"ports": [ 80, 81, 82, ...]

我可以像这样循环:https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple。

【问题讨论】:

    标签: azure arm-template azure-resource-manager


    【解决方案1】:

    确实可以! 复制确实适用于属性!

    像这样创建一个参数或变量(本例将使用参数数组):

    "lbRules": {
      "type": "array",
      "defaultValue": [
        {
          "name": "httpPort",
          "frontendPort": "80",
          "backendPort": "80",
          "protocol": "tcp"
        },
        {
          "name": "customAppPort",
          "frontendPort": "8080",
          "backendPort": "8888",
          "protocol": "tcp"
        },
        {
          "name": "httpsPort",
          "frontendPort": "443",
          "backendPort": "443",
          "protocol": "tcp"
        }
      ]
    }
    

    使用 copy 在负载均衡器资源中使用此参数,这样会创建您在参数数组中定义的许多探测和规则:

    {
      "apiVersion": "[variables('lbApiVersion')]",
      "type": "Microsoft.Network/loadBalancers",
      "name": "[parameters('myLoadBalancer')]",
      "location": "[parameters('computeLocation')]",
      "dependsOn": [
        "[concat('Microsoft.Network/publicIPAddresses/',concat(parameters('lbIPName'),'-','0'))]"
      ],
      "properties": {
        "frontendIPConfigurations": [
          {
            "name": "LoadBalancerIPConfig",
            "properties": {
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(parameters('lbIPName'),'-','0'))]"
              }
            }
          }
        ],
        "backendAddressPools": [
          {
            "name": "LoadBalancerBEAddressPool",
            "properties": {}
          }
        ],
    
        "copy": [
          {
            "name": "probes",
            "count": "[length(parameters('lbRules'))]",
            "input": {
              "name": "[concat(parameters('lbRules')[copyIndex('probes')].name,'Probe')]",
              "properties": {
                "intervalInSeconds": 5,
                "numberOfProbes": 2,
                "port": "[parameters('lbRules')[copyIndex('probes')].backendPort]",
                "protocol": "[parameters('lbRules')[copyIndex('probes')].protocol]"
    
              }
            }
          },
    
          {
            "name": "loadBalancingRules",
            "count": "[length(parameters('lbRules'))]",
            "input": {
              "name": "[parameters('lbRules')[copyIndex('loadBalancingRules')].name]",
              "properties": {
                "frontendIPConfiguration": {
                  "id": "[concat(resourceId('Microsoft.Network/loadBalancers', parameters('myLoadBalancer')),'/frontendIPConfigurations/LoadBalancerIPConfig')]"
                },
                "frontendport": "[parameters('lbRules')[copyIndex('loadBalancingRules')].frontendport]",
                "backendport": "[parameters('lbRules')[copyIndex('loadBalancingRules')].backendport]",
                "enableFloatingIP": false,
                "idleTimeoutInMinutes": "5",
                "protocol": "[parameters('lbRules')[copyIndex('loadBalancingRules')].protocol]",
                "backendAddressPool": {
                  "id": "[concat(resourceId('Microsoft.Network/loadBalancers', parameters('myLoadBalancer')),'/backendAddressPools/LoadBalancerBEAddressPool')]"
                },
                "probe": {
                  "id": "[concat(variables('lbID0'),'/probes/', parameters('lbRules')[copyIndex('loadBalancingRules')].name,'Probe')]"
                }
              }
            }
          }
        ],
    
    
        "inboundNatPools": []
      },
    
      }
    }
    

    更多信息可以在这里找到:

    【讨论】:

    【解决方案2】:

    您只能将复制对象应用到顶级资源。

    您不能将其应用于资源类型的属性或子资源。

    "resources": [
      {
        "type": "{provider-namespace-and-type}",
        "name": "parentResource",
        "copy": {  
          /* yes, copy can be applied here */
        },
        "properties": {
          "exampleProperty": {
            /* no, copy cannot be applied here */
          }
        },
        "resources": [
          {
            "type": "{provider-type}",
            "name": "childResource",
            /* copy can be applied if resource is promoted to top level */ 
          }
        ]
      }
    ] 
    

    Source of Quotation: Deploy multiple instances of resources in Azure Resource Manager templates

    您可以循环访问 ARM 模板中的属性仅当复制对象应用于顶级资源,在您的情况下为 “Microsoft.Network/loadBalancers” strong>,但这也会创建所述资源的多个副本。

    如果这不是您想要实现的目标,我建议您保留现有方式,直到 ARM 模板将来支持将对象复制到资源类型上的属性。

    【讨论】:

    • 如果该资源在技术上是“具体”资源的子资源,我如何将资源提升到顶级?例如。 WebSite 作为顶层,WebSite/Extension 作为子级。我可以将扩展资源作为顶级声明并对网站进行某种形式的依赖吗?
    • 谢谢你的回答。
    • @lee-g 是的,您可以在顶层声明子资源,只需将父资源的类型/名称添加到子资源的类型/名称。见这里:docs.microsoft.com/en-us/azure/azure-resource-manager/…。完成此操作后,您还可以再次使用属性迭代。
    • 不再是有效答案
    【解决方案3】:

    现在可以循环属性或子资源,如https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#property-iteration 或 https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#create-multiple-instances-of-a-child-resource

    您可以按照类型的格式将子资源扩展(例如网站/扩展)作为顶级资源: {resource-provider-namespace}/{parent-resource-type}/{child-resource-type}. 例如 Microsoft.Web/sites/siteextensions

    您还必须通过连接引用子资源中的父资源。例如: "name": "[concat('mywebsite', '/', 'myextension', copyIndex())]"

    【讨论】:

      【解决方案4】:

      take 功能可以实现您想要实现的目标。 您自己链接了正确的文档站点。转到您发布的链接并查看“复制不起作用时创建多个实例”部分。。

      在你的情况下,这看起来像这样:

      "variables": {
          "probeArray": [                    
                 {
                   "name": "AppPortProbe1",
                   "properties": {
                       "protocol": "Tcp",
                       "port": 80,
                       "intervalInSeconds": 5,
                       "numberOfProbes": 2
                   }
                 },
                 {
                   "name": "AppPortProbe2",
                   "properties": {
                       "protocol": "Tcp",
                       "port": 81,
                       "intervalInSeconds": 5,
                       "numberOfProbes": 2
                   }
                 },
                 {
                   "name": "AppPortProbe3",
                   "properties": {
                       "protocol": "Tcp",
                       "port": 82,
                       "intervalInSeconds": 5,
                       "numberOfProbes": 2
                   }
                 }
          ],
      

      然后你创建一个参数来指定你想要多少个探针

      "parameters": {
      ...
      "numProbes": {
        "type": "int",
        "maxValue": 3,
        "metadata": {
          "description": "This parameter allows you to select the number of probes you want"
        }
      }
      

      最后你在资源中使用take:

      "resources": [
      ...
      {
        "type": "Microsoft.Network/loadBalancers",
        "properties": {
            ...
            "probes": "[take(variables('probeArray'),parameters('numProbes'))]"
          },
          ...
        }
        ...
      }
      ]
      

      如果您继续阅读文档,您会发现您会变得更加疯狂,并将复制和获取与链接模板结合起来。

      【讨论】:

      • 这是否意味着我仍然必须声明所有探针,但要在 variablea 中突出显示?我希望有一种方法只需将它们声明为一个块,然后循环遍历唯一改变的东西,即端口号。
      • 是的,您必须在执行此操作时定义探针。没有简单的方法可以使用 copyIndex() 遍历属性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多