【问题标题】:Assign static outbound ip address to azure container instance将静态出站 IP 地址分配给 azure 容器实例
【发布时间】:2020-09-13 00:28:57
【问题描述】:

我需要进行设置,以便我可以从驻留在 azure 容器实例中的 python 脚本读取和写入外部 sql db。为了完成这项工作,我需要为容器分配一个静态 ip。

由于我无法将容器实例与专用 IP 相关联,我不得不进行使用以下资源的设置:vnet、网关和公共 IP。

我从https://godatadriven.com/blog/azure-container-instance-example/那里借了一部分设置,设置如下:

我已经创建了一个 dev-ops 构建和发布管道。我使用一个ARM模板来创建release(模板的资源如下):

  "resources": [
    {
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[parameters('vnetName')]",
      "apiVersion": "2019-07-01",
      "location": "[parameters('location')]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[parameters('vnetAddressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[parameters('subnet2Name')]",
            "properties": {
              "addressPrefix": "[parameters('subnet2AddressPrefix')]",
              "privateEndpointNetworkPolicies": "Enabled",
              "privateLinkServiceNetworkPolicies": "Enabled"
            }
          },
          {
            "name": "[parameters('subnetName')]",
            "properties": {
              "addressPrefix": "[parameters('subnetAddressPrefix')]",
              "delegations": [
                {
                  "name": "DelegationService",
                  "properties": {
                    "serviceName": "Microsoft.ContainerInstance/containerGroups"
                  }
                }
              ],
              "privateEndpointNetworkPolicies": "Enabled",
              "privateLinkServiceNetworkPolicies": "Enabled"
            }
          }
        ]
      }
    },
    {
      "apiVersion": "2018-07-01",
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "[variables('publicIPAddressName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard",
        "tier": "Regional"
      },
      "properties": {
        "publicIPAddressVersion": "IPv4",
        "publicIPAllocationMethod": "Static",
        "idleTimeoutInMinutes": 4,
         "dnsSettings": {
          "domainNameLabel": "[parameters('dnsName')]"
        }
      }
    },
    {
      "apiVersion": "2019-08-01",
      "name": "[variables('applicationGatewayName')]",
      "type": "Microsoft.Network/applicationGateways",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks/', parameters('vnetName'))]",
        "[resourceId('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
        "[resourceId('Microsoft.ContainerInstance/containerGroups/', parameters('containerInstanceName'))]"
      ],
      "properties": {
        "sku": {
          "name": "[parameters('skuName')]",
          "tier": "Standard_v2",
          "capacity": "[variables('capacity')]"
        },
        "gatewayIPConfigurations": [
          {
            "name": "appGatewayIpConfig",
            "properties": {
              "subnet": {
                "id": "[variables('subnetRef')]"
              }
            }
          }
        ],
        "frontendIPConfigurations": [
          {
            "name": "appGatewayFrontendIP",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "PublicIPAddress": {
                "id": "[variables('publicIPRef')]"
              }
            }
          }
        ],
        "frontendPorts": [
          {
            "name": "appGatewayFrontendPort",
            "properties": {
              "Port": 80
            }
          }
        ],
        "backendAddressPools": [
          {
            "name": "appGatewayBackendPool",
            "properties": {
              "backendAddresses": [
                {
                  "IpAddress": "[parameters('backendIP')]"
                }
              ]
            }
          }
        ],
        "backendHttpSettingsCollection": [
          {
            "name": "appGatewayBackendHttpSettings",
            "properties": {
              "Port": 80,
              "Protocol": "Http",
              "CookieBasedAffinity": "Disabled"
            }
          }
        ],
        "httpListeners": [
          {
            "name": "appGatewayHttpListener",
            "properties": {
              "FrontendIPConfiguration": {
                "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations', variables('applicationGatewayName'), 'appGatewayFrontendIP')]"
              },
              "FrontendPort": {
                "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendPorts', variables('applicationGatewayName'), 'appGatewayFrontendPort')]"
              },
              "Protocol": "Http",
              "SslCertificate": null
            }
          }
        ],
        "requestRoutingRules": [
          {
            "Name": "rule1",
            "properties": {
              "RuleType": "Basic",
              "httpListener": {
                "id": "[resourceId('Microsoft.Network/applicationGateways/httpListeners', variables('applicationGatewayName'), 'appGatewayHttpListener')]"
              },
              "backendAddressPool": {
                "id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools', variables('applicationGatewayName'), 'appGatewayBackendPool')]"
              },
              "backendHttpSettings": {
                "id": "[resourceId('Microsoft.Network/applicationGateways/backendHttpSettingsCollection', variables('applicationGatewayName'), 'appGatewayBackendHttpSettings')]"
              }
            }
          }
        ]
      }
    },
    {
      "name": "[parameters('networkProfileName')]",
      "type": "Microsoft.Network/networkProfiles",
      "apiVersion": "2018-07-01",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]"
      ],
      "properties": {
        "containerNetworkInterfaceConfigurations": [
          {
            "name": "[variables('interfaceConfigName')]",
            "properties": {
              "ipConfigurations": [
                {
                  "name": "[variables('interfaceIpConfig')]",
                  "properties": {
                    "subnet": {
                      "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetName'))]"
                    }
                  }
                }
              ]
            }
          }
        ]
      }
    },
    {
      "name": "[parameters('containerInstanceName')]",
      "type": "Microsoft.ContainerInstance/containerGroups",
      "apiVersion": "2018-10-01",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkProfiles', parameters('networkProfileName'))]"
      ],
      "properties": {
        "containers": [
          {
            "name": "[parameters('containerName')]",
            "properties": {
              "image": "[parameters('registryImageUri')]",
              "ports": [{
                "port": "[variables('port')]"
              }],
              "resources": {
                "requests": {
                  "cpu": "[variables('cpuCores')]",
                  "memoryInGb": "[variables('memoryInGb')]"
                }
              }
            }
          }
        ],
        "imageRegistryCredentials": [
          {
            "server": "[parameters('registryLoginServer')]",
            "username": "[parameters('registryUserName')]",
            "password": "[parameters('registryPassword')]"
          }
        ],
        "diagnostics": {
          "logAnalytics": {
          "workspaceId": "[parameters('LogAnalyticsID')]",
          "workspaceKey": "[parameters('LogAnalyticsKEY')]"
         }
        },
        "networkProfile": {
          "Id": "[resourceId('Microsoft.Network/networkProfiles', parameters('networkProfileName'))]"
        },
        "osType": "Linux",
        "ipAddress": {
            "ports": [{
                "protocol": "tcp",
                "port": 80
            }],
            "type": "private",
            "ip": "[parameters('backendIP')]"
        },
        "restartPolicy": "[parameters('restartPolicy')]"
      }
    }
  ]

该版本有效,但是当我运行时我尝试运行容器实例,它每次都使用不同的 ip。

我做错了什么?

【问题讨论】:

  • 你指的是哪个 IP 正在改变?
  • 另外,您在 Azure 中的“外部 sql db”是否使用他们的 SaaS 产品?
  • 另外,您是否每次运行管道时都重新运行整个 ARM 模板?
  • @djsly ,正在改变的 ip 是面向外部的 ip。我在容器内的脚本中使用 odbc (pyodbc) 连接到 sql db,当我运行容器时,我收到一条错误消息,指出“不允许 IP 地址为 'xx.xx.xxx.xxx' 的客户端访问服务器."。我已经多次运行 ARM 模板,但是当我尝试启动容器实例(不重新运行管道)时,ip 发生了变化。
  • 你在使用 azure sql 服务吗?

标签: azure-resource-manager azure-container-instances vnet azure-public-ip


【解决方案1】:

由于您使用的是 Azure 提供的 SQL,我建议您利用 Azure 提供的私有 VNET 产品。

您应该考虑使用私有子网配置您的 ACI https://docs.microsoft.com/en-us/azure/container-instances/container-instances-vnet

并为您的 SQL 服务器设置 vnet 规则

https://docs.microsoft.com/en-us/azure/sql-database/sql-database-vnet-service-endpoint-rule-overview

Virtual network rules are one firewall security feature that controls whether the database server for your single databases and elastic pool in Azure SQL Database or for your databases in Azure Synapse Analytics accepts communications that are sent from particular subnets in virtual networks.

在 ACI 子网上为 SQL 启用 SQL 服务端点也很重要。

这将避免您必须在 SQL 防火墙中管理出站 IP 白名单。

【讨论】:

    【解决方案2】:

    从你所做的事情来看,我认为你误解了 Azure Container Instance 的网络。 ACI 的 Public 或 Private 类型仅适用于入站流量,不适用于出站流量。即使你使用私有类型,实例也可以在没有任何其他资源的情况下访问互联网,但是在这种类型中,你不能从互联网访问它。

    不幸的是,当您使用公共类型时,入站和出站的公共 IP 地址可能甚至不一样。而对于 Azure Container Instance,我们无法控制我们可以使用的 IP 地址。所以当你想使用静态公网IP访问SQL DB时,Azure Container Instance就不适合了,我推荐VM,它更可控也更合适。

    【讨论】:

    • @charles_xu 死了,表示无法控制出站ip,当使用“just”的容器时很难吗?
    • @MartinPetriBagger 是的,我们对 ACI 没有太多控制权。
    猜你喜欢
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 1970-01-01
    • 2018-11-13
    • 1970-01-01
    • 2020-05-02
    相关资源
    最近更新 更多