将静态出站 IP 地址分配给 Azure 容器实例

Assign static outbound ip address to azure container instance

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

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

部分借鉴了https://godatadriven.com/blog/azure-container-instance-example/的设置,设置如下:

我制作了开发运营构建和发布管道。我使用ARM模板创建发布(模板资源如下):

  "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。

我做错了什么?

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

不幸的是,当您使用public 类型时,入站和出站的public IP 地址甚至可能不相同。而对于 Azure 容器实例,我们无法控制我们可以使用的 IP 地址。所以当你想使用静态public IP地址访问SQL DB时,Azure Container Instance不适合,我会推荐VM,它更可控和合适。

由于您使用的是 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 白名单。