为 GKE 配置以非公开方式使用的公共 IP 地址


本教程介绍如何将以非公开方式使用的公共 IP (PUPI) 地址应用于 Google Kubernetes Engine (GKE) Pod 地址块。

以非公开方式使用的公共 IP (PUPI) 地址是您可以在 Google Cloud Virtual Private Cloud (VPC) 网络中以非公开方式使用的地址。这些 IP 地址不归 Google 所有。您无需拥有这些公共 IP 地址即可以不公开方式使用它们。

概览

GKE 集群要求为节点、Pod 和 Service 使用专用 IP 地址范围。随着基础设施的发展,您可能会面临标准内部 IP 地址空间 (RFC 1918) 耗尽问题。缓解专用 RFC 1918 地址耗尽问题的一种方法是使用 GKE Pod CIDR 地址块的以非公开方式使用的公共 IP (PUPI) 地址。PUPI 为 GKE Pod 网络提供了一种替代方案,可为其他集群组件预留专用 IP 地址。

单个集群:如果您只创建一个 GKE 集群,则可以通过启用以非公开方式使用的外部 IP 地址范围来启用 PUPI。

多个集群:如果您使用的是通过 VPC 对等互连连接的多个 GKE 集群(服务提供商的常见场景),则需要更复杂的配置。下图举例说明了公司(提供方)如何使用 PUPI 为托管式服务提供与客户(使用方)的 VPC 对等互连。

GKE Pod CIDR 地址块的 PUPI 地址。

上图涉及以下注意事项:

  • 主要 CIDR 地址块:用于节点和内部负载均衡器 (ILB) 且不能跨 VPC 重叠的非 PUPI CIDR 地址块。
  • 提供方次要 CIDR 地址块:用于 Pod 的 PUPI CIDR 地址块(例如 45.45.0.0/16)。
  • 使用方次要 CIDR 地址块:客户端的任何其他 PUPI CIDR 地址块(例如 5.5.0.0/16)。

在服务提供商场景中如何使用 PUPI

服务提供商(提供方)在其 VPC (vpc-producer) 内的 GKE 集群 (gke-2) 上运行其托管式服务。此集群使用 PUPI 范围 45.0.0.0/8 作为其 Pod IP 地址。

客户(使用方)也在自己的 VPC (vpc-consumer) 中有一个 GKE 集群 (gke-1),该集群使用另一 PUPI 范围 5.0.0.0/8 作为其 Pod IP 地址。

这两个 VPC 使用 VPC 对等互连连接,但每个 VPC 都继续为节点、服务和内部负载均衡器使用标准专用 IP 地址 (RFC 1918)。

确保 VPC 之间的通信

  • 使用方到提供方:默认情况下,使用方的 VPC 会自动与提供方共享其 RFC 1918 路由(但不共享 PUPI)。这样,使用方 VPC 中的资源便可访问提供方 VPC 中的服务(通常通过内部负载均衡器)。
  • 提供方到使用方:为了让提供方的 Pod 访问使用方 VPC 中的资源,需要进行明确配置。
  • 不重叠:提供方和使用方必须确保使用方的 PUPI 范围不与提供方 VPC 中使用的任何 IP 地址冲突。
  • 导出/导入:提供方必须启用导出 PUPI 路由的功能,并且使用方必须启用通过对等互连连接导入这些路由的功能。

在 PUPI 范围重叠时启用通信

如果使用方的 VPC 已使用与提供方相同的 PUPI 范围,则无法实现来自提供方 Pod 的直接通信。但是,提供方可以启用 IP 地址伪装,以便将 Pod IP 地址隐藏在提供方的节点 IP 地址后面。

下表展示了每个 VPC 的默认导入和导出设置。您可以使用 gcloud compute networks peerings update 命令修改默认 VPC 对等互连设置。

VPC 网络 导入设置 导出设置 备注
提供方

默认行为(已关闭):不导入具有公共 IP 地址的子网路由
如需开启,请使用以下命令:--import-subnet-routes-with-public-ip(通过对等互连)

默认行为(已开启):导出具有公共 IP 地址的子网路由
如需关闭,请使用以下命令:--no-export-subnet-routes-with-public-ip(通过对等互连)

通过服务网络控制标志。
使用方 已关闭(默认) 已开启(默认) 通常由客户管理,不需要通过服务网络进行修改

这些设置会产生以下结果:

  • 提供方 VPC 看到所有客户路由。
  • 使用方 VPC 未看到提供方 VPC 的 Pod 子网上配置的 PUPI 路由。
  • 从提供方 Pod 到 vpc-consumer 网络的流量必须在提供方集群中的节点地址后面进行转换。

前提条件

如需在 VPC Pod 与另一个 VPC 之间成功建立通信,请确保满足以下前提条件和配置:

  • GKE 集群必须满足以下最低版本要求:
    • Autopilot 集群:GKE 1.22 版或更高版本
    • Standard 集群:GKE 1.14 版或更高版本
  • 选择不可公开路由或不归 Google 所有的 PUPI 范围。
  • 确保两个 VPC 的节点 IP 地址和主要 IP 地址范围不重叠。
  • 如果您需要在客户 VPC 与托管式服务之间实现直接 Pod 到 Pod 通信,请按照以下步骤操作:
    • Autopilot 集群:为 PUPI 配置 SNAT,以确保 Pod 到 Pod 的通信。您无需进行额外配置。
    • Standard 集群:使用 SNAT 将 Pod IP 地址转换为相应的节点 IP 地址。为 PUPI 流量启用 SNAT。如需了解详情,请参阅启用以非公开方式使用的外部 IP 地址范围

为 GKE 集群配置以非公开方式使用的公共 IP 地址

如需为 GKE 集群配置 PUPI 地址,请执行以下操作:

  1. 配置两个 Virtual Private Cloud 网络。
  2. 在每个 Virtual Private Cloud 网络内配置一个子网。
  3. 在每个子网的次要地址范围内配置 PUPI 地址范围。
  4. 通过适当的导入和导出设置,在两个 Virtual Private Cloud 网络之间建立 Virtual Private Cloud 对等互连关系。
  5. 检查每个 Virtual Private Cloud 内的路由。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用量来估算费用。

准备工作

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

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行 gcloud components update 以获取最新版本。
  • 仅使用 VPC 原生集群。

  • VPC 对等互连设置所需的 IPAM 规范。

设置网络和集群

  1. 创建 VPC 网络:

    创建以下两个 VPC 网络,并将 RFC-1918 用作节点的主要范围和 Pod 的 PUPI 范围。将 RFC 1918 专用地址空间中的主要 IP 地址范围(例如 10.x.x.x172.16.x.x192.168.x.x)分配给这两个 VPC。这些范围通常用于 GKE 集群中的工作器节点。除了内部 IP 地址范围之外,请为每个 VPC 指定单独的以非公开方式使用的公共 IP 地址 (PUPI) 范围。这些 PUPI 范围专门用于相应 GKE 集群中的 Pod IP 地址。

    • 使用方 VPC 网络:此 VPC 托管在其中运行使用方应用或工作负载的 GKE 集群。您可以使用如下所示的配置:

      Network: consumer
      Subnetwork: consumer-subnet
      Primary range: 10.129.0.0/24
      Service range name and cidr: consumer-services, 172.16.5.0/24
      Pod range name and cidr: consumer-pods, 5.5.5.0/24
      Cluster name: consumer-cluster
      
    • 提供方 VPC 网络:此 VPC 托管负责提供使用方使用的服务的 GKE 集群。您可以使用如下所示的配置:

      Network: producer
      Subnetwork: producer-subnet
      Primary range: 10.128.0.0/24
      Service range name and cidr: producer-services, 172.16.45.0/24
      Pod range name and cidr: producer-pods, 45.45.45.0/24
      Cluster name: producer-cluster
      

    如需详细了解如何创建 VPC 网络,请参阅创建 VPC 网络

  2. 借助在上一步中使用 PUPI 范围创建的 VPC 网络和子网,您可以创建两个 GKE 集群(producerconsumer)。

    1. 使用提供方网络和子网创建 producer 集群,如下所示:

      gcloud container clusters create PRODUCER_CLUSTER_NAME \
          --enable-ip-alias \
          --network=NETWORK_NAME \
          --subnetwork=SUBNETWORK_NAME \
          --cluster-secondary-range-name=PRODUCER_PODS \
          --services-secondary-range-name=PRODUCER_SERVICES \
          --num-nodes=1 \
          --zone=PRODUCER_ZONE_NAME \
          --project=PRODUCER_PROJECT_NAME
      

      替换以下内容:

      • PRODUCER_CLUSTER_NAME:GKE 提供方集群的名称。
      • COMPUTE_LOCATION:集群的 Compute Engine 位置
      • PRODUCER_SUBNET_NAME:现有子网的名称。 子网的主要 IP 地址范围用于节点。子网必须位于集群所使用的区域中。如果省略此项,GKE 会尝试使用集群所在区域的 default VPC 网络中的子网。
      • 如果次要范围分配方法由 GKE 管理:
        • POD_IP_RANGE:以 CIDR 表示法表示的 IP 地址范围(例如 10.0.0.0/14),或 CIDR 地址块的子网掩码大小(例如 /14)。此项用于为 Pod 创建子网次要 IP 地址范围。如果您省略 --cluster-ipv4-cidr 选项,GKE 会自动选择 /14 范围(218 个地址)。系统会从 10.0.0.0/8(范围为 224 个地址)随机选择自动选择的范围。
        • SERVICES_IP_RANGE:以 CIDR 表示法表示的 IP 地址范围(例如 10.4.0.0/19)或 CIDR 地址块的子网掩码大小(例如 /19)。此项用于为 Service 创建子网次要 IP 地址范围。
      • 如果次要范围分配方法由用户管理
        • SECONDARY_RANGE_PODS:指定的 SUBNET_NAME 中现有次要 IP 地址范围的名称。GKE 将整个子网次要 IP 地址范围用于集群的 Pod。
        • SECONDARY_RANGE_SERVICES:指定项中现有次要 IP 地址范围的名称。
    2. 使用使用方网络和子网创建 consumer 集群,如下所示:

      gcloud container clusters create CONSUMER_CLUSTER_NAME \
          --enable-ip-alias \
          --network=CONSUMER_NETWORK_NAME \
          --subnetwork=CONSUMER_SUBNETWORK_NAME \
          --cluster-secondary-range-name=CONSUMER_PODS \
          --services-secondary-range-name=CONSUMER_SERVICES \
          --num-nodes=1 \
          --zone=CONSUMER_ZONE \
          --project=CONSUMER_PROJECT
      

      替换以下内容:

      • CONSUMER_CLUSTER_NAME:GKE 使用方集群的名称。
      • COMPUTE_LOCATION:集群的 Compute Engine 位置
      • CONSUMER_SUBNET_NAME:现有子网的名称。 子网的主要 IP 地址范围用于节点。子网必须位于集群所使用的区域中。如果省略此项,GKE 会尝试使用集群所在区域的 default VPC 网络中的子网。
      • 如果次要范围分配方法由 GKE 管理
        • POD_IP_RANGE:以 CIDR 表示法表示的 IP 地址范围(例如 10.0.0.0/14),或 CIDR 地址块的子网掩码大小(例如 /14)。此项用于为 Pod 创建子网次要 IP 地址范围。如果您省略 --cluster-ipv4-cidr 选项,GKE 会自动选择 /14 范围(218 个地址)。系统会从 10.0.0.0/8(范围为 224 个地址)随机选择自动选择的范围,且该范围不会包括分配给虚拟机和现有路由的 IP 地址范围,也不会包括分配给其他集群的范围。自动选择的范围可能与预留的 IP 地址动态路由或与此集群建立对等互连的 VPC 内的路由相冲突。如果您使用其中任一项,则应指定 --cluster-ipv4-cidr 以防止发生冲突。
        • SERVICES_IP_RANGE:以 CIDR 表示法表示的 IP 地址范围(例如 10.4.0.0/19)或 CIDR 地址块的子网掩码大小(例如 /19)。此项用于为 Service 创建子网次要 IP 地址范围。
      • 如果次要范围分配方法由用户管理
        • SECONDARY_RANGE_PODS:指定的 SUBNET_NAME 中现有次要 IP 地址范围的名称。GKE 将整个子网次要 IP 地址范围用于集群的 Pod。
        • SECONDARY_RANGE_SERVICES:指定项中现有次要 IP 地址范围的名称。

    如需详细了解如何创建集群,请参阅创建集群

  3. 在 consumer-vpc 网络和 producer-vpc 网络之间建立 VPC 对等互连关系,如下所示:

    • 如需将 consumer 网络连接到提供方,请运行以下命令:

      gcloud compute networks peerings create PEERING_NAME \
          --project=consumer_project \
          --network=consumer \
          --peer-network=producer
      
    • 如需将 producer 网络连接到使用方,请运行以下命令:

      gcloud compute networks peerings create PEERING_NAME \
          --project=producer_project \
          --network=producer \
          --peer-network=consumer \
          --no-export-subnet-routes-with-public-ip \
          --import-subnet-routes-with-public-ip
      

    替换以下内容:

    • PEERING_NAME:GKE 提供方集群的名称。
    • CONSUMER_CLUSTER_NAME:GKE 使用方集群的名称。

    默认情况下,使用方 VPC 会导出 PUPI 地址。创建提供方 VPC 时,请使用以下参数将 VPC 配置为导入 PUPI 地址,但不导出它们:

    --no-export-subnet-routes-with-public-ip
    --import-subnet-routes-with-public-ip
    

验证网络和子网

  1. 验证提供方网络:

    gcloud compute networks describe producer \
        --project=producer_project
    

    输出类似于以下内容:

    ...
    kind: compute#network
    name: producer
    peerings:
    - autoCreateRoutes: true
      exchangeSubnetRoutes: true
      exportCustomRoutes: false
      exportSubnetRoutesWithPublicIp: false
      importCustomRoutes: false
      importSubnetRoutesWithPublicIp: true
      name: producer-peer-consumer
    …
    
  2. 验证提供方子网:

    gcloud compute networks subnets describe producer-subnet \
        --project=producer_project\
        --region=producer_region
    

    输出类似于以下内容:

    ...
    ipCidrRange: 10.128.0.0/24
    kind: compute#subnetwork
    name: producer-subnet
    …
    secondaryIpRanges:
    - ipCidrRange: 172.16.45.0/24
      rangeName: producer-services
    - ipCidrRange: 45.45.45.0/24
      rangeName: producer-pods
    …
    
  3. 验证使用方网络:

    gcloud compute networks subnets describe consumer-subnet \
        --project=consumer_project \
        --region=consumer_region
    

    输出类似于以下内容:

    ...
    kind: compute#network
    name: consumer
    peerings:
    - autoCreateRoutes: true
      exchangeSubnetRoutes: true
      exportCustomRoutes: false
      exportSubnetRoutesWithPublicIp: true
      importCustomRoutes: false
      importSubnetRoutesWithPublicIp: false
      name: consumer-peer-producer
    ...
    
  4. 验证使用方子网:

    gcloud compute networks describe consumer \
    --project=consumer_project
    

    输出类似于以下内容:

    ...
    ipCidrRange: 10.129.0.0/24
    kind: compute#subnetwork
    name: consumer-subnet
    ...
    secondaryIpRanges:
    - ipCidrRange: 172.16.5.0/24
      rangeName: consumer-services
    - ipCidrRange: 5.5.5.0/24
      rangeName: consumer-pods
    ...
    

验证 GKE 集群及其资源

  1. 获取使用方集群凭据:

    gcloud container clusters get-credentials consumer-cluster \
        --project=consumer_project \
        --zone=consumer_zone
    

    输出类似于以下内容:

    ...
    Fetching cluster endpoint and auth data.
    kubeconfig entry generated for consumer-cluster.
    ...
    
  2. 安装并验证 helloapp

    或者,您也可以将以下清单保存为 deployment.yaml

    kubectl apply -f - <<'EOF'
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: helloweb
      labels:
        app: hello
    spec:
      selector:
        matchLabels:
          app: hello
          tier: web
      template:
        metadata:
          labels:
            app: hello
            tier: web
        spec:
          containers:
          - name: hello-app
            image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
            ports:
            - containerPort: 8080
            resources:
              requests:
                cpu: 200m
    EOF
    
  3. 应用 deployment.yaml:

    kubectl apply -f
    
  4. 验证 helloweb Deployment。

    kubectl get deployment helloweb
    

    输出类似于以下内容:

    ...
    NAME       READY   UP-TO-DATE   AVAILABLE   AGE
    helloweb   1/1     1            1           10s
    ...
    

验证解决方案

  1. 验证是否已成功创建 VPC 对等互连:

    gcloud compute networks peerings list
    

    输出类似于以下内容,其中显示了名为使用方和提供方的对等互连:

    NAME                                     NETWORK    PEER_PROJECT                PEER_NETWORK                            STACK_TYPE  PEER_MTU  IMPORT_CUSTOM_ROUTES  EXPORT_CUSTOM_ROUTES  STATE   STATE_DETAILS
    consumer-peer-producer                   consumer   <project_name>            producer                                IPV4_ONLY   1460      False                 False                 ACTIVE  [2023-08-07T13:14:57.178-07:00]: Connected.
    producer-peer-consumer                   producer   <project_name>             consumer                                IPV4_ONLY   1460      False                 False                 ACTIVE  [2023-08-07T13:14:57.178-07:00]: Connected.
    
  2. 验证使用方 VPC 是否导出 PUPI 路由:

    gcloud compute networks peerings list-routes consumer-peer-producer \
        --direction=OUTGOING \
        --network=consumer \
        --region=<consumer_region>
    

    输出类似于以下内容,其中显示了全部三个使用方 CIDR 地址块:

    DEST_RANGE     TYPE                  NEXT_HOP_REGION  PRIORITY  STATUS
    10.129.0.0/24  SUBNET_PEERING_ROUTE  us-central1      0         accepted by peer
    172.16.5.0/24  SUBNET_PEERING_ROUTE  us-central1      0         accepted by peer
    5.5.5.0/24     SUBNET_PEERING_ROUTE  us-central1      0         accepted by peer
    
  3. 验证提供方 VCP 导入的 PUPI 路由:

    gcloud compute networks peerings list-routes producer-peer-consumer \
        --direction=INCOMING \
        --network=producer \
        --region=<producer_region>
    

    输出类似于以下内容,其中显示了全部三个使用方 CIDR 地址块:

    DEST_RANGE     TYPE                  NEXT_HOP_REGION  PRIORITY  STATUS
    10.129.0.0/24  SUBNET_PEERING_ROUTE  us-central1      0         accepted
    172.16.5.0/24  SUBNET_PEERING_ROUTE  us-central1      0         accepted
    5.5.5.0/24     SUBNET_PEERING_ROUTE  us-central1      0         accepted
    
  4. 验证 GKE Pod 是否拥有 PUPI 地址:

    kubectl get pod -o wide
    

    输出类似于以下内容,其中显示 Pod 的 IP 地址在 5.5.5/24 范围内。

    NAME                        READY   STATUS    RESTARTS   AGE   IP         NODE                                              NOMINATED NODE   READINESS GATES
    helloweb-575d78464d-xfklj   1/1     Running   0          28m   5.5.5.16   gke-consumer-cluster-default-pool-e62b6542-dp5f   <none>           <none>
    

后续步骤