控制与永久性 IP 地址进行的通信

本页面介绍如何在 Google Kubernetes Engine (GKE) Pod 上实现永久性 IP 地址。您可以使用自定义永久性 IP 地址映射来控制 GKE Pod 网络。如需详细了解永久性 IP 地址、其应用场景和优势,请参阅 GKE Pod 的永久性 IP 地址简介

要求

  • GKE 1.31 版或更高版本。
  • 选择预留 Google 提供的 IP 地址,或是自备 IP 地址 (BYOIP)。
  • 配置在 Pod 中运行的应用,以识别和使用分配的永久性 IP 地址。
  • GKE Pod 的永久性 IP 地址需要启用了 GKE Dataplane V2 和 Gateway API 的集群。

限制

  • 您必须配置应用以使用分配的永久性 IP 地址。GKE 不会自动将 IP 地址配置添加到 Pod 的网络接口。
  • 每个永久性 IP 地址一次可以与一个 Pod 相关联。 如果您有多个 Pod 可用,GKE 通常会将流量发送到最新的匹配 Pod。但是,GKE 仅在最新 Pod 健康状况良好时才会执行此操作,这意味着 Pod 的 Ready 条件状态在默认情况下为 True。您可以使用 GKEIPRoute 上的 reactionMode 设置来配置和更改此行为。
  • GKE 仅支持将 IPv4 地址用作永久性 IP 地址。
  • GKE 仅支持将 第 3 层或设备类型 多网络用于永久性 IP 地址。
    • 使用永久性 IP 地址支持高可用性 (HA) 不适合非 DPDK 应用场景。
  • 您可以在单个 GKEIPRoute 上指定最多 16 个 IP 地址。如需配置更多地址,您可以创建多个 GKEIPRoute 对象。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务, 安装初始化 gcloud CLI。如果您之前安装了 gcloud CLI,请通过运行 gcloud components update 命令来获取最新 版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。

为 GKE Pod 实现永久性 IP 地址

GKE 中的永久性 IP 地址提供了一种为 Pod 提供稳定网络身份的方法(即使 Pod 本身进行更新或四处移动也是如此)。

本部分总结了为 GKE Pod 实现永久性 IP 地址的工作流:

  1. 创建集群:创建一个使用 Gateway API 和 GKE Dataplane V2 的集群。
  2. 预留 IP 地址:确定您需要外部(可公开访问)还是内部(仅限 Google Cloud)IP 地址并预留该地址。选择 GKE 集群所在的同一区域。
  3. 创建 Gateway:配置 Kubernetes Gateway 对象,该对象用于容纳预留的永久性 IP 地址,并且可让您创建有关集群中哪些 Pod 可以使用这些永久性 IP 地址的规则 (GKEIPRoutes)。
  4. 创建或识别工作负载以用于永久性 IP 地址:如果您在其他网络上使用 永久性 IP 地址,请通过启用多个网络接口并定义 永久性 IP 地址所在的网络,使 Pod 准备好使用 永久性 IP 地址。
  5. 为所选工作负载创建 GKEIPRoute 对象:配置 GKEIPRoute 以将永久性 IP 地址分配给特定 Pod。您可以使用标签来确定正确的目标 Pod,并且可以视情况配置路由如何响应 Pod 更改。
  6. 配置应用感知:在 Pod 中配置应用以主动使用永久性 IP 地址。
  7. 监控:跟踪网关和 GKEIPRoute 对象的状态,以确保一切按预期正常运行。

如需为 GKE Pod 实现永久性 IP 地址,请执行以下步骤:

第 1 步:创建启用了 Gateway API 和 GKE Dataplane V2 的 GKE 集群

如需启用在 GKE Pod 上实现永久性 IP 地址所需的高级网络路由和 IP 地址管理功能 ,您必须 创建 GKE Dataplane V2 集群,如下所示:

gcloud container clusters create CLUSTER_NAME \
    --cluster-version=CLUSTER_VERSION \
    --enable-dataplane-v2 \
    --enable-ip-alias \
    --gateway-api=standard

替换以下内容:

  • CLUSTER_NAME:集群的名称。
  • CLUSTER_VERSION:集群的版本。

第 2 步:设置永久性 IP 地址

如需为 Pod 建立可靠的网络身份并设置永久性 IP 地址,您必须先获取永久性 IP 地址。您可以选择预留 Google 提供的 IP 地址,或是使用自备 IP 地址 (BYOIP)。

第 2a 步:预留 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 地址必须属于集群的默认子网或其他网络子网。

如需详细了解外部和内部 IP 地址,或了解如何使用控制台预留地址,请参阅预留静态外部 IP 地址预留静态内部 IP 地址

第 2b 步:自备 IP 地址 (BYOIP)

您可以自备 IP 地址 (BYOIP),而不是依赖于 Google 提供的 IP 地址。如果您需要将特定 IP 地址用于应用或将现有系统迁移到 Google Cloud,则 BYOIP 非常有用。如需使用 BYOIP,Google 会验证您是否拥有该 IP 地址范围,在这些 IP 地址导入后,您可以将其分配为 GKE Pod 的永久性 IP 地址。 Google Cloud如需了解详情,请参阅自备 IP 地址

第 3 步:创建网关对象

网关对象用于保存 IP 地址,并定义哪些 Pod 有资格使用它们。如需控制将永久性 IP 地址分配给 GKE Pod 的方式,您会使用网关对象。

  1. 创建适当类的 Kubernetes 网关对象:
    • gke-persistent-regional-external-managed ,用于外部(公共)IP 地址。
    • gke-persistent-regional-internal-managed,用于内部( Google Cloud-仅限)IP 地址。
    • gke-persistent-fast-regional-external-managed ,用于具有快速故障切换功能的外部 IP 地址。
    • gke-persistent-fast-regional-internal-managed ,用于具有快速故障切换功能的内部(仅限 Google Cloud)IP 地址。
  2. 在网关的地址部分中,列出此网关管理的永久性 IP 地址(Google 提供的 IP 地址或 BYOIP)。
  3. 使用 Listeners 部分确定哪些 Pod(及其关联的 GKEIPRoute 对象)可能会使用网关的 IP 地址。 Listeners 基于 GKEIPRoute 对象所在的 GKEIPRoute 命名空间充当过滤条件。

    您可以从以下 Kubernetes 命名空间选择选项中进行选择:

    • 所有命名空间:集群中的任何 GKEIPRoute
    • 选择器GKEIPRoute 命名空间中与 特定标签匹配的 GKEIPRoute
    • 相同命名空间:仅限位于网关所在的 GKEIPRoute 的 命名空间中的 GKEIPRoutes

以下示例提供对外部永久性 IP 地址的集群范围访问权限,允许任何 Pod 使用它们。

将以下示例清单保存为 allowed-pod-ips.yaml

kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
  namespace: default
  name: allowed-pod-ips
spec:
  gatewayClassName: gke-persistent-regional-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 对象 可以从中引用此 Gateway 的命名空间。

将清单应用于集群:

kubectl apply -f allowed-pod-ips.yaml

第 4 步:(可选)使用其他网络创建或识别工作负载以用于永久性 IP 地址

如果您计划将永久性 IP 地址用于需要连接到多个网络的 Pod,您可以设置多网络 Pod创建网络对象 以表示永久性 IP 地址所属的网络。

第 5 步:为所选工作负载创建 GKEIPRoute 对象

如需为所选 Pod 分配永久性 IP 地址,请创建 GKEIPRoute 对象。

将以下示例清单保存为 my-ip-route.yaml

kind: GKEIPRoute
apiVersion: networking.gke.io/v1
metadata:
  namespace: default
  name: my-ip-route
spec:
  parentRefs:
  - name: allowed-pod-ips
    namespace: default
  addresses:
  - value: "34.123.10.1/32"
    type: "gke.networking.io/cidr"
  network: default
  reactionMode: ReadyCondition
  podSelector:
    matchLabels:
      component: proxy
  nodeSelector: # Can only be specified when using fast failover Gateway Classes.
    matchLabels:
      component: proxy
---
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

其中:

  • parentRefs:指向从中使用永久性 IP 地址的网关。该字段不可更改。
  • addresses:列出路由到使用 podSelector 标识的 Pod 的所有永久性 IP 地址。此字段可更改。 对于 IPv4,仅支持 /32 地址。
  • podSelector:指定用于标识永久性 IP 地址路由到的 Pod 的标签。此字段可更改,应用于放置 GKEIPRoute 的同一命名空间。如果您选择多个 Pod,需考虑另外两个因素:Pod 创建时间(GKE 会选择最新 Pod)和 reactionMode 字段的设置。
  • reactionMode:指定在创建或删除特定 Pod(通过 podSelector 选择)时,此功能的行为方式。此字段是可选字段,默认值为 ReadyConditionReadyCondition 字段不可更改。您可以设置 reactionMode 以控制在创建、删除或更新 Pod 时此功能的行为方式。
  • network:指向永久性 IP 地址路由到的 Pod 上的网络接口。此字段是可选字段,默认值为 default。请注意,如果您使用默认网络,则 network 必须设置为 default。如果您使用其他网络,请将网络设置为您之前创建的网络对象的名称。该字段不可更改。
  • nodeSelector:指定要预先配置以实现快速 故障切换的节点的标签。使用快速故障切换网关类时,必须设置此字段,并且最多可以选择 64 个节点。您必须确保具有永久性 IP 地址的 Pod 安排在这些节点上,通常通过使用 Pod 的 nodeSelector 来实现。

将清单应用于集群:

kubectl apply -f my-ip-route.yaml

为 StatefulSet Pod 分配永久性 IP 地址

如需为 StatefulSet 中的特定多网络 Pod 分配永久性 IP 地址,请使用 Pod 的可预测主机名和 Kubernetes 的自动添加标签功能,如以下示例所示:

将以下示例清单保存为 my-pod-ips.yaml

kind: GKEIPRoute
apiVersion: networking.gke.io/v1
metadata:
  namespace: proxy-ss-ns
  name: my-pod-ips
spec:
  parentRefs:
  - name: allowed-pod-ips
    namespace: default
  addresses:
  - value: "34.123.10.1/32"
    type: "gke.networking.io/cidr"
  - value: "34.123.10.2/32"
    type: "gke.networking.io/cidr"
  network: blue-network
  reactionMode: ReadyCondition
  podSelector:
    matchLabels:
      statefulset.kubernetes.io/pod-name: proxy-ss-1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  namespace: proxy-ss-ns
  name: proxy-ss
spec:
  selector:
    matchLabels:
      component: proxy
  serviceName: "proxy"
  replicas: 3
  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

将清单应用于集群(确保您有一个名为“blue-network”的网络):

kubectl apply -f my-pod-ips.yaml

将永久性 IP 地址分配给 Deployment Pod

如需为 Deployment 中的最新 Pod 分配永久性 IP 地址,请应用具有以下配置的 GKEIPRoute

将以下示例清单保存为 my-pod-ips.yaml

kind: GKEIPRoute
apiVersion: networking.gke.io/v1
metadata:
  namespace: proxy-deploy-ns
  name: my-pod-ips
spec:
  parentRefs:
  - name: allowed-pod-ips
    namespace: default
  addresses:
  - value: "34.123.10.1/32"
    type: "gke.networking.io/cidr"
  - value: "34.123.10.2/32"
    type: "gke.networking.io/cidr"
  network: blue-network # point to the right network if you intend to use persistent-ip on additional networks
  reactionMode: ReadyCondition
  podSelector:
    matchLabels:
      component: proxy
---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: proxy-deploy-ns
  name: proxy-deploy
spec:
  selector:
    matchLabels:
      component: proxy
  replicas: 4 # Latest Pod is used
  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

将清单应用于集群:

kubectl apply -f my-ip-route.yaml

如果您使用其他网络,请确保您有一个名为“blue-network”的网络。

第 6 步:使用 Pod 中的分配的 IP 地址

使用 GKEIPRoute 对象向 GKE Pod 分配 IP 地址并不会自动使这些 IP 地址可供应用使用。IP 地址在网络路由级别进行处理,但 Pod 的默认配置不清楚这一点。您必须配置 Pod 规范,以识别和使用 Pod 中的地址。为此,您的 Pod 需要特权权限。

您可以使用以下选项之一配置 Pod 规范:

  • 修改 net.ipv4.ip_nonlocal_bind sysctl

    您可以通过在 Pod securityContext 中设置 net.ipv4.ip_nonlocal_bind sysctl 来修改系统设置,以允许应用使用未直接分配给其接口的 IP 地址。如果您的应用可以绑定到接口上没有的 IP 地址,此选项非常有用。

    spec.template.spec 下将以下内容添加到 Deployment 或 StatefulSet YAML 规范中:

    securityContext:
      sysctls:
      - name: net.ipv4.ip_nonlocal_bind
        value: "1"
    
  • 将分配的 IP 地址添加到 Pod 接口

    您可以使用 init 容器将 GKEIPRoute 对象声明的 IP 地址手动添加到 Pod 的一个接口。这样,IP 地址对 Pod 可见,就像直接分配的一样。这需要 NET_ADMIN 功能。

    spec.template.spec 下将以下内容添加到 Deployment 或 StatefulSet YAML 规范中:

    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 步:使用快速故障切换

如果您将永久性 IP 地址与快速故障切换搭配使用,则可以通过从该 Pod 发出无偿 ARP (GARP) 请求,暂时将流量定向到 Pod。 Google Cloud 会尊重 GARP 大约 20 分钟。在此期间,您必须更新集群配置。为此,请在 GKEIPRoutespec.podSelector 字段中,将旧 Pod 的标签替换为新 Pod 的标签。

自定义 Pod 更改期间的永久性 IP 地址行为

本部分介绍在创建或删除目标 Pod 时,GKE Pod 的永久性 IP 地址的行为方式。GKE 控制器会监控您的 Pod 和 GKEIPRoute 配置。当检测到发生更新时,它会根据您选择的 reactionMode 自动将永久性 IP 地址重新分配给合适的 Pod。

了解永久性 IP 地址功能如何自动处理 Pod 更改以及您可以使用的配置选项:

  • 确定 GKEIPRoute 配置的 reactionMode 字段中是 ReadyCondition 还是 Exists。请考虑应用在分配 IP 地址的速度与严格就绪性要求方面的需求。
  • 如果您使用 ReadyCondition 来确保就绪性,请确保您的 Pod 已正确实现 Kubernetes 就绪性探测。否则,永久性 IP 地址可能无法按预期运行。
  • 我们建议您监控 Pod 的状态和 GKEIPRoute 对象的 Conditions 字段,以确保系统正常运行。Ready 条件的 true 状态表示系统正常运行。

排查与 Pod 的永久性 IP 地址进行通信方面的问题

本部分介绍如何解决与 Pod 的永久性 IP 地址相关的问题。

NoPodsFound(如果找不到匹配的 Pod)

症状

GKEIPRoute 对象指定 podSelector(一组标签),以标识哪些 Pod 与永久性 IP 地址相关联。NoPodsFound 状态表示目标 GKEIPRoute's 命名空间中没有具有匹配标签的 Pod。

潜在原因

  • 标签不正确:您打算对其使用永久性 IP 地址的 Pod 可能具有错误的标签,或者根本没有标签。
  • Pod 不存在:如果 reactionMode == Exists,请通过检查 pod.Spec.nodeName 字段来检查 Pod 是否已分配给节点。GKEIPRoute's 命名空间中可能没有任何与选择器匹配的 Pod 运行。
  • Pod 未就绪:如果 reactionMode == ReadyCondition,请检查 Pod 状态是否为 READY。即使存在匹配的 Pod,但如果其未处于 Ready 状态,它也无法处理流量,因此不会被选择。

解决方法

  1. 检查您的标签:核查 GKEIPRoute's podSelector 中的标签是否与您应用于预期 Pod 的标签相匹配。
  2. 验证 Pod 是否存在:确保具有正确标签的 Pod 实际 存在于 GKEIPRoute 所指定的网关 Listeners 命名空间中。 如果 reactionMode == Exists,请通过检查 pod.Spec.nodeName 字段来检查 Pod 是否已分配给节点
  3. 确认 Pod 就绪性:如果 reactionMode == ReadyCondition,请检查 Pod 状态是否为 READY。可使用以下命令确保 Pod 处于 Ready 状态:

    kubectl get pods -n <namespace>
    

    不会选择处于其他状态(例如“Pending”或“Error”)的 Pod。

  4. 配置 Pod,以响应分配的永久性 IP 地址。

Mutated(如果找到匹配的 Pod 并且永久性 IP 地址编程正在进行)

症状

GKEIPRoute 状态显示“Mutated”,表示匹配 Pod 的永久性 IP 地址配置正在进行中。

可能原因

在配置期间,当系统为永久性 IP 地址设置 GKE 数据路径和 Google Cloud 资源时,预计会出现“Mutated”状态。

解决方法

  1. 等待并重试 :在大多数情况下,配置过程会在短时间内自动完成。等待后检查状态。成功后,状态会更改为 Ready
  2. 进一步调查(如有必要) :如果“Mutated”状态长时间持续存在,则可能表示存在配置错误。检查 GKEIPRoute 上的其他状态条件:
    • Accepted:指示您的 GKEIPRoute 设置是否有效。
    • DPV2Ready:指示节点上的数据路径是否已正确编程 。
    • GCPReady:指示资源是否按 Google Cloud 预期设置。

在这些条件下查找错误消息,以帮助排查问题。

已发送 GARP,但 Pod 未接收流量

症状

您已从新 Pod 发送 GARP,但流量保持不变。GKEIPRoute 状态保持“就绪”,并且未指示错误。

潜在原因

Pod 不在与 GKEIPRoute 中的 nodeSelector 匹配的节点上。GARP 使用的 IP 地址未与 GKEIPRoute 关联。

解决方法

  • 验证 Pod 的节点:确保 Pod 在与 您 nodeSelector 配置中的 GKEIPRoute 匹配的节点上运行。如果 Pod 不在匹配的节点上,则可能未针对 GKEIPRoute 对节点进行编程。
  • 验证 GARP 的 IP 地址:确保 GARP 中的 IP 地址 是 GKEIPRoute 的地址 字段中指定的 IP 地址之一。如果 IP 地址未与 GKEIPRoute 关联,则不会触发快速故障切换机制。

后续步骤