本文档介绍了如何使用基于健康检查的负载均衡在 Google Kubernetes Engine (GKE) 上实现永久性 IP 地址的高可用性。虽然标准永久性 IP 配置会将单个永久性 IP 地址映射到单个 Pod,但基于健康检查的负载均衡可让您将来自一个或多个永久性 IP 地址的流量分配到运行状况良好的 Pod 池中。
如需声明特定的永久性 IP 地址并确定哪些 Pod 接收流量,您可以创建 GKEIPRoute 自定义资源。通过将 GKEIPRoute 资源与区域健康检查相集成,GKE 可以在网络层监控工作负载,并仅将流量路由到已准备好接收流量的 Pod。您还可以使用 GKEIPRoute 对象指定可选的备份 Pod。 如果每个主活跃 Pod 都未通过健康检查,GKE 才会将流量路由到这些备用 Pod。
要求和限制
- 如需使用基于健康检查的负载均衡,您的集群必须运行 GKE 1.32.3-gke.1440000 版或更高版本。GKE 仅在 1.35.0-gke.1403000 版或更高版本中支持选择备份 Pod。
- 您的集群必须已启用 GKE Dataplane V2 和 Gateway API。
- 单个 GKEIPRoute 对象仅支持每个节点一个匹配的 Pod。如果节点上的多个 Pod 与 GKEIPRoute 的 Pod 选择器匹配,GKE 会选择该节点上最近创建的 Pod。 字段,以确保 Pod 的适当分布。
- 创建 GKEIPRoute 对象后,您将无法修改网关类。
- 基于健康检查的负载均衡仅支持从工作负载外部发起的流量。不支持从工作负载内发起到持久 IP 地址的流量。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请通过运行
gcloud components update命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。
- 了解 IP 地址。
实现基于健康检查的负载均衡
本部分总结了实现基于健康检查的负载均衡的工作流:
- 创建区域性健康检查:定义 GKE 用于监控 Pod 状态的参数。此对象会告知网络层哪些端点运行状况良好,并且有资格接收来自永久性 IP 地址的流量。
- 创建集群:设置启用了 GKE Dataplane V2 和 Gateway API 的 GKE 集群。这些组件提供管理持久 IP 路由和基于健康检查的负载均衡所需的基础架构。
- 预留 IP 地址:选择并预留与集群位于同一区域的静态内部或外部 IP 地址。此地址将作为持久性入口点,由 GKE 在您的活跃或备份 Pod 池中进行分配。
- 创建网关:配置网关对象以管理预留的永久性 IP 地址。GKEIPRoute 对象会从网关为工作负载声明并使用特定的 IP 地址。
- 创建 GKEIPRoute 对象:使用标签选择器定义将永久性 IP 地址映射到一组 Pod 的路由规则。在此对象中,您可以引用区域性健康检查,并可以选择性地为故障切换场景指定备用 Pod。
- 查看匹配的端点:检查自动生成的 EndpointSlice,验证 GKE 是否已正确识别您的活跃 Pod 和备份 Pod。此步骤可确认您的标签是否与预期 Pod 匹配,以及网络层是否已准备好路由流量。
第 1 步:创建区域级健康检查和防火墙规则
如需创建区域健康检查,请按照创建健康检查中的步骤操作。您在此处提供的名称将用在您的 GKEIPRoute 配置中。例如:
gcloud compute health-checks create http reg-lb-hc \
--region=us-central1 \
--check-interval=5s \
--timeout=5s \
--healthy-threshold=2 \
--unhealthy-threshold=2
为了让来自 Google Cloud 的健康检查探测到达您的节点,您还必须创建防火墙规则。
第 2 步:创建 GKE 集群
创建启用了 Gateway API 和 GKE Dataplane V2 的集群。例如:
gcloud container clusters create cluster-1 \
--enable-dataplane-v2 \
--gateway-api=standard \
--region=us-central1
如果您在与集群的默认 VPC 网络不同的 VPC 网络上配置 GKEIPRoute 对象,则必须创建具有多网络功能的 GKE 集群。如需了解详情,请参阅设置 Pod 的多网络支持。
第 3 步:预留 IP 地址
预留要用于工作负载的 IP 地址。您可以选择预留 Google 提供的 IP 地址,或是使用自备 IP 地址 (BYOIP)。
第 3a 步:预留 Google 提供的 IP 地址
如需预留外部 IP 地址,请运行以下命令:
gcloud compute addresses create ADDRESS_NAME \
--region=REGION
替换以下内容:
ADDRESS_NAME:您要与此地址关联的名称。REGION:您要预留此地址的区域。此区域应为您要将 IP 地址附加到的 Pod 所在的区域。注意:您必须在预留 IP 地址时指定区域,因为处理永久性 IP 地址的流量路由的转发规则是区域级的。您的 IP 地址和 GKE 集群必须位于同一区域,才能使路由正常运行。
如需预留内部 IP 地址,请运行以下命令:
gcloud compute addresses create ADDRESS_NAME \
--region REGION
--subnet SUBNETWORK \
--addresses IP_ADDRESS
替换以下内容:
ADDRESS_NAME:您要预留的一个或多个地址的名称。对于多个地址,请将所有地址指定为列表(以空格分隔)。例如:example-address-1 example-address-2 example-address-3。REGION:此请求对应的区域。SUBNETWORK:此内部 IPv4 地址所属的子网。IP_ADDRESS:所选子网的主要 IP 地址范围中未使用的内部 IP 地址。
为了确保在专用网络中正确路由流量,内部 IP 地址必须属于集群的默认子网或其他网络子网。
如需详细了解外部和内部 IP 地址,或了解如何使用 Google Cloud 控制台预留地址,请参阅预留静态外部 IP 地址和预留静态内部 IP 地址。
第 3b 步:自备 IP 地址 (BYOIP)
您可以自备 IP 地址 (BYOIP),而不是依赖于 Google 提供的 IP 地址。如果您需要将特定 IP 地址用于应用或将现有系统迁移到 Google Cloud,则 BYOIP 非常有用。如需使用 BYOIP,Google 会验证您是否拥有该 IP 地址范围,在这些 IP 地址导入 Google Cloud后,您可以将其分配为 GKE Pod 的 IP 地址。如需了解详情,请参阅自备 IP 地址。
第 4 步:创建网关对象
您可以使用以下仅支持 L3 网络类型的网关类来创建网关:
- gke-passthrough-lb-external-managed 或
- gke-passthrough-lb-internal-managed.
以下示例定义了一个管理外部 IP 地址池的网关:
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: lb-gateway
spec:
gatewayClassName: gke-passthrough-lb-external-managed
listeners:
- name: default
port: 443
protocol: none
allowedRoutes:
namespaces:
from: All
addresses:
- value: "34.123.10.1/32"
type: "gke.networking.io/cidr"
- value: "34.123.10.2/32"
type: "gke.networking.io/cidr"
在上面的示例中,请注意以下字段:
- addresses:列出特定网关管理权限的所有 IP 地址范围。
- listeners:用于标识 GKEIPRoute 对象可以从中引用此网关的命名空间。
如需详细了解监听器用法,请参阅创建网关对象。
第 5 步:创建包含负载均衡和健康检查配置的 GKEIPRoute 对象
创建一个 GKEIPRoute 对象,在其中定义主 Pod 选择器和备份 Pod 选择器,并关联您在第 1 步中创建的健康检查。
kind: GKEIPRoute
apiVersion: networking.gke.io/v1
metadata:
namespace: default
name: my-ip-route
spec:
parentRefs:
- name: lb-gateway
addresses:
- value: "34.123.10.1/32"
type: "gke.networking.io/cidr"
- value: "34.123.10.2/32"
type: "gke.networking.io/cidr"
network: default
podSelector:
matchLabels:
component: activePodSelector
loadBalancing:
healthCheckName: "reg-lb-hc"
backupPodSelector:
namespaceSelector:
matchLabels:
environment: test
dc: us-central
podSelector:
matchLabels:
component: backupPodSelector
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: proxy-deployment
spec:
replicas: 1
selector:
matchLabels:
component: proxy
template:
metadata:
# annotations: <- Include these lines if the pods are multi-nic pods
# networking.gke.io/default-interface: 'eth0'
# networking.gke.io/interfaces: '[{"interfaceName":"eth0","network":"default"}, {"interfaceName":"eth1","network":"blue-network"}]'
labels:
component: proxy
spec:
containers:
- name: hello-app
image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
请注意以下几点:
podSelector:用于标识接收来自所定义的永久性 IP 地址的流量的主要活跃 Pod。此字段使用标签来匹配与 GKEIPRoute 资源位于同一命名空间中的 Pod。GKE 会在与此选择器匹配的所有健康 Pod 之间分配流量。如果多个匹配的 Pod 位于同一节点上,GKE 只会选择最近创建的 Pod 来接收流量。此处定义的标签不得与backupPodSelector字段中的标签重叠。此字段可更改。backupPodSelector:定义仅在与 podSelector 对象匹配的所有主 Pod 都无法通过健康检查时才接收流量的备用 Pod。此选择器包含以下内容:namespaceSelector:确定 GKE 搜索哪些命名空间来查找这些备份 Pod。您可以使用标签选择器将搜索范围限定为特定命名空间。如果省略或留空此字段,GKE 会在集群中的所有命名空间中查找备份 Pod。podSelector:根据标签匹配备份 Pod。这些标签必须与主 podSelector 对象中使用的标签不同。
如需详细了解此清单中的其他字段,请参阅创建 GKEIPRoute 对象。
第 6 步:在 Pod 中使用分配的 IP 地址
使用 GKEIPRoute 对象向 GKE Pod 分配 IP 地址并不会自动使这些 IP 地址可供应用使用。IP 地址在网络路由级别进行处理,但 Pod 的默认配置不清楚这一点。您必须配置 Pod 规范,以识别和使用 Pod 中的地址。为此,您的 Pod 需要特权权限。
您可以使用以下选项之一配置 Pod 规范:
修改
net.ipv4.ip_nonlocal_bindsysctl您可以通过在 Pod 中设置
net.ipv4.ip_nonlocal_bindsysctlsecurityContext来修改系统设置,以允许应用使用未直接分配给其接口的 IP 地址。如果您的应用可以绑定到不在接口上的 IP 地址,此选项非常有用。将以下内容添加到 Deployment 或 StatefulSet YAML 规范的
spec.template.spec下:securityContext: sysctls: - name: net.ipv4.ip_nonlocal_bind value: "1"将分配的 IP 地址添加到 Pod 接口
您可以使用 init 容器将 GKEIPRoute 对象声明的 IP 地址手动添加到某个 Pod 的接口。这样,Pod 就可以看到 IP 地址,就像直接分配的一样。这需要
NET_ADMIN功能。将以下内容添加到 Deployment 或 StatefulSet YAML 规范的
spec.template.spec下:initContainers: - name: configure-ips image: gcr.io/google.com/cloudsdktool/cloud-sdk:slim command: ['sh', '-c', 'ip address add ASSIGNED_IP/32 dev eth0'] securityContext: capabilities: add: - NET_ADMIN将
ASSIGNED_IP替换为分配给 GKEIPRoute 对象的 IP 地址之一。原始套接字:为了实现更多控制,您的应用可以直接与网络栈进行交互(高级)。
用户空间 IP 地址栈:在专门的场景中,一个单独的应用可能会在 Pod 中运行来管理 IP 地址(非常高级)。
第 7 步:为分配的 IP 地址启用 ARP(仅限默认网络)
如需生成有效的地址解析协议 (ARP) 请求和响应,并使用 GKEIPRoute 对象在默认网络上分配的 IP 地址与 Pod 建立新连接,您必须配置 arp_announce 变量。
如需设置 arp_announce 变量,请在 Pod 上运行以下命令:
echo "2" > /proc/sys/net/ipv4/conf/eth0/arp_announce
其中,arp_announce 变量用于控制 ARP 通知的处理方式。将其设置为“2”可确保针对永久性 IP 地址发出 ARP 通知,从而使网络上的其他设备了解新的关联。
第 8 步:查看匹配的端点
为了管理流量分配,GKE 会为每个 GKEIPRoute 对象创建 EndpointSlice。这些切片充当指定为相应特定路由的路由目的地的所有 Pod 的注册表。
GKE 会为有效端点和备份端点分别生成 EndpointSlice。系统会根据您的工作负载自动扩缩 EndpointSlice 的数量。虽然单个 EndpointSlice 最多支持 1,000 个端点,但如果匹配的 Pod 数量超过此限制,GKE 会创建额外的切片。
如需查看特定 GKEIPRoute 对象的所有 EndpointSlice,请运行以下命令:
kubectl get endpointslices --all-namespaces -l \
networking.gke.io/gkeiproute-name=GKEIPROUTE_NAME,\
networking.gke.io/gkeiproute-namespace=GKEIPROUTE_NAMESPACE
替换以下内容:
GKEIPROUTE_NAME:GKEIPRoute 清单的名称。GKEIPROUTE_NAMESPACE:GKEIPRoute 清单的命名空间。
以下输出显示了 EndpointSlice 的示例:
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: {gkeiproute_name-truncated}-{gkeiproute_namespace-truncated}-backup-{unique_hash}
namespace: {gkeiproute_namespace}
labels:
endpointslice.kubernetes.io/managed-by: gkeiproute-controller
networking.gke.io/gkeiproute-name: {gkeiproute_name}
networking.gke.io/gkeiproute-namespace: {gkeiproute_namespace}
networking.gke.io/pip-es-role: backup
ownerReferences:
- kind: GKEIPRoute
name: {gkeiproute_name}
apiVersion: networking.gke.io/v1
uid: {uid}
controller: true
addressType: IPv4
endpoints:
- addresses:
- "{pod_ip_address}"
targetRef:
Name: {pod_name}
nodeName: {node_name}
如需专门查看活动端点或备份端点的 EndpointSlice,请使用 pip-eps-role 标签过滤结果。例如:
kubectl get endpointslices --all-namespaces -l \
networking.gke.io/pip-eps-role=ROLE \
networking.gke.io/gkeiproute-name=GKEIPROUTE_NAME,
替换以下内容:
ROLE:您要查看的端点类型,可以是active或backup。GKEIPROUTE_NAME:特定 GKEIPRoute 对象的名称。
排查基于健康检查的负载均衡问题
本部分介绍如何解决与基于健康检查的负载均衡相关的问题。
部分活跃 Pod 健康状况不佳,但备份 Pod 未接收流量
症状
GKEIPRoute 状态显示 Ready,表示匹配 Pod 的 IP 地址配置已完成。健康检查或其他诊断显示,部分活跃 Pod 运行状况不佳。不过,备份 pod 不会接收流量。
原因
在所有活跃 Pod 运行状况不佳之前,备用 Pod 不会接收流量。在此之前,所有流量都会分配给剩余的运行状况良好且活跃的 Pod。
解决方法
如有必要,请更新 podSelector 字段标签,使其不再与任何活跃的 Pod 匹配。GKE 会自动将流量路由到后端组。
GKEIPRoute 已配置,但并非所有 Pod 都接收到流量
症状
GKEIPRoute 状态显示 Ready,表示匹配 Pod 的 IP 地址配置已完成,但部分匹配 Pod 未收到流量。
原因
未接收流量的 Pod 可能运行不正常,或者可能无法正确响应健康检查。请注意,如果所有匹配的 Pod 都不正常,GKE 会在所有 Pod 之间分配流量,无论其健康状况如何。
解决方法
- 验证 Pod 是否正常运行:使用 Google Cloud CLI 或Google Cloud 控制台验证 Pod 是否对健康状况检查做出正确响应。
- 必要时进一步调查:如果 Pod 运行状况不佳,请验证您是否已为健康检查正确设置防火墙,以及您的 Pod 是否正在响应。
“负载均衡器配置无效”错误
本部分将帮助您排查 GKEIPRoute 状态错误。
Backup pod and active pod are on the same node
症状
GKEIPRoute 状态报告以下错误:
invalid LB configuration: Backup pod %s and active pod %s are on the same node %s. Active and backup pods must reside on different nodes.
原因
与同一 GKEIPRoute 对象匹配的活跃 Pod 和备份 Pod 会被安排到同一节点上。换句话说,在同一节点上,存在同时与有效 podSelector 对象和备份 podSelector 对象匹配的 Pod。
解决方法
确保活跃 Pod 和备份 Pod 位于不同的节点上。更新 GKEIPRoute 配置并调整 podSelector 或 backupPodSelector 标签,使同一节点上的任何两个 Pod 都不会与同一 GKEIPRoute 对象匹配。
Pod cannot be selected as both an active and a backup pod
症状
GKEIPRoute 状态报告以下错误:
invalid LB configuration: pod %s cannot be selected as both an active and a backup pod. Active and backup pod sets must be mutually exclusive
原因
一个或多个 Pod 与 podSelector(活跃)字段和 backupPodSelector(备用)字段的标签选择器相匹配。GKE 要求这两个组互斥。单个 Pod 无法充当自己的备份。
解决方法
确保您的主 Pod 和备份 Pod 是唯一的。修改 GKEIPRoute 清单中的 podSelector 字段或 backupPodSelector 字段,以使用更具体或更独特的标签键和值。
NoPodsFound状态
症状
GKEIPRoute 清单显示状态为 NoPodsFound,表示命名空间中没有具有匹配标签的 Pod。
潜在原因
- 标签不正确:您打算对其使用配置的 IP 地址的 Pod 可能具有错误的标签,或者根本没有标签。
- Pod 不存在:如果
reactionMode == Exists,请通过检查pod.Spec.nodeName字段来检查 Pod 是否已分配给节点。GKEIPRoute 的命名空间中可能没有任何与选择器匹配的 Pod 运行。 - Pod 未就绪:如果
reactionMode == ReadyCondition,请检查 Pod 状态是否为READY。如果存在匹配的 Pod,但其未处于READY状态,则该 Pod 无法处理流量,因此不会被选择。
解决方法
- 检查标签:确认 GKEIPRoute 对象的
podSelector字段中的标签与您应用于预期 Pod 的标签相匹配。 - 验证 Pod 是否存在:确保具有正确标签的 Pod 实际存在于网关的监听器所指定的 GKEIPRoute 对象的命名空间中。如果
reactionMode == Exists,请通过检查pod.Spec.nodeName字段来检查 Pod 是否已分配给节点。 确认 Pod 就绪性:如果
reactionMode == ReadyCondition,请检查 Pod 状态是否为READY。使用以下命令确保 Pod 处于Ready状态:kubectl get pods -n NAMESPACE不会选择处于其他状态(例如
Pending、Error)的 Pod。
Mutated 状态(如果找到匹配的 Pod 并且 GKEIPRoute IP 地址编程正在进行)
症状
GKEIPRoute 状态显示 Mutated,表示匹配 Pod 的 IP 地址配置正在进行中。
可能原因
在配置期间,当系统为配置的 IP 地址设置 GKE 数据路径和 Google Cloud 资源时,预计会出现 Mutated 状态。
解决方法
- 等待并重试:在大多数情况下,配置过程会在短时间内自动完成。等待后检查状态。成功后,状态会更改为
Ready。 进一步调查(如有必要):如果
Mutated状态长时间持续存在,则可能表示存在配置错误。检查 GKEIPRoute 对象上的其他状态条件:- Accepted:指示您的 GKEIPRoute 设置是否有效。
- GCPReady:指示 Google Cloud 资源是否按预期设置。
在这些条件下查找错误消息,以帮助排查问题。
后续步骤
- 详细了解 GKE Pod 的永久性 IP 地址