在 Azure Kubernetes 服务 (AKS) 中使用实例级公共 IP

AKS 节点无需使用自身的公共 IP 地址进行通信。 但某些方案可能需要节点池中的节点收到专用公共 IP 地址。 一个常见的场景是游戏工作负载,在这种情况下,游戏主机需要与云端虚拟机建立直接连接,以尽量减少网络跳数。 可通过使用节点公共 IP 在 AKS 上实现此方案。

首先,创建一个新的资源组。

az group create --name <resourceGroup> --location <region>

创建新的 AKS 群集并为节点附加公共 IP。 节点池中的每个节点都将收到唯一的公共 IP。 可以通过查看虚拟机规模集实例来验证这一点。

az aks create \
    --resource-group <resourceGroup> \
    --name <aksClusterName> \
    --location <region> \
    --enable-node-public-ip \
    --generate-ssh-keys

对于现有 AKS 群集,还可以添加新的节点池,并为节点附加公共 IP。

az aks nodepool add --resource-group <resourceGroup> --cluster-name <aksClusterName> --name <newNodePool> --enable-node-public-ip

使用公共 IP 前缀

使用公共 IP 前缀有很多好处。 在创建新群集或添加节点池时,通过 --node-public-ip-prefix-id 标志传递资源 ID,AKS 支持为节点使用来自现有公共 IP 前缀的地址。

首先,使用 az network public-ip prefix create 创建公共 IP 前缀:

az network public-ip prefix create --length 28 --location <region> --name <publicIPPrefixName> --resource-group <resourceGroup>

查看输出,并注意前缀为 id

{
  ...
  "id": "/subscriptions/<subscription-id>/resourceGroups/<resourceGroup>/providers/Microsoft.Network/publicIPPrefixes/<publicIPPrefixName>",
  ...
}

最后,在创建新群集或添加新的节点池时,使用标志 --node-public-ip-prefix-id 并传入前缀的资源 ID:

az aks create \
    --resource-group <resourceGroup> \
    --name <aksClusterName> \
    --location <region> \
    --enable-node-public-ip \
    --node-public-ip-prefix-id /subscriptions/<subscription-id>/resourceGroups/<resourceGroup>/providers/Microsoft.Network/publicIPPrefixes/<publicIPPrefixName> \
    --generate-ssh-keys

使用双堆栈公共 IP 前缀(预览版)

可以使用双堆栈公共 IP 前缀将 IPv4 和 IPv6 公共 IP 地址分配给节点池中的每个节点。 此方法允许你自带公共 IP 前缀,并确保每个节点接收一个 IPv4 地址和一个 IPv6 地址。

此功能对于需要通过 IPv4 和 IPv6 或运行在需要 IPv6 符合性的环境中运行的应用程序进行直接入站或出站连接的工作负荷非常有用。

重要

AKS 预览功能以自助且需主动选择加入的方式提供。 预览功能是“按现状”和“按可用”提供的,不包括在服务级别协议和有限保证中。 AKS 预览功能是由客户支持尽最大努力部分覆盖。 因此,这些功能并不适合用于生产。 有关详细信息,请参阅以下支持文章:

要求

若要将双堆栈公共 IP 前缀与节点公共 IP 配合使用,请确保满足以下先决条件:

  • 群集配置为具有 IPv4 和 IPv6 IP 系列的双堆栈群集。
  • 群集使用具有覆盖网络的 Azure CNI。
  • 在 AKS 群集所在的同一区域中创建了一个 IPv4 公共 IP 前缀和一个 IPv6 公共 IP 前缀。
  • 这两个公共 IP 前缀都使用标准 SKU。
  • AKS 群集标识有权管理公共 IP 前缀。 如果前缀位于其他资源组中,请将该资源组上的网络参与者角色分配给群集标识。

注册预览功能

适用于节点公共 IP 的双堆栈(IPv4 和 IPv6)公共 IP 前缀支持当前处于预览阶段。 在使用此功能之前,必须先安装或更新Azure CLI扩展并在订阅中注册NodePublicIPv6PrefixPreview功能标志。

安装或更新 aks-preview 扩展:

az extension add --name aks-preview --upgrade

注册所需的预览功能:

az feature register --namespace Microsoft.ContainerService --name NodePublicIPv6PrefixPreview

完成功能注册可能需要几分钟时间。 若要检查注册状态,请运行:

az feature show --namespace Microsoft.ContainerService --name NodePublicIPv6PrefixPreview --query "properties.state"

等待这两个功能均显示为“已注册”状态后,再继续操作。

注册功能标志后,请刷新资源提供程序,以确保更改已生效:

az provider register --namespace Microsoft.ContainerService

注册完成后,可以创建或更新群集,以对节点公共 IP 使用双堆栈公共 IP 前缀。

创建公共 IP 前缀

使用 Azure CLI为 IPv4 和 IPv6 创建公共 IP 前缀。

对于 IPv4:

az network public-ip prefix create \
  --resource-group <resourceGroup> \
  --name <ipv4PrefixName> \
  --location <region> \
  --length 28 \
  --sku Standard \
  --version IPv4

对于 IPv6:

az network public-ip prefix create \
  --resource-group <resourceGroup> \
  --name <ipv6PrefixName> \
  --location <region> \
  --length 124 \
  --sku Standard \
  --version IPv6

创建前缀后,请记下两个前缀的资源 ID。

创建具有双堆栈节点公共 IP 前缀的新群集

创建新的 AKS 群集时,使用 --node-public-ip-prefix-ids 参数同时指定 IPv4 和公共 IP 前缀。

az aks create \
  --resource-group <resourceGroup> \
  --name <aksClusterName> \
  --location <region> \
  --enable-node-public-ip \
  --ip-families IPv4,IPv6 \
  --network-plugin azure \
  --network-plugin-mode overlay \
  --node-public-ip-prefix-ids "<ipv4PrefixResourceId>,<ipv6PrefixResourceId>" \
  --generate-ssh-keys

--node-public-ip-prefix-ids 参数接受以逗号分隔的公共 IP 前缀资源 ID 列表。 该列表必须包含一个 IPv4 前缀和一个 IPv6 前缀。

添加具有双堆栈节点公共 IP 前缀的节点池

还可以将具有双堆栈节点公共 IP 前缀的节点池添加到现有的双堆栈群集。

az aks nodepool add \
  --resource-group <resourceGroup> \
  --cluster-name <aksClusterName> \
  --name <nodePoolName> \
  --enable-node-public-ip \
  --node-public-ip-prefix-ids "<ipv4PrefixResourceId>,<ipv6PrefixResourceId>"

局限性

以下限制适用于双堆栈公共 IP 前缀:

  • 必须同时提供 IPv4 和 IPv6 前缀。 不支持仅 IPv6 配置。
  • 节点公共 IP 配置是不可变的。 若要更改公共 IP 前缀,必须创建新的节点池并迁移工作负载。
  • 为每个节点分配一个 IPv6 公共 IP 地址。
  • AKS 自动或节点自动预配不支持此功能。
  • 不支持多 NIC 节点池。
  • 支持 Cluster Autoscaler,但请确保配置的最大节点数不超过公共 IP 前缀中可用的 IP 地址数量,因为每个节点都需要使用此前缀中的一个 IP 地址。

找到节点的公共 IP

可以通过多种方式找到节点的公共 IP:

重要

节点资源组包含节点及其公共 IP。 执行命令时,使用节点资源组查找节点的公共 IP。

az vmss list-instance-public-ips --resource-group <MC_region_aksClusterName_region> --name <virtualMachineScaleSetName>

在节点公共 IP 上使用公共 IP 标记

可以在节点公共 IP 上使用公共 IP 标记来利用 Azure 路由首选项功能。

要求

  • 需要 AKS 版本 1.29 或更高版本。

使用路由首选项 Internet 创建新群集

az aks create \
    --name <aksClusterName> \
    --location <region> \
    --resource-group <resourceGroup> \
    --enable-node-public-ip \
    --node-public-ip-tags RoutingPreference=Internet \
    --generate-ssh-keys

添加具有路由首选项 Internet 的节点池

az aks nodepool add --cluster-name <aksClusterName> \
  --name <nodePoolName> \
  --location <region> \
  --resource-group <resourceGroup> \
  --enable-node-public-ip \
  --node-public-ip-tags RoutingPreference=Internet

允许主机端口连接并将节点池添加到应用程序安全组

对于利用节点公共 IP 并在其主机地址上托管服务的 AKS 节点,需要为其添加 NSG 规则以允许流量。 在节点池配置中添加所需的端口会在群集网络安全组中创建相应的允许规则。

如果使用自带虚拟网络的群集所在的子网上已配置网络安全组,则必须向该网络安全组添加一条允许规则。 可以通过将该节点池添加到应用程序安全组 (ASG) 中,将此限制为特定节点池中的节点。 如果指定了允许的主机端口,则默认情况下会在托管资源组中创建托管 ASG。 还可以通过在节点池参数中指定 NSG 的资源 ID,将节点添加到一个或多个自定义 ASG。

主机端口规范格式

指定允许的端口列表时,请使用逗号分隔列表,其中包含采用 port/protocolstartPort-endPort/protocol 格式的条目。

示例:

  • 80/tcp
  • 80/tcp,443/tcp
  • 53/udp,80/tcp
  • 50000-60000/tcp

要求

  • 需要 AKS 版本 1.29 或更高版本。

使用允许的端口和应用程序安全组创建新群集

az aks create \
    --resource-group <resourceGroup> \
    --name <aksClusterName> \
    --nodepool-name <nodePoolName> \
    --nodepool-allowed-host-ports 80/tcp,443/tcp,53/udp,40000-60000/tcp,40000-50000/udp\
    --nodepool-asg-ids "<asgId>,<asgId>" \
    --generate-ssh-keys

添加具有允许的端口和应用程序安全组的新节点池

az aks nodepool add \
  --resource-group <resourceGroup> \
  --cluster-name <aksClusterName> \
  --name <nodePoolName> \
  --allowed-host-ports 80/tcp,443/tcp,53/udp,40000-60000/tcp,40000-50000/udp \
  --asg-ids "<asgId>,<asgId>"

更新节点池允许的端口和应用程序安全组

az aks nodepool update \
  --resource-group <resourceGroup> \
  --cluster-name <aksClusterName> \
  --name <nodePoolName> \
  --allowed-host-ports 80/tcp,443/tcp,53/udp,40000-60000/tcp,40000-50000/udp \
  --asg-ids "<asgId>,<asgId>"

为 Pod 工作负载自动分配主机端口(预览版)

在节点上配置公共 IP 时,可以利用主机端口允许 Pod 直接接收流量,而无需配置负载均衡器服务。 这在游戏等场景中特别有用,在这些场景中,节点 IP 和端口的临时性质不成问题,因为已知主机名中的配对服务可以提供要在连接时使用的正确主机和端口。 但是,由于主机上只有一个进程可以侦听同一端口,因此将应用程序与主机端口配合使用可能会导致计划出现问题。 为了避免此问题,AKS 允许系统在计划时动态分配可用端口,从而防止冲突。

警告

群集上设置的默认 NSG 规则会阻止 Pod 主机端口流量。 此功能应与在节点池上允许使用主机端口结合使用,以使流量能够通过。

重要

AKS 预览功能以自助且需主动选择加入的方式提供。 预览功能是“按现状”和“按可用”提供的,不包括在服务级别协议和有限保证中。 AKS 预览功能是由客户支持尽最大努力部分覆盖。 因此,这些功能并不适合用于生产。 有关详细信息,请参阅以下支持文章:

要求

  • 需要 AKS 版本 1.29 或更高版本。

注册“PodHostPortAutoAssignPreview”功能标志

使用 PodHostPortAutoAssignPreview 命令注册 功能标志,如以下示例所示:

az feature register --namespace "Microsoft.ContainerService" --name "PodHostPortAutoAssignPreview"

状态需要几分钟才会显示为已注册。 使用 az feature show 命令验证注册状态:

az feature show --namespace "Microsoft.ContainerService" --name "PodHostPortAutoAssignPreview"

当状态反映为“已注册”时,使用 az provider register 命令刷新 Microsoft.ContainerService 资源提供程序的注册:

az provider register --namespace Microsoft.ContainerService

自动为 Pod 分配主机端口

触发主机端口自动分配的方法是:部署一个未指定任何主机端口的工作负载,并添加 kubernetes.azure.com/assign-hostports-for-containerports 注解,其中包含需要分配主机端口的端口列表。 该注释的值应指定为逗号分隔的条目列表,例如 port/protocol,其中 port 是 Pod 规范中定义的单个端口号,protocol 为 tcpudp

端口将从范围 40000-59999 分配,并且在整个群集中是唯一的。 分配的端口还将添加到 Pod 内的环境变量中,以便应用程序可以确定分配了哪些端口。 环境变量名称将采用以下格式(示例如下):<deployment name>_PORT_<port number>_<protocol>_HOSTPORT,例如 mydeployment_PORT_8080_TCP_HOSTPORT: 41932

下面是一个示例 echoserver 部署,显示了端口 8080 和 8443 的主机端口映射:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: echoserver-hostport
  labels:
    app: echoserver-hostport
spec:
  replicas: 3
  selector:
    matchLabels:
      app: echoserver-hostport
  template:
    metadata:
      annotations:
        kubernetes.azure.com/assign-hostports-for-containerports: 8080/tcp,8443/tcp
      labels:
        app: echoserver-hostport
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: echoserver-hostport
          image: k8sgcr.azk8s.cn/echoserver:1.10
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
            - name: https
              containerPort: 8443
              protocol: TCP

应用该部署时,hostPort 条目将出现在各个 Pod 的 YAML 中:

$ kubectl describe pod echoserver-hostport-75dc8d8855-4gjfc
<cut for brevity>
Containers:
  echoserver-hostport:
    Container ID:   containerd://d0b75198afe0612091f412ee7cf7473f26c80660143a96b459b3e699ebaee54c
    Image:          k8sgcr.azk8s.cn/echoserver:1.10
    Image ID:       k8sgcr.azk8s.cn/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229                                                                                                      Ports:          8080/TCP, 8443/TCP
    Host Ports:     46645/TCP, 49482/TCP
    State:          Running
      Started:      Thu, 12 Jan 2023 18:02:50 +0000
    Ready:          True
    Restart Count:  0
    Environment:
      echoserver-hostport_PORT_8443_TCP_HOSTPORT:  49482
      echoserver-hostport_PORT_8080_TCP_HOSTPORT:  46645

后续步骤