Estoy desarrollando una plantilla ARM para implementar un App Service Environment v2 configurado con un Internal Load Balancer (ILB ASE). ¿Hay alguna forma de obtener la dirección IP virtual (VIP) que obtiene el equilibrador de carga interno de la red virtual a la que está conectado como salida? Cuando miro las propiedades del ASE a través de PowerShell después de su aprovisionamiento, no veo una propiedad para la dirección IP o para el equilibrador de carga.

2
phydeauxman 6 mar. 2018 a las 20:18

3 respuestas

La mejor respuesta

Después de mucha investigación y pruebas ... actualmente no hay forma de hacer esto como resultado de la plantilla ARM. Estas son las formas en que se puede recopilar el valor:

  1. Vía Resource Explorer ... aunque esto no es muy útil para hacerlo mediante programación, pero me ayudó a descubrir las otras 2 formas

  2. Usando PowerShell para consultar la API de management.azure.com, pero debe publicar una aplicación con los permisos apropiados y asignar la aplicación para que tenga permisos en la suscripción desde la que está intentando consultar recursos

  3. Uso de la CLI de Azure. Este método resultó ser el más fácil.

Necesitaba este valor para automatizar completamente la implementación de una puerta de enlace de aplicaciones frente a un ASE ILB. Uso Terraform para la automatización de la implementación y ejecuto las configuraciones de Terraform desde Azure Cloud Shell. Comienzo mis implementaciones con un script de shell donde obtengo dinámicamente la clave de la cuenta de almacenamiento a la cuenta de almacenamiento donde almaceno los archivos de estado. Luego consulto al ASE de ILB para obtener la dirección IP y establecerla en una variable que luego paso a Terraform

A continuación se muestra una copia del script de shell que uso:

#!/bin/bash
set -eo pipefail

# The block below will grab the access key for the storage account that is used
# to store state files

subscription_name="<my_subscription_name>"
tfstate_storage_resource_group="terraform-state-rg"
tfstate_storage_account="<name_of_statefile_storage_account>"
subscription_id="my_subscription_id>"
ilbase_rg_name="<name_of_resourcegroup_where_ase_is_deployed>"
ilbase_name="<name_of_ase>"

az account set --subscription "$subscription_name"
tfstate_storage_access_key=$(
  az storage account keys list \
  --resource-group "$tfstate_storage_resource_group" \
  --account-name "$tfstate_storage_account" \
  --query '[0].value' -o tsv
)

echo ""
echo "Terraform state storage account access key:"
echo $tfstate_storage_access_key
echo ""

# The block below will get the Virtual IP of the ASE Internal Load Balancer
# which will be used to create the App GW

ilbase_virtual_ip=$(
  az resource show \
  --ids "/subscriptions/$subscription_id/resourceGroups/$ilbase_rg_name/providers/Microsoft.Web/hostingEnvironments/$ilbase_name/capacities/virtualip" \
  --query "additionalProperties.internalIpAddress"
)

echo ""
echo "ASE internal load balancer IP:"
echo $ilbase_virtual_ip
echo ""

terraform plan \
  -var "tfstate_access_key=$tfstate_storage_access_key" \
  -var "ilbase_virtual_ip=$ilbase_virtual_ip"
2
phydeauxman 22 mar. 2018 a las 18:35

Si está utilizando Terraform, así es como lo hice funcionar. Tuve que usar la fuente de datos externos en Terraform junto con la CLI de Azure y jq para solucionar los errores en Azure y el proveedor de datos externos de Terraform.

# As of writing, the ASE ARM deployment don’t return the IP address of the ILB
# ASE. This workaround querys Azure’s API to get the values we need for use
# elsewhere in the script.
# See this https://stackoverflow.com/a/49436100
data “external” “app_service_environment_ilb_ase_ip_address” {
  # This calls the Azure CLI then passes the value to jq to return JSON as a single
  # string so that external provider can parse it properly. Otherwise you get an
  # error. See this bug https://github.com/terraform-providers/terraform-provider-external/issues/23
  program = [“bash”, “-c”, “az resource show --ids ${local.app_service_environment_id}/capacities/virtualip --query ‘{internalIpAddress: internalIpAddress}’ | jq -c”]

  # Explicit dependency on the ASE ARM deployment because this command will fail
  # if that resource isn’t built yet.
  depends_on = [azurerm_template_deployment.ase]
}
0
Omar 4 sep. 2019 a las 19:09

Puede usar una salida como esta:

"outputs": {
      "privateIp": {
        "type": "string",
          "value": "[reference(parameters('lbname')).frontendIPConfigurations[0].properties.privateIPAddress]"
      }
    }

Aquí está mi plantilla, cree un Vnet y un equilibrador de carga interno:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "vnetName": {
      "type": "string",
      "defaultValue": "VNet1",
      "metadata": {
        "description": "VNet name"
      }
    },
    "vnetAddressPrefix": {
      "type": "string",
      "defaultValue": "10.0.0.0/16",
      "metadata": {
        "description": "Address prefix"
      }
    },
    "subnet1Prefix": {
      "type": "string",
      "defaultValue": "10.0.0.0/24",
      "metadata": {
        "description": "Subnet 1 Prefix"
      }
    },
    "subnet1Name": {
      "type": "string",
      "defaultValue": "Subnet1",
      "metadata": {
        "description": "Subnet 1 Name"
      }
    },
    "subnet2Prefix": {
      "type": "string",
      "defaultValue": "10.0.1.0/24",
      "metadata": {
        "description": "Subnet 2 Prefix"
      }
    },
    "subnet2Name": {
      "type": "string",
      "defaultValue": "Subnet2",
      "metadata": {
        "description": "Subnet 2 Name"
      }
    },
    "lbname": {
      "defaultValue": "jasonlbb",
      "type": "String"
    }
    },
"variables": {
    "virtualnetworkname" : "vnet1",
    "apiVersion": "2015-06-15",
    "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualnetworkname'))]",
    "subnetRef": "[concat(variables('vnetID'),'/subnets/',parameters('subnet1Name'))]"
},
  "resources": [
    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[parameters('vnetName')]",
      "location": "[resourceGroup().location]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[parameters('vnetAddressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[parameters('subnet1Name')]",
            "properties": {
              "addressPrefix": "[parameters('subnet1Prefix')]"
            }
          },
          {
            "name": "[parameters('subnet2Name')]",
            "properties": {
              "addressPrefix": "[parameters('subnet2Prefix')]"
            }
          }
        ]
      }
    },
    {
      "apiVersion": "2015-05-01-preview",
      "type": "Microsoft.Network/loadBalancers",
      "name": "[parameters('lbname')]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[variables('vnetID')]"
      ],
      "properties": {
        "frontendIPConfigurations": [
          {
            "properties": {
              "subnet": {
                "id": "[variables('subnetRef')]"
              },
              "privateIPAllocationMethod": "Dynamic"
            },
            "name": "LoadBalancerFrontend"
          }
        ],
        "backendAddressPools": [
          {
            "name": "BackendPool1"
          }
        ],
        "loadBalancingRules": [
          {
            "properties": {
              "frontendIPConfiguration": {
                "id": "[concat(resourceId('Microsoft.Network/loadBalancers', parameters('lbname')), '/frontendIpConfigurations/LoadBalancerFrontend')]"
              },
              "backendAddressPool": {
                "id": "[concat(resourceId('Microsoft.Network/loadBalancers', parameters('lbname')), '/backendAddressPools/BackendPool1')]"
              },
              "probe": {
                "id": "[concat(resourceId('Microsoft.Network/loadBalancers', parameters('lbname')), '/probes/lbprobe')]"
              },
              "protocol": "Tcp",
              "frontendPort": 80,
              "backendPort": 80,
              "idleTimeoutInMinutes": 15
            },
            "Name": "lbrule"
          }
        ],
        "probes": [
          {
            "properties": {
              "protocol": "Tcp",
              "port": 80,
              "intervalInSeconds": 15,
              "numberOfProbes": 2
            },
            "name": "lbprobe"
          }
        ]
      } 
    }
  ],
  "outputs": {
      "privateIp": {
        "type": "string",
          "value": "[reference(parameters('lbname')).frontendIPConfigurations[0].properties.privateIPAddress]"
      }
    }
}

Aquí está la captura de pantalla sobre el resultado:

enter image description here

Espero que esto ayude.

0
Jason Ye 7 mar. 2018 a las 05:57