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

AKS 节点无需使用自身的公共 IP 地址进行通信。 但某些方案可能需要节点池中的节点收到专用公共 IP 地址。 游戏工作负载就是一种常见方案,此时控制台需要直接连接到云虚拟机才能尽量减少画面跳跃。 可通过使用节点公共 IP 在 AKS 上实现此方案。

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

az group create --name myResourceGroup2 --location chinaeast2

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

az aks create \
    --resource-group MyResourceGroup2 \
    --name MyManagedCluster \
    --location eastus \
    --enable-node-public-ip \
    --generate-ssh-keys

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

az aks nodepool add --resource-group MyResourceGroup2 --cluster-name MyManagedCluster --name nodepool2 --enable-node-public-ip

使用公共 IP 前缀

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

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

az network public-ip prefix create --length 28 --location chinaeast2 --name MyPublicIPPrefix --resource-group MyResourceGroup3

查看输出,并记下前缀的 id

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

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

az aks create \
    --resource-group MyResourceGroup3 \
    --name MyManagedCluster \
    --location eastus \
    --enable-node-public-ip \
    --node-public-ip-prefix /subscriptions/<subscription-id>/resourcegroups/MyResourceGroup3/providers/Microsoft.Network/publicIPPrefixes/MyPublicIPPrefix \
    --generate-ssh-keys

找到节点的公共 IP

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

重要

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

az vmss list-instance-public-ips --resource-group MC_MyResourceGroup2_MyManagedCluster_chinaeast2 --name YourVirtualMachineScaleSetName

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

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

要求

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

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

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

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

az aks nodepool add --cluster-name <clusterName> --name <nodepoolName> --location <location> --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.24 或更高版本。

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

az aks create \
    --resource-group <resourceGroup> \
    --name <clusterName> \
    --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

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

  --resource-group <resourceGroup> \
  --cluster-name <clusterName> \
  --name <nodepoolName> \
  --allowed-host-ports 80/tcp,443/tcp,53/udp,40000-60000/tcp,40000-50000/udp \
  --asg-ids "<asgId>,<asgId>"

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

  --resource-group <resourceGroup> \
  --cluster-name <clusterName> \
  --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.24 或更高版本。

注册“PodHostPortAutoAssignPreview”功能标志

使用 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

后续步骤