在 Azure Kubernetes 服务 (AKS) 中使用公共标准负载均衡器

Azure 负载均衡器在开放式系统互连 (OSI) 模型的第 4 层运行,支持入站和出站方案。 它将抵达负载均衡器前端的入站流量分配到后端池实例。

与 AKS 集成的公共负载均衡器有两个用途:

  1. 通过将专用 IP 地址转换为其出站池的公共 IP 地址部分,为 AKS 虚拟网络中的群集节点提供出站连接。
  2. 通过 LoadBalancer 类型的 Kubernetes 服务提供对应用程序的访问,使你能够轻松缩放应用程序并创建高度可用的服务。

仅允许专用 IP 作为前端时才使用内部(或专用)负载均衡器。 内部负载均衡器用于对虚拟网络内部的流量进行负载均衡。 负载均衡器前端还可在混合场景中从本地网络进行访问。

本文介绍与 AKS 上的公共负载均衡器的集成。 如需了解内部负载均衡器集成,请参阅使用 AKS 中的内部负载均衡器

准备阶段

  • Azure 负载均衡器以两种 SKU 提供:“基本”和“标准”。 默认情况下,创建 AKS 群集时将使用标准 SKU。 使用“标准”SKU 可以访问添加的功能(例如更大的后端池、多个节点池可用性区域),并且默认是安全的。 这是推荐的 AKS 的负载均衡器 SKU。 有关基本与标准 SKU 的详细信息,请参阅 Azure 负载均衡器 SKU 比较
  • 本文假设已有一个 AKS 群集,其中包含标准 SKU Azure 负载均衡器。 如果需要 AKS 群集,可以使用 Azure CLIAzure PowerShellAzure 门户创建一个。
  • AKS 管理代理节点的生命周期和操作。 不支持修改与代理节点关联的 IaaS 资源。 不支持的操作示例是对负载均衡器资源组进行手动更改。

重要

如果更愿意使用自己的网关、防火墙或代理提供出站连接,则可以使用出站类型作为 UserDefinedRouting (UDR),跳过创建负载均衡器出站池和相应的前端 IP。 出站类型定义群集的出口方法,它默认为 LoadBalancer 类型。

使用公共标准负载均衡器

创建出站类型为 LoadBalancer(默认)的 AKS 群集后,群集可以使用负载均衡器公开服务。

创建名为 public-svc.yaml 的服务清单,用于创建类型为 LoadBalancer 的公共服务。

apiVersion: v1
kind: Service
metadata:
  name: public-svc
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: public-app

指定负载均衡器 IP 地址

如果要将特定 IP 地址与负载均衡器配合使用,有两种方法:

重要

将 LoadBalancerIP 属性添加到负载均衡器 YAML 清单将弃用以下上游 Kubernetes。 虽然当前使用情况保持不变,并且现有服务无需修改即可正常工作,但我们强烈建议改为设置服务注释。

  • 设置服务注释:将 service.beta.kubernetes.io/azure-load-balancer-ipv4service.beta.kubernetes.io/azure-load-balancer-ipv6 分别用于 IPv4 地址和 IPv6 地址。
  • 将 LoadBalancerIP 属性添加到负载均衡器 YAML 清单:将 Service.Spec.LoadBalancerIP 属性添加到负载均衡器 YAML 清单。 此字段正在弃用以下上游 Kubernetes,并且它不能支持双堆栈。 当前使用情况保持不变,现有服务无需修改即可正常工作。

部署服务清单

使用 kubectl apply 部署公共服务清单,并指定 YAML 清单的名称。

kubectl apply -f public-svc.yaml

Azure 负载均衡器配置有一个面向新服务的新公共 IP。 由于 Azure 负载均衡器可以有多个前端 IP,因此部署的每个新服务都会获得唯一的专用前端 IP。

使用以下命令确认是否创建了服务并配置了负载均衡器。

kubectl get service public-svc
NAMESPACE     NAME          TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)         AGE
default       public-svc    LoadBalancer   10.0.39.110    52.156.88.187   80:32068/TCP    52s

查看服务详细信息时,为负载均衡器上的该服务创建的公共 IP 地址显示在“EXTERNAL-IP”列中。 将 IP 地址从 <待定> 更改为实际公共 IP 地址可能需要几分钟时间

有关服务的更多详细信息,请使用以下命令。

kubectl describe service public-svc

以下示例输出是运行 kubectl describe service 后的精简版输出。 LoadBalancer 入口显示服务公开的外部 IP 地址。 IP 显示内部地址。

Name:                        public-svc
Namespace:                   default
Labels:                      <none>
Annotations:                 <none>
Selector:                    app=public-app
...
IP:                          10.0.39.110
...
LoadBalancer Ingress:        52.156.88.187
...
TargetPort:                  80/TCP
NodePort:                    32068/TCP
...
Session Affinity:            None
External Traffic Policy:     Cluster
...

配置公共标准负载均衡器

可以在创建群集时或通过更新群集来自定义标准公共负载均衡器的不同设置。 通过这些自定义选项,可以创建满足工作负载需求的负载均衡器。 使用标准负载均衡器,你可以执行以下操作:

  • 设置或缩放受管理出站 IP 的数量。
  • 自带自定义出站 IP 或出站 IP 前缀
  • 自定义分配给群集上每个节点的出站端口数。
  • 为空闲连接配置超时设置。

重要

在给定时间只能使用一个出站 IP 选项(托管 IP、自带 IP 或 IP 前缀)。

更改入站池类型

在负载均衡器后端池中,可以通过 AKS 节点的 IP 配置(基于 Azure 虚拟机规模集的成员身份)或者仅通过其 IP 地址来引用这些节点。 在更新服务和预配负载均衡器时,利用基于 IP 地址的后端池成员身份可以提高效率,尤其是在节点数量较高的情况下。 现在支持使用基于 IP 的后端池预配新群集,还支持转换现有群集。 与 NAT 网关或用户定义的路由出口类型结合使用时,新节点和服务的预配将更加高效。

提供了两种不同的池成员身份类型:

  • nodeIPConfiguration–旧版虚拟机规模集基于 IP 配置的池成员身份类型
  • nodeIP - 基于 IP 的成员身份类型

要求

  • AKS 群集的版本必须为 1.23 或更高版本。
  • AKS 群集必须使用标准负载均衡器和虚拟机规模集。

限制

  • 使用基于 IP 的后端池的群集限制为 2500 个节点。

使用基于 IP 的入站池成员身份创建新的 AKS 群集

az aks create \
    --resource-group myResourceGroup \
    --name myAKSCluster \
    --load-balancer-backend-pool-type=nodeIP

更新现有的 AKS 群集以使用基于 IP 的入站池成员身份

警告

此操作会导致群集中的传入服务流量暂时中断。 对于具有许多节点的较大群集,影响时间会增加。

az aks update \
    --resource-group myResourceGroup \
    --name myAKSCluster \
    --load-balancer-backend-pool-type=nodeIP

缩放受管理出站公共 IP 的数量

Azure 负载均衡器还提供源自虚拟网络的出站和入站连接。 使用出站规则可以方便地配置公共标准负载均衡器的出站网络地址转换。

出站规则遵循与负载均衡和入站 NAT 规则相同的语法:

前端 IP + 参数 + 后端池

出站规则为后端池识别的、要转换为前端的所有虚拟机配置出站 NAT。 参数针对出站 NAT 算法提供更大的控制度。

虽然可以将出站规则与单个公共 IP 地址配合使用,但出站规则非常适合缩放出站 NAT,因为它们减轻了配置负担。 可以使用多个 IP 地址规划大规模方案,并可以使用出站规则来缓解容易出现 SNAT 耗尽的模式。 前端提供的每个 IP 地址可提供 64,000 个临时端口,供负载均衡器用作 SNAT 端口。

使用具有(默认创建的)托管出站公共 IP 的标准 SKU 负载均衡器时,可以使用 --load-balancer-managed-outbound-ip-count 参数缩放托管出站公共 IP 的数量。

使用以下命令更新现有群集。 还可以将此参数设置为具有多个托管出站公共 IP。

重要

不建议使用 Azure 门户进行任何出站规则更改。 进行这些更改时,应浏览 AKS 群集,而不是直接访问负载均衡器资源。

每当协调群集时(例如停止、启动、升级或缩放群集时),会删除对负载均衡器资源直接作出的出站规则更改。

使用 Azure CLI,如示例所示。 使用 az aks CLI 命令进行的出站规则更改在群集停机期间是永久性的。

有关详细信息,请参阅 Azure 负载均衡器出站规则

az aks update \
    --resource-group myResourceGroup \
    --name myAKSCluster \
    --load-balancer-managed-outbound-ip-count 2

以上示例将 myResourceGroupmyAKSCluster 群集的托管出站公共 IP 数量设置为 2

在创建群集时,还可以通过追加 --load-balancer-managed-outbound-ip-count 参数并将其设置为所需的值来设置托管出站公共 IP 的初始数量。 托管出站公共 IP 的默认数量为 1。

提供自己的出站公共 IP 或前缀

使用标准 SKU 负载均衡器时,默认情况下,AKS 群集会自动在 AKS 管理的基础结构资源组中创建公共 IP 并将其分配给负载均衡器出站池。

AKS 创建的公共 IP 是 AKS 托管的资源,这意味着 AKS 管理该公共 IP 的生命周期,且不需要用户直接对公共 IP 资源执行操作。 或者,你可以在群集创建时分配自己的自定义公共 IP 或公共 IP 前缀。 还可以在现有群集的负载均衡器属性上更新自定义 IP。

使用自己的公共 IP 或前缀的要求包括:

  • 用户必须创建并拥有自定义公共 IP 地址。 由 AKS 创建的托管公共 IP 地址不能重新用于“自带的自定义 IP”,因为它可能会导致管理冲突。
  • 必须根据所需的公共 IP 权限列表,确保 AKS 群集标识(服务主体或托管标识)有权访问出站 IP。
  • 确保满足配置出站 IP 或出站 IP 前缀所需的先决条件和限制

使用自己的出站公共 IP 更新群集

使用 az network public-ip show 命令列出公共 IP 的 ID。

az network public-ip show --resource-group myResourceGroup --name myPublicIP --query id -o tsv

以上命令显示 myResourceGroup 资源组中 myPublicIP 公共 IP 的 ID。

az aks update 命令与 load-balancer-outbound-ips 参数一起使用,以使用公共 IP 更新群集。

以下示例结合前一命令返回的 ID 使用 load-balancer-outbound-ips 参数。

az aks update \
    --resource-group myResourceGroup \
    --name myAKSCluster \
    --load-balancer-outbound-ips <publicIpId1>,<publicIpId2>

使用自己的出站公共 IP 前缀更新群集

你也可以将出口的公共 IP 前缀与标准 SKU 负载均衡器配合使用。 以下示例使用 az network public-ip prefix show 命令列出公共 IP 前缀的 ID。

az network public-ip prefix show --resource-group myResourceGroup --name myPublicIPPrefix --query id -o tsv

以上命令显示 myResourceGroup 资源组中 myPublicIPPrefix 公共 IP 前缀的 ID。

以下示例将 load-balancer-outbound-ip-prefixes 参数与前一命令返回的 ID 配合使用。

az aks update \
    --resource-group myResourceGroup \
    --name myAKSCluster \
    --load-balancer-outbound-ip-prefixes <publicIpPrefixId1>,<publicIpPrefixId2>

使用自己的公共 IP 或前缀创建群集

在创建群集时可以为出口提供自己的 IP 地址或 IP 前缀,以支持将出口终结点添加到允许列表这样的方案。 若要在创建群集时定义自己的公共 IP 和 IP 前缀,请追加上一命令中显示的相同参数。

az aks create 命令与 load-balancer-outbound-ips 参数配合使用,以使用自己的公共 IP 创建新群集。

az aks create \
    --resource-group myResourceGroup \
    --name myAKSCluster \
    --load-balancer-outbound-ips <publicIpId1>,<publicIpId2>

az aks create 命令与 load-balancer-outbound-ip-prefixes 参数配合使用,以使用自己的公共 IP 前缀创建新群集。

az aks create \
    --resource-group myResourceGroup \
    --load-balancer-outbound-ip-prefixes <publicIpPrefixId1>,<publicIpPrefixId2>

配置分配的出站端口

重要

如果群集上的应用程序可以与小型目标集(例如连接到数据库的前端应用程序的多个实例)建立大量连接,则可能会遇到易于出现 SNAT 端口耗尽的情况。 当一个应用程序用完用于建立与另一个应用程序或主机的连接的出站端口时,就会发生 SNAT 端口耗尽。 如果你有容易遇到 SNAT 端口耗尽的情况,我们强烈建议你在负载均衡器上增加分配的出站端口和出站前端 IP。

有关 SNAT 的详细信息,请参阅将 SNAT 用于出站连接

默认情况下,AKS 将其负载均衡器上的 AllocatedOutboundPorts 设置为 0,这样一来就可以在创建群集时根据后端池大小启用自动出站端口分配。 例如,如果群集有 50 个或更少的节点,则向每个节点分配 1024 个端口。 随着群集中节点数的增加,每个节点可用的端口将减少。

重要

无论在节点大小不大于 50 (1-50) 时是否添加前端 IP,都存在 1024 个端口的硬限制。

若要显示 AKS 群集负载均衡器的 AllocatedOutboundPorts 值,请使用 az network lb outbound-rule list

NODE_RG=$(az aks show --resource-group myResourceGroup --name myAKSCluster --query nodeResourceGroup -o tsv)
az network lb outbound-rule list --resource-group $NODE_RG --lb-name kubernetes -o table

以下示例输出显示了已为群集启用基于后端池大小的自动出站端口分配。

AllocatedOutboundPorts    EnableTcpReset    IdleTimeoutInMinutes    Name             Protocol    ProvisioningState    ResourceGroup
------------------------  ----------------  ----------------------  ---------------  ----------  -------------------  -------------
0                         True              30                      aksOutboundRule  All         Succeeded            MC_myResourceGroup_myAKSCluster_chinaeast2  

若要在创建或更新群集时配置 AllocatedOutboundPorts 和出站 IP 地址的特定值,请使用 load-balancer-outbound-ports 以及 load-balancer-managed-outbound-ip-countload-balancer-outbound-ipsload-balancer-outbound-ip-prefixes。 为出站端口或出站 IP 地址设置特定值或增加现有值之前,必须计算出站端口和 IP 地址的适当数量。 使用以下公式将此计算舍入为最接近的整数:64,000 ports per IP / <outbound ports per node> * <number of outbound IPs> = <maximum number of nodes in the cluster>

计算出站端口和 IP 数并设置值时,请记住以下信息:

  • 根据你设置的值,每个节点的出站端口数为固定值。
  • 出站端口数的值必须是 8 的倍数。
  • 添加更多 IP 不会将更多端口添加到任何节点,但会为群集中的更多节点提供容量。
  • 必须将升级过程中可能添加的节点考虑在内,包括通过 maxSurge 值指定的节点计数。

以下示例显示了你所设置的值会如何影响出站端口和 IP 地址的数量:

  • 如果使用默认值,并且群集有 48 个节点,则每个节点有 1024 个可用端口。
  • 如果使用默认值,并且群集的节点从 48 个增加到 52 个,则每个节点都会从 1024 个可用端口更新为 512 个可用端口。
  • 如果出站端口数设置为 1,000 并且出站 IP 数设置为 2,则群集最多可以支持 128 个节点:64,000 ports per IP / 1,000 ports per node * 2 IPs = 128 nodes
  • 如果出站端口数设置为 1,000 并且出站 IP 数设置为 7,则群集最多可以支持 448 个节点:64,000 ports per IP / 1,000 ports per node * 7 IPs = 448 nodes
  • 如果出站端口数设置为 4,000 并且出站 IP 数设置为 2,则群集最多可以支持 32 个节点:64,000 ports per IP / 4,000 ports per node * 2 IPs = 32 nodes
  • 如果出站端口数设置为 4,000 并且出站 IP 数设置为 7,则群集最多可以支持 112 个节点:64,000 ports per IP / 4,000 ports per node * 7 IPs = 112 nodes

重要

计算出站端口和 IP 的数量后,验证是否有额外的出站端口容量可在升级过程中处理节点激增。 请务必为升级和其他操作所需的其他节点分配足够多的额外端口。 AKS 默认为一个用于升级操作的缓冲区节点。 如果使用 maxSurge 值,请将每个节点的出站端口数乘以 maxSurge 值,以确定所需的端口数。 例如,如果计算出每个节点需要 4000 个端口,并且在群集上有 7 个 IP 地址,最大节点数为 100 个,最大激增数为 2:

  • 2 个激增节点 * 每个节点 4000 个端口 = 升级过程中节点激增需要 8000 个端口。
  • 100 个节点 * 每个节点 4000 个端口 = 群集需要 400,000 个端口。
  • 7 个 IP * 每个 IP 64000 个端口 = 448,000 个端口可用于群集。

上面的示例显示群集的容量超过 48,000 个端口,足以处理升级期间节点激增所需的 8000 个端口。

计算并验证这些值后,可以在创建或更新集群时使用 load-balancer-outbound-ports 以及 load-balancer-managed-outbound-ip-countload-balancer-outbound-ipsload-balancer-outbound-ip-prefixes 来应用这些值。

az aks update \
    --resource-group myResourceGroup \
    --name myAKSCluster \
    --load-balancer-managed-outbound-ip-count 7 \
    --load-balancer-outbound-ports 4000

配置负载均衡器的空闲超时

如果 SNAT 端口资源已经耗尽,那么在现有流释放 SNAT 端口之前出站流会失败。 当流关闭时,负载均衡器将回收 SNAT 端口,AKS 配置的负载均衡器将使用 30 分钟空闲超时回收空闲流中的 SNAT 端口。

还可以使用传输(例如 TCP keepalivesapplication-layer keepalives)刷新空闲流,并在必要时重置此空闲超时。 可以按照以下示例配置此超时。

az aks update \
    --resource-group myResourceGroup \
    --name myAKSCluster \
    --load-balancer-idle-timeout 4

如果你希望具有许多短生存期的连接,而不想有长生存期且可能有长时间空闲的连接(例如使用 kubectl proxykubectl port-forward),请考虑使用低超时值(如 4 分钟)。 使用 TCP keepalive 时,在连接的一端启用它们就足够了。 例如,若要重置流的空闲计时器,在服务器端启用这些连接就足够了。 没有必要在两端都启动 TCP keepalive。 应用程序层(包括数据库客户端-服务器配置)也存在类似的概念。 检查服务器端对于特定于应用程序的 keepalive 存在哪些选项。

重要

默认情况下,AKS 会启用空闲时 TCP 重置。 我们建议保留此配置,并利用它在方案中实现可预测性更高的应用程序行为。

只有在 TCP 连接的状态为“已建立”时才会发送 TCP RST。 在此处阅读详细信息。

IdleTimeoutInMinutes 设置为与默认值 30 分钟不同的值时,请考虑你的工作负载需要使用出站连接多长时间。 还要考虑到,对于在 AKS 外部使用的标准 SKU 负载均衡器,默认超时值为 4 分钟。 如果 idletimeoutminutes 值较准确地反映你的具体 AKS 工作负载,则有助于降低由于绑定不再使用的连接而导致的 SNAT 耗尽。

警告

更改 AllocatedOutboundPorts 和 IdleTimeoutInMinutes 的值可能会明显改变负载均衡器的出站规则的行为,因此请不要轻易更改。 在更新这些值之前,请查看 SNAT 故障排除部分,并查看负载均衡器出站规则Azure 中的出站连接,以充分了解你的更改造成的影响。

将入站流量限制为特定 IP 范围

以下清单使用 loadBalancerSourceRanges 为入站外部流量指定新的 IP 范围。

apiVersion: v1
kind: Service
metadata:
  name: azure-vote-front
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: azure-vote-front
  loadBalancerSourceRanges:
  - MY_EXTERNAL_IP_RANGE

此示例将规则更新为仅允许 MY_EXTERNAL_IP_RANGE 范围内的入站外部流量。 如果将 MY_EXTERNAL_IP_RANGE 替换为内部子网 IP 地址,则流量将限制为仅群集内部 IP。 如果流量限制为群集内部 IP,则 Kubernetes 群集外部的客户端无法访问负载均衡器。

注意

  • 入站、外部流量从负载均衡器流向 AKS 群集的虚拟网络。 该虚拟网络有一个网络安全组 (NSG),该安全组允许来自负载均衡器的所有入站流量。 此 NSG 使用 LoadBalancer 类型的服务标记允许来自负载均衡器的流量。
  • 如果有 Pod 需要针对 v1.25 或更高版本的群集访问服务的 LoadBalancer IP,则应将 Pod CIDR 添加到 loadBalancerSourceRanges。

维护入站连接上的客户端 IP

默认情况下,在 Kubernetes 和 AKS 中,LoadBalancer 类型的服务在连接到 Pod 时不会持久保留客户端的 IP 地址。 传递到 Pod 的数据包上的源 IP 会成为节点的专用 IP。 若要保留客户端的 IP 地址,必须在服务定义中将 service.spec.externalTrafficPolicy 设置为 local。 以下清单显示了一个示例。

apiVersion: v1
kind: Service
metadata:
  name: azure-vote-front
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports:
  - port: 80
  selector:
    app: azure-vote-front

通过 Kubernetes 注释进行自定义

类型为 LoadBalancer 的 Kubernetes 服务支持以下批注,这些批注仅适用于 INBOUND 流。

Annotation Value 说明
service.beta.kubernetes.io/azure-load-balancer-internal truefalse 指定负载均衡器是否应为“内部”。 如果未设置,则默认为公共。
service.beta.kubernetes.io/azure-load-balancer-internal-subnet 子网的名称 指定内部负载均衡器应绑定到的子网。 如果未设置,则默认为云配置文件中配置的子网。
service.beta.kubernetes.io/azure-dns-label-name 公共 IP 上的 DNS 标签的名称 指定公共服务的 DNS 标签的名称。 如果设置为空字符串,则不会使用公共 IP 中的 DNS 条目。
service.beta.kubernetes.io/azure-shared-securityrule truefalse 利用网络安全组中的 Azure 增强安全规则,指定通过潜在共享的 Azure 安全规则公开服务,以提高服务的公开程度。
service.beta.kubernetes.io/azure-load-balancer-resource-group 资源组的名称 指定与群集基础结构(节点资源组)不在同一资源组中的负载均衡器公共 IP 的资源组。
service.beta.kubernetes.io/azure-allowed-service-tags 允许的服务标记列表 指定以逗号隔开的允许服务标记的列表。
service.beta.kubernetes.io/azure-load-balancer-tcp-idle-timeout TCP 空闲超时(以分钟为单位) 指定 TCP 连接空闲超时在负载均衡器上发生的时间(以分钟为单位)。 默认值和最小值为 4。 最大值为 30。 该值必须为整数。
service.beta.kubernetes.io/azure-load-balancer-disable-tcp-reset truefalse 指定负载均衡器是否应在达到空闲超时时禁用 TCP 重置。
service.beta.kubernetes.io/azure-load-balancer-ipv4 IPv4 地址 指定要分配给负载均衡器的 IPv4 地址。
service.beta.kubernetes.io/azure-load-balancer-ipv6 IPv6 地址 指定要分配给负载均衡器的 IPv6 地址。

自定义负载均衡器运行状况探测

Annotation Value 说明
service.beta.kubernetes.io/azure-load-balancer-health-probe-interval 运行状况探测间隔
service.beta.kubernetes.io/azure-load-balancer-health-probe-num-of-probe 运行状况探测的最小不正常响应数
service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path 运行状况探测的请求路径
service.beta.kubernetes.io/port_{port}_no_lb_rule true/false {port} 是服务端口号。 如果设置为 true,则不会生成此端口的 lb 规则或运行状况探测规则。 运行状况检查服务不应公开到公共 Internet(例如 istio/envoy 运行状况检查服务)
service.beta.kubernetes.io/port_{port}_no_probe_rule true/false {port} 是服务端口号。 如果设置为 true,则不会生成此端口的运行状况探测规则。
service.beta.kubernetes.io/port_{port}_health-probe_protocol 运行状况探测协议 {port} 是服务端口号。 服务端口 {port} 的运行状况探测的显式协议,如果设置将替代 port.appProtocol。
service.beta.kubernetes.io/port_{port}_health-probe_port 服务清单中的端口号或端口名 {port} 是服务端口号。 服务端口 {port} 的运行状况探测的显式端口,将替代默认值。
service.beta.kubernetes.io/port_{port}_health-probe_interval 运行状况探测间隔 {port} 是服务端口号。
service.beta.kubernetes.io/port_{port}_health-probe_num-of-probe 运行状况探测的最小不正常响应数 {port} 是服务端口号。
service.beta.kubernetes.io/port_{port}_health-probe_request-path 运行状况探测的请求路径 {port} 是服务端口号。

此处所述,Tcp、Http 和 Https 是负载均衡器服务支持的三种协议。

目前,运行状况探测的默认协议因传输协议、应用协议、注释和外部流量策略的不同服务而异。

  1. 对于本地服务,将使用 HTTP 和 /healthz。 运行状况探测将查询 NodeHealthPort,而不是实际的后端服务
  2. 对于群集 TCP 服务,将使用 TCP。
  3. 对于群集 UDP 服务,无运行状况探测。

注意

对于启用了 PLS 集成和 PLS 代理协议的本地服务,默认 HTTP+/healthz 运行状况探测不可用。 因此,可以使用与群集服务相同的方式自定义运行状况探测以支持此场景。

自 v1.20 起,引入了服务注释 service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path 来确定运行状况探测行为。

  • 对于 <=1.23 的群集,spec.ports.appProtocol 仅在设置 service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path 时用作探测协议。
  • 对于 >1.24 的群集,spec.ports.appProtocol 将用作探测协议,/ 将用作默认探测请求路径(service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path 可用于更改为其他请求路径)。

请注意,使用 TCP 或 spec.ports.appProtocol 为空时,将忽略请求路径。 更具体说来:

loadbalancer sku externalTrafficPolicy spec.ports.Protocol spec.ports.AppProtocol service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path LB 探测协议 LB 探测请求路径
standard local 任意 任意 any http /healthz
standard cluster _udp any any null
standard cluster tcp (已忽略) tcp null
standard cluster tcp tcp (已忽略) tcp null
standard cluster tcp http/https TCP(<=1.23) 或 http/https(>=1.24) null(<=1.23) 或 /(>=1.24)
standard cluster tcp http/https /custom-path http/https /custom-path
standard cluster tcp 协议不受支持 /custom-path tcp null
基本 local 任意 任意 any http /healthz
基本 cluster tcp (已忽略) tcp null
基本 cluster tcp tcp (已忽略) tcp null
基本 cluster tcp http TCP(<=1.23) 或 http/https(>=1.24) null(<=1.23) 或 /(>=1.24)
基本 cluster tcp http /custom-path http /custom-path
基本 cluster tcp 协议不受支持 /custom-path tcp null

自 v1.21 起,引入了两个服务注释 service.beta.kubernetes.io/azure-load-balancer-health-probe-intervalload-balancer-health-probe-num-of-probe,用于自定义运行状况探测的配置。 如果未设置 service.beta.kubernetes.io/azure-load-balancer-health-probe-interval,则应用默认值 5。 如果未设置 load-balancer-health-probe-num-of-probe,则应用默认值 2。 总探测应小于 120 秒。

端口的自定义负载均衡器运行状况探测

服务中的不同端口可能需要不同的运行状况探测配置。 这可能是由于服务设计(例如控制多个端口的单个运行状况终结点)或 Kubernetes 功能(例如 MixedProtocolLBService)所致。

以下注释可用于自定义每个服务端口的探测配置。

端口特定注释 全局探测注释 使用情况
service.beta.kubernetes.io/port_{port}_no_lb_rule 不适用(全局无等效项) 如果设置为 true,则不会生成 LB 规则和探测规则
service.beta.kubernetes.io/port_{port}_no_probe_rule 不适用(全局无等效项) 如果设置为 true,则不会生成探测规则
service.beta.kubernetes.io/port_{port}_health-probe_protocol 不适用(全局无等效项) 设置此服务端口的运行状况探测协议(例如 Http、Https、Tcp)
service.beta.kubernetes.io/port_{port}_health-probe_port 不适用(全局无等效项) 设置此服务端口的运行状况探测端口(例如 15021)
service.beta.kubernetes.io/port_{port}_health-probe_request-path service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path 对于 Http 或 Https,设置运行状况探测请求路径。 默认值为 /
service.beta.kubernetes.io/port_{port}_health-probe_num-of-probe service.beta.kubernetes.io/azure-load-balancer-health-probe-num-of-probe 在将端口视为不正常之前的连续探测失败次数
service.beta.kubernetes.io/port_{port}_health-probe_interval service.beta.kubernetes.io/azure-load-balancer-health-probe-interval 探测尝试之间的时间长短

对于以下清单,端口 httpsserver 的探测规则不同于 httpserver 的探测规则,因为指定了端口 httpsserver 的注释。

apiVersion: v1
kind: Service
metadata:
  name: appservice
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-health-probe-num-of-probe: "5"
    service.beta.kubernetes.io/port_443_health-probe_num-of-probe: "4"
spec:
  type: LoadBalancer
  selector:
    app: server
  ports:
    - name: httpserver
      protocol: TCP
      port: 80
      targetPort: 30102
    - name: httpsserver
      protocol: TCP
      appProtocol: HTTPS
      port: 443
      targetPort: 30104

在以下清单中,https 端口使用不同的节点端口,即 /healthz(kube-proxy 的 healthz 终结点)上端口 10256 处的 HTTP 就绪情况检查。

apiVersion: v1
kind: Service
metadata:
  name: istio
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: "true"
    service.beta.kubernetes.io/port_443_health-probe_protocol: "http"
    service.beta.kubernetes.io/port_443_health-probe_port: "10256"
    service.beta.kubernetes.io/port_443_health-probe_request-path: "/healthz"
spec:
  ports:
    - name: https
      protocol: TCP
      port: 443
      targetPort: 8443
      nodePort: 30104
      appProtocol: https
  selector:
    app: istio-ingressgateway
    gateway: istio-ingressgateway
    istio: ingressgateway
  type: LoadBalancer
  sessionAffinity: None
  externalTrafficPolicy: Local
  ipFamilies:
    - IPv4
  ipFamilyPolicy: SingleStack
  allocateLoadBalancerNodePorts: true
  internalTrafficPolicy: Cluster

在以下清单中,https 端口使用不同的运行状况探测终结点,即 /healthz/ready 上端口 30000 处的 HTTP 就绪情况检查。

apiVersion: v1
kind: Service
metadata:
  name: istio
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: "true"
    service.beta.kubernetes.io/port_443_health-probe_protocol: "http"
    service.beta.kubernetes.io/port_443_health-probe_port: "30000"
    service.beta.kubernetes.io/port_443_health-probe_request-path: "/healthz/ready"
spec:
  ports:
    - name: https
      protocol: TCP
      port: 443
      targetPort: 8443
      appProtocol: https
  selector:
    app: istio-ingressgateway
    gateway: istio-ingressgateway
    istio: ingressgateway
  type: LoadBalancer
  sessionAffinity: None
  externalTrafficPolicy: Local
  ipFamilies:
    - IPv4
  ipFamilyPolicy: SingleStack
  allocateLoadBalancerNodePorts: true
  internalTrafficPolicy: Cluster

SNAT 疑难解答

如果知道正在启动与同一目标 IP 地址和端口的多个出站 TCP 或 UDP 连接,并且观察到失败的出站连接,或者支持人员通知已耗尽 SNAT 端口(PAT 使用的预先分配的临时端口),则有几个常见缓解选项可供选择。 查看这些选项,确定最适合自己的方案的选项。 一个或多个选项可能有助于管理方案。 有关详细信息,请查看出站连接故障排除指南

SNAT 耗尽的根本原因通常是建立和管理出站连接的方式出现了对立模式,或者可配置的计时器已更改,不再使用默认值。 请认真阅读本部分。

步骤

  1. 检查连接是否长时间处于空闲状态,以及是否依靠默认的空闲超时释放该端口。 如果是,可能需要为你的方案减少 30 分钟的默认超时。
  2. 调查应用程序如何建立出站连接(例如,通过代码评审或数据包捕获进行调查)。
  3. 确定此活动是否为预期行为,或者应用程序是否行为异常。 使用 Azure Monitor 中的指标日志来证实发现结果。 例如,对 SNAT 连接指标使用“失败”类别。
  4. 评估是否遵循适当的模式
  5. 评估更多出站 IP 地址 + 更多分配的出站端口是否应可以缓解 SNAT 端口耗尽的问题。

设计模式

尽量利用连接重用和连接池。 这些模式有助于避免资源耗尽问题,并使行为可预测。 在许多开发库和框架中,都可以找到这些模式的根源。

  • 原子请求(每个连接一个请求)是一个通常并不良好的设计选项。 这种反模式会限制缩放,降低性能并降低可靠性。 应该重复使用 HTTP/S 连接来减少连接数和关联的 SNAT 端口数。 由于使用 TLS 时会减少握手次数、系统开销以及加密操作的开销,因此应用程序的规模与性能都会提高。
  • 如果你使用的是群集/自定义 DNS,或者 coreDNS 上的自定义上游服务器,请记住,当客户端不缓存 DNS 解析器结果时,DNS 可以在卷上引入许多单独的流。 请确保首先自定义 coreDNS 而不是使用自定义 DNS 服务器,并定义合适的缓存值。
  • UDP 流(例如 DNS 查找)在空闲超时期间分配 SNAT 端口。 空闲超时越长,SNAT 端口上的压力越大。 使用较短的空闲超时(例如 4 分钟)。
  • 使用连接池来调整连接卷。
  • 切勿以静默方式丢弃 TCP 流,且不要依赖 TCP 计时器来清理流。 如果不允许 TCP 显式关闭连接,中间系统和终结点上将保持已分配状态,使 SNAT 端口不可用于其他连接。 此模式可能会触发应用程序故障和 SNAT 耗尽。
  • 在对造成的影响了解不深的情况下,请不要更改与 OS 级别的 TCP 关闭相关的计时器值。 当某个连接的终结点不符合预期时,尽管 TCP 堆栈会恢复,但应用程序的性能可能会受负面影响。 希望更改计时器往往意味着底层设计出现了问题。 查看以下建议:

从基本 SKU 负载均衡器迁移到标准 SKU

如果你已有一个具有基本 SKU 负载均衡器的群集,则在迁移到标准 SKU 负载均衡器时,需要注意一些重要的行为差异。

例如,给定群集的 load-balancer-sku 类型后,进行蓝/绿部署以迁移群集是一种常见的做法,并且只能在创建群集时定义。 但是,基本 SKU 负载均衡器使用基本 SKU IP 地址,而这些地址与标准 SKU 负载均衡器不兼容。 标准 SKU 负载均衡器需要标准 SKU IP 地址。 迁移群集以升级负载均衡器 SKU 时,需要一个具有兼容 IP 地址 SKU 的新 IP 地址。

有关如何迁移群集的注意事项,请访问我们有关迁移注意事项的文档

限制

创建和管理支持标准 SKU 负载均衡器的 AKS 群集时存在以下限制:

  • 至少需要指定一个公共 IP 或 IP 前缀来允许 AKS 群集的出口流量。 此外,需要使用公共 IP 或 IP 前缀来保持控制平面与代理节点之间的连接,以及保持与旧版 AKS 的兼容性。 可以使用以下选项指定标准 SKU 负载均衡器的公共 IP 或 IP 前缀:
    • 提供自己的公共 IP。
    • 提供自己的公共 IP 前缀。
    • 指定一个数字,最大可以为 100,使 AKS 群集可以在其所在的资源组中创建该数量的标准 SKU 公共 IP。 此资源组的名称通常以 MC_ 开头。 AKS 会将公共 IP 分配到标准 SKU 负载均衡器。 默认情况下,如果未指定公共 IP、公共 IP 前缀或 IP 数量,则会在 AKS 群集所在的资源组中自动创建一个公共 IP。 还必须允许公共地址,并避免创建任何禁止创建 IP 的 Azure 策略。
  • 由 AKS 创建的公共 IP 不能作为自定义的自带公共 IP 地址重复使用。 用户必须创建和管理所有自定义 IP 地址。
  • 只能在创建 AKS 群集时定义负载均衡器 SKU。 创建 AKS 群集后,无法更改负载均衡器 SKU。
  • 在单个群集中只能使用一种类型的负载均衡器 SKU (基本或标准)。
  • 标准 SKU 负载均衡器仅支持标准 SKU IP 地址。

后续步骤

要详细了解 Kubernetes 服务,请参阅 Kubernetes 服务文档

要详细了解如何对入站流量使用内部负载均衡器,请参阅 AKS 内部负载均衡器文档