共用方式為

为 Azure Kubernetes 服务 (AKS) 群集创建托管或用户分配的 NAT 网关

虽然你可以通过 Azure 负载均衡器路由出口流量,但可以创建的出站流量的流数量有限制。 Azure NAT 网关允许每个 IP 地址最多 64,512 个出站 UDP 和 TCP 流量流,并且最多只能有 16 个 IP 地址。

本文介绍了如何创建一个带有托管 NAT 网关和用户分配的 NAT 网关的 Azure Kubernetes 服务 (AKS) 集群,用于处理出口流量。 它还演示了如何在 Windows 上禁用 OutboundNAT。

开始之前

  • 确保使用最新版本的 Azure CLI
  • 请确保使用的是 Kubernetes 版本 1.20.x 或更高版本。
  • 托管 NAT 网关与自定义虚拟网络不兼容。

重要

在非专用群集中,API 服务器群集流量是通过群集出站类型路由和处理的。 若要防止 API 服务器流量作为公共流量进行处理,请考虑使用 专用群集

创建带有托管 NAT 网关的 AKS 群集

  • 使用带有 az aks create--outbound-type managedNATGateway--nat-gateway-managed-outbound-ip-count 参数的 --nat-gateway-idle-timeout 命令创建具有新的托管 NAT 网关的 AKS 群集。 如果希望 NAT 网关从特定可用性区域运行,请使用 --zones 指定区域。
  • 如果在创建托管 NAT 网关时未指定任何区域,则默认情况下,NAT 网关将部署到“无区域”。 将 NAT 网关放置在“无区域”中时,Azure 会将资源放置在某个区域中。 有关非区域性部署模型的详细信息,请参阅非区域性 NAT 网关
  • 托管 NAT 网关资源不能跨多个可用性区域使用。

以下命令首先创建所需的资源组,然后使用托管 NAT 网关创建 AKS 群集。

export RANDOM_SUFFIX=$(openssl rand -hex 3)
export MY_RG="myResourceGroup$RANDOM_SUFFIX"
export MY_AKS="myNatCluster$RANDOM_SUFFIX"
az group create --name $MY_RG --location "eastus2"

结果:

{
  "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroupxxx",
  "location": "eastus2",
  "managedBy": null,
  "name": "myResourceGroupxxx",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": "Microsoft.Resources/resourceGroups"
}
az aks create \
    --resource-group $MY_RG \
    --name $MY_AKS \
    --node-count 3 \
    --outbound-type managedNATGateway \
    --nat-gateway-managed-outbound-ip-count 2 \
    --nat-gateway-idle-timeout 4 \
    --generate-ssh-keys

结果:

{
  "aadProfile": null,
  "agentPoolProfiles": [
    {
      ...
      "name": "nodepool1",
      ...
      "provisioningState": "Succeeded",
      ...
    }
  ],
  "dnsPrefix": "myNatClusterxxx-dns-xxx",
  "fqdn": "myNatClusterxxx-dns-xxx.xxxxx.xxxxxx.chinacloudapp.cn",
  "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroupxxx/providers/Microsoft.ContainerService/managedClusters/myNatClusterxxx",
  "name": "myNatClusterxxx",
  ...
  "resourceGroup": "myResourceGroupxxx",
  ...
  "provisioningState": "Succeeded",
  ...
  "type": "Microsoft.ContainerService/ManagedClusters"
}
  • 使用带 az aks update--nat-gateway-managed-outbound-ip-count 参数的 --nat-gateway-idle-timeout 命令更新出站 IP 地址或空闲超时。

以下示例将 AKS 群集的 NAT 网关托管出站 IP 计数更新为 5。

az aks update \
    --resource-group $MY_RG \
    --name $MY_AKS \
    --nat-gateway-managed-outbound-ip-count 5

结果:

{
  "aadProfile": null,
  "agentPoolProfiles": [
    {
      ...
      "name": "nodepool1",
      ...
      "provisioningState": "Succeeded",
      ...
    }
  ],
  "dnsPrefix": "myNatClusterxxx-dns-xxx",
  "fqdn": "myNatClusterxxx-dns-xxx.xxxxx.xxxxxx.chinacloudapp.cn",
  "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroupxxx/providers/Microsoft.ContainerService/managedClusters/myNatClusterxxx",
  "name": "myNatClusterxxx",
  ...
  "resourceGroup": "myResourceGroupxxx",
  ...
  "provisioningState": "Succeeded",
  ...
  "type": "Microsoft.ContainerService/ManagedClusters"
}

创建带有用户分配的 NAT 网关的 AKS 群集

此配置需要自带网络(通过 KubenetAzure CNI),并且需要在子网中预配置 NAT 网关。 以下命令为此方案创建所需的资源。

  1. 使用 az group create 命令创建资源组。

    export RANDOM_SUFFIX=$(openssl rand -hex 3)
    export MY_RG="myResourceGroup$RANDOM_SUFFIX"
    az group create --name $MY_RG --location southcentralus
    

    结果:

    {
      "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroupxxx",
      "location": "southcentralus",
      "managedBy": null,
      "name": "myResourceGroupxxx",
      "properties": {
        "provisioningState": "Succeeded"
      },
      "tags": null,
      "type": "Microsoft.Resources/resourceGroups"
    }
    
  2. 创建托管标识以获取网络权限,并将 ID 存储到 $IDENTITY_ID 中供稍后使用。

    export IDENTITY_NAME="myNatClusterId$RANDOM_SUFFIX"
    export IDENTITY_ID=$(az identity create \
        --resource-group $MY_RG \
        --name $IDENTITY_NAME \
        --location southcentralus \
        --query id \
        --output tsv)
    

    结果:

    /xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroupxxx/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myNatClusterIdxxx
    
  3. 使用 az network public-ip create 命令为 NAT 网关创建公共 IP。

    export PIP_NAME="myNatGatewayPip$RANDOM_SUFFIX"
    az network public-ip create \
        --resource-group $MY_RG \
        --name $PIP_NAME \
        --location southcentralus \
        --sku standard
    

    结果:

    {
      "publicIp": {
        "ddosSettings": null,
        "dnsSettings": null,
        "etag": "W/\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"",
        "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroupxxx/providers/Microsoft.Network/publicIPAddresses/myNatGatewayPipxxx",
        "ipAddress": null,
        "ipTags": [],
        "location": "southcentralus",
        "name": "myNatGatewayPipxxx",
        ...
        "provisioningState": "Succeeded",
        ...
        "sku": {
          "name": "Standard",
          "tier": "Regional"
        },
        "type": "Microsoft.Network/publicIPAddresses",
        ...
      }
    }
    
  4. 使用 az network nat gateway create 命令创建 NAT 网关。

    export NATGATEWAY_NAME="myNatGateway$RANDOM_SUFFIX"
    az network nat gateway create \
        --resource-group $MY_RG \
        --name $NATGATEWAY_NAME \
        --location southcentralus \
        --public-ip-addresses $PIP_NAME
    

    结果:

    {
      "etag": "W/\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"",
      "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroupxxx/providers/Microsoft.Network/natGateways/myNatGatewayxxx",
      "location": "southcentralus",
      "name": "myNatGatewayxxx",
      "provisioningState": "Succeeded",
      "publicIpAddresses": [
        {
          "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroupxxx/providers/Microsoft.Network/publicIPAddresses/myNatGatewayPipxxx"
        }
      ],
      ...
      "type": "Microsoft.Network/natGateways"
    }
    

    重要

    单个 NAT 网关资源不能跨多个可用性区域使用。 为了确保区域复原能力,建议将 NAT 网关资源部署到每个可用性区域,并分配给每个区域中包含 AKS 群集的子网。 有关此部署模型的详细信息,请参阅每个区域的 NAT 网关。 如果未为 NAT 网关配置任何区域,则默认区域放置为“无区域”,其中 Azure 会将 NAT 网关放入一个区域中。

  5. 使用 az network vnet create 命令创建虚拟网络。

    export VNET_NAME="myVnet$RANDOM_SUFFIX"
    az network vnet create \
        --resource-group $MY_RG \
        --name $VNET_NAME \
        --location southcentralus \
        --address-prefixes 172.16.0.0/20 
    

    结果:

    {
      "newVNet": {
        "addressSpace": {
          "addressPrefixes": [
            "172.16.0.0/20"
          ]
        },
        ...
        "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroupxxx/providers/Microsoft.Network/virtualNetworks/myVnetxxx",
        "location": "southcentralus",
        "name": "myVnetxxx",
        "provisioningState": "Succeeded",
        ...
        "type": "Microsoft.Network/virtualNetworks",
        ...
      }
    }
    
  6. 使用 NAT 网关在虚拟网络中创建子网,并将 ID 存储到 $SUBNET_ID 中供稍后使用。

    export SUBNET_NAME="myNatCluster$RANDOM_SUFFIX"
    export SUBNET_ID=$(az network vnet subnet create \
        --resource-group $MY_RG \
        --vnet-name $VNET_NAME \
        --name $SUBNET_NAME \
        --address-prefixes 172.16.0.0/22 \
        --nat-gateway $NATGATEWAY_NAME \
        --query id \
        --output tsv)
    

    结果:

    /xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroupxxx/providers/Microsoft.Network/virtualNetworks/myVnetxxx/subnets/myNatClusterxxx
    
  7. 使用 az aks create 命令通过具有 NAT 网关和托管标识的子网创建 AKS 群集。

    export AKS_NAME="myNatCluster$RANDOM_SUFFIX"
    az aks create \
        --resource-group $MY_RG \
        --name $AKS_NAME \
        --location southcentralus \
        --network-plugin azure \
        --vnet-subnet-id $SUBNET_ID \
        --outbound-type userAssignedNATGateway \
        --assign-identity $IDENTITY_ID \
        --generate-ssh-keys
    

    结果:

    {
      "aadProfile": null,
      "agentPoolProfiles": [
        {
          ...
          "name": "nodepool1",
          ...
          "provisioningState": "Succeeded",
          ...
        }
      ],
      "dnsPrefix": "myNatClusterxxx-dns-xxx",
      "fqdn": "myNatClusterxxx-dns-xxx.xxxxx.xxxxxx.chinacloudapp.cn",
      "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourcegroups/myResourceGroupxxx/providers/Microsoft.ContainerService/managedClusters/myNatClusterxxx",
      "name": "myNatClusterxxx",
      ...
      "resourceGroup": "myResourceGroupxxx",
      ...
      "provisioningState": "Succeeded",
      ...
      "type": "Microsoft.ContainerService/ManagedClusters"
    }
    

为 Windows 禁用 OutboundNAT

Windows OutboundNAT 可能导致 AKS Pod 出现某些连接和通信问题。 一个示例问题是节点端口重用。 在此示例中,Windows OutboundNAT 使用端口将 Pod IP 转换为 Windows 节点主机 IP,这可能会因端口耗尽问题而导致与外部服务的连接不稳定。

Windows 默认会启用 OutboundNAT。 现在可以在创建新的 Windows 代理池时手动禁用 OutboundNAT。

先决条件

  • 具有 v1.26 或更高版本的现有 AKS 群集。 如果使用的是 Kubernetes 1.25 或更低版本,则需要更新部署配置

限制

  • 无法将群集出站类型设置为 LoadBalancer。 可以将它设置为 NAT 网关或 UDR:
    • NAT 网关:NAT 网关可以自动处理 NAT 连接,并且比标准负载均衡器更强大。 此选项可能会产生额外费用。
    • UDR (UserDefinedRouting):配置传递规则时,必须牢记端口限制。
    • 如果需要从负载均衡器切换到 NAT 网关,则可以将 NAT 网关添加到 VNet 中,或运行 az aks upgrade 以更新出站类型。

注意

UserDefinedRouting 具有以下限制:

  • Azure 负载均衡器的 SNAT(必须使用默认 OutboundNAT)具有“主机 IP 上的 64 个端口”。
  • Azure 防火墙的 SNAT(禁用 OutboundNAT)对每个公共 IP 有 2496 个端口。
  • NAT 网关的 SNAT(禁用 OutboundNAT)对每个公共 IP 有 64512 个端口。
  • 如果 Azure 防火墙端口范围对于应用程序来说不够用,则需要使用 NAT 网关。
  • 如果目标 IP 地址在符合 IANA RFC 1918 的专用 IP 地址范围内或符合 IANA RFC 6598 的共享地址空间内,Azure 防火墙将不使用网络规则执行 SNAT。

手动为 Windows 禁用 OutboundNAT

  • 在使用带有 az aks nodepool add 标记的 --disable-windows-outbound-nat 命令创建新的 Windows 代理池时,可以手动为 Windows 禁用 OutboundNAT。

    注意

    可以使用现有的 AKS 群集,但可能需要更新出站类型并添加节点池以启用 --disable-windows-outbound-nat

    以下命令将 Windows 节点池添加到现有 AKS 群集,禁用 OutboundNAT。

      export WIN_NODEPOOL_NAME="win$(head -c 1 /dev/urandom | xxd -p)"
      az aks nodepool add \
        --resource-group $MY_RG \
        --cluster-name $MY_AKS \
        --name $WIN_NODEPOOL_NAME \
        --node-count 3 \
        --os-type Windows \
        --disable-windows-outbound-nat
    

    结果:

    {
      "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroupxxx/providers/Microsoft.ContainerService/managedClusters/myNatClusterxxx/agentPools/mynpxxx",
      "name": "mynpxxx",
      "osType": "Windows",
      "provisioningState": "Succeeded",
      "resourceGroup": "myResourceGroupxxx",
      "type": "Microsoft.ContainerService/managedClusters/agentPools"
    }
    

后续步骤

有关 Azure NAT 网关的详细信息,请参阅 Azure NAT 网关