部署网关


本页面介绍了如何部署 Kubernetes Gateway 资源,以将入站流量负载均衡到单个 Google Kubernetes Engine (GKE) 集群。

如需部署 Gateway 以跨多个集群(或舰队)对入站流量进行负载均衡,请参阅部署多集群 Gateway

准备工作

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

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

GKE Gateway Controller 要求

  • 对于标准版,需要 GKE 1.24 或更高版本。
  • 对于 Autopilot,需要 GKE 1.26 或更高版本。
  • Google Cloud CLI 407.0.0 版或更高版本。
  • VPC 原生集群支持 Gateway API。
  • 如果您使用的是内部 GatewayClass,则必须启用代理专用子网
  • 集群必须启用 HttpLoadBalancing 插件。
  • 如果您使用的是 Istio,则必须将 Istio 升级到以下版本之一:
    • 1.15.2 或更高版本
    • 1.14.5 或更高版本
    • 1.13.9 或更高版本。
  • 如果您使用的是共享 VPC,则需要在宿主项目中将 Compute Network User 角色分配给服务项目的 GKE 服务账号。

限制和局限

  • GKE GatewayClass 支持不同的功能,具体取决于它们使用的负载均衡器。如需详细了解每个 GatewayClass 支持的不同功能,请参阅 GatewayClass 功能

  • 您不能使用 FrontendConfigBackendConfig 配置网关,必须使用政策

  • GKE 网关的行为与 Ingress 不同,因为网关不会推断健康检查参数。如果您的 Service 没有为 GET / 请求返回 200,或者您有其他调整的 Pod 就绪性检查,则需要为 Service 配置 HealthCheckPolicy

  • 您可以在 Google Cloud 控制台中查看 GKE 为网关创建的负载均衡器资源,但这些资源不会引用它们所连接的网关或 GKE 集群。

  • 您无法使用网关自动生成 Google 管理的 SSL 证书,但可以手动创建和引用 Google 管理的 SSL 证书。如需了解详情,请参阅保护网关安全

  • HTTPRoute 是唯一受支持的路由类型。不支持 TCPRoute、UDPRoute 和 TLSRoute。如需查看 GKE Gateway Controller 支持的字段列表,请参阅 GatewayClass 功能

  • 使用网关或路径重定向的自定义请求和响应标头以及使用网关的网址重写仅适用于 GKE 1.27 版或更高版本。

  • 对于使用网关和路径重定向的自定义请求和响应标头以及使用网关的网址重写,不支持 GatewayClass gke-l7-gxlb
  • 不支持以下 Google Cloud 标头变量:

    • cdn_cache_id(GKE 网关不支持 Cloud CDN)
    • cdn_cache_status(GKE 网关不支持 Cloud CDN)
    • origin_request_header(GKE 网关不支持 CORS)
  • GKE Gateway 不支持 Cloud CDN 负载均衡功能。

  • 不支持双向 TLS 自定义标头(GKE 网关不支持 mTLS)

  • Google Cloud 传统应用负载均衡器限制适用于 GKE 网关,还有一项额外的限制:

    • 您不能在后端服务中配置自定义主机响应标头。
  • 路径重定向和网址重写是互斥的,您不能在同一规则中同时使用这两个过滤条件。

  • Cloud Load Balancing 不支持将流量重定向到其他端口。如需查看 GKE Gateway Controller 支持的字段列表,请参阅 GatewayClass 功能

  • GKE 网关不支持通配符、正则表达式和动态网址

  • 如果您指定具有区域级外部网关类的网关,则控制器会预配内部 IP 地址而不是外部地址。 如需了解如何将已命名的地址与区域级外部应用负载均衡器结合使用,请参阅部署区域级外部网关

  • 网关利用独立 NEG 来预配网络端点组。为了确保网关控制器正确协调负载均衡器配置,您无法修改作为网关一部分的 Service 的 cloud.google.com/neg 注解。

  • GKE Gateway 不支持引用 GKE Ingress 也引用的 Service。

  • Gateway 配置为预配 IP 地址时,不支持更改 Gateway.spec.gatewayClass。为确保网关控制器正确协调负载均衡器,请删除现有网关,并使用更新后的 gatewayClass 值重新部署清单。

  • 不支持 networking.gke.io/app-protocols 注解。请改用 appProtocol 字段来实现相同的结果。

在集群中启用 Gateway API

在 GKE 中使用 Gateway 资源之前,您的集群必须启用 Gateway API。

创建启用 Gateway API 的新集群

从 GKE 1.26 版开始,GKE 在 Autopilot 集群上支持 Gateway API。如果您在 GKE 1.26 及更高版本上创建新的 Autopilot 集群,Gateway API 是默认启用的。对于 GKE 1.25 及更低版本上的现有集群,Gateway API 默认停用。

Autopilot

创建启用 Gateway API 的新 GKE Autopilot 集群:

  gcloud container clusters create-auto CLUSTER_NAME \
      --location=CLUSTER_LOCATION \
      --release-channel=RELEASE_CHANNEL \
      --cluster-version=VERSION

替换以下内容:

  • CLUSTER_NAME:集群的名称。
  • CLUSTER_LOCATION:新集群的 Compute Engine 区域或可用区
  • RELEASE_CHANNEL:发布渠道的名称。
  • VERSION:GKE 版本,必须为 1.26 或更高版本。您还可以使用 --release-channel 标志来选择发布渠道。发布渠道必须具有默认版本 1.26 或更高版本。

Standard

使用 GKE Standard 时,Gateway API 由 --gateway-api 标志控制。启用时使用值 standard,停用时则使用值 disabled。

创建启用 Gateway API 的新 VPC 原生 GKE 集群:

  gcloud container clusters create CLUSTER_NAME \
    --gateway-api=standard \
    --cluster-version=VERSION \
    --location=CLUSTER_LOCATION

替换以下内容:

  • RELEASE_CHANNEL:发布渠道的名称。
  • CLUSTER_NAME:集群的名称。
  • VERSION:GKE 版本,必须为 1.24 或更高版本。您还可以使用 --release-channel 标志来选择发布渠道。发布渠道必须具有默认版本 1.24 或更高版本。
  • CLUSTER_LOCATION:新集群的 Compute Engine 区域或可用区

--gateway-api=standard 标志指示 GKE 使用集群安装 v1beta1 CRD。

在现有集群上启用 Gateway API

确保您的 Autopilot 集群版本为 1.26 或更高版本,并且 Standard 集群版本为 1.24 或更高版本。

如需在现有 GKE 集群(Autopilot 或 Standard)上启用 Gateway API,请使用以下命令:

gcloud container clusters update CLUSTER_NAME \
    --location=CLUSTER_LOCATION\
    --gateway-api=standard

替换以下内容:

--gateway-api=standard 标志指示 GKE 使用集群安装 v1beta1 CRD。

验证集群

创建或升级集群后,GKE Gateway Controller 会自动安装 GatewayClass。控制器可能需要几分钟时间才能识别 CRD 并安装 GatewayClass。

  1. 确认已在 GKE 控制平面中启用 Gateway API:

    gcloud container clusters describe CLUSTER_NAME \
      --location=CLUSTER_LOCATION \
      --format json
    

    输出类似于以下内容:如果此输出为空,请再次运行集群更新命令

    "networkConfig": {
      ...
      "gatewayApiConfig": {
        "channel": "CHANNEL_STANDARD"
      },
      ...
    },
    
  2. 确认您的集群中安装了 GatewayClass:

    kubectl get gatewayclass
    

    输出类似于以下内容:

    NAME                             CONTROLLER                  ACCEPTED   AGE
    gke-l7-global-external-managed   networking.gke.io/gateway   True       16h
    gke-l7-regional-external-managed networking.gke.io/gateway   True       16h
    gke-l7-gxlb                      networking.gke.io/gateway   True       16h
    gke-l7-rilb                      networking.gke.io/gateway   True       16h
    

如需了解每个 GatewayClass 的功能,请参阅 GatewayClass 功能

部署内部网关

内部网关公开只能从 VPC 或连接到 VPC 的网络访问的应用。

部署区域级内部网关

以下示例展示了如何部署区域性内部网关,以便实现在特定地理区域内服务之间的高效安全通信。

配置代理专用子网

您必须先配置代理专用子网,然后才能创建使用内部应用负载均衡器的网关。在使用内部应用负载均衡器的 VPC 中,每个区域都必须具有一个代理专用子网。此子网为负载均衡器代理提供了内部 IP 地址。

  1. 创建代理专用子网:

    gcloud compute networks subnets create SUBNET_NAME \
        --purpose=REGIONAL_MANAGED_PROXY \
        --role=ACTIVE \
        --region=COMPUTE_REGION \
        --network=VPC_NETWORK_NAME \
        --range=CIDR_RANGE
    

    替换以下内容:

    • SUBNET_NAME:代理专用子网的名称。
    • COMPUTE_REGION:代理专用子网的区域。
    • VPC_NETWORK_NAME:包含子网的 VPC 网络的名称。
    • CIDR_RANGE:子网的主要 IP 地址范围。使用的子网掩码长度不得超过 /26,以确保至少有 64 个 IP 地址可用于该区域中的代理。建议的子网掩码为 /23
  2. 验证代理专用子网:

    gcloud compute networks subnets describe SUBNET_NAME \
        --region=COMPUTE_REGION
    

    输出类似于以下内容:

    ...
    gatewayAddress: 10.1.1.1
    ipCidrRange: 10.1.1.0/24
    kind: compute#subnetwork
    name: proxy-subnet
    network: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/global/networks/default
    privateIpGoogleAccess: false
    privateIpv6GoogleAccess: DISABLE_GOOGLE_ACCESS
    purpose: REGIONAL_MANAGED_PROXY
    region: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION
    role: ACTIVE
    selfLink: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION/subnetworks/proxy-subnet
    state: READY
    

创建网关

网关资源表示在 Kubernetes 中路由流量的数据层面。网关可表示许多不同类型的负载均衡和路由,具体取决于派生网关的 GatewayClass。如需详细了解网关资源,请参阅网关资源说明或 API 规范

在这种情况下,GKE 集群的管理员需要创建一个网关,可供不同团队用于在内部公开其应用。管理员部署网关,应用团队独立部署其路由并将路由连接到此网关。

  1. 将以下网关清单保存到名为 gateway.yaml 的文件中:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: internal-http
    spec:
      gatewayClassName: gke-l7-rilb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
    

    此清单包含以下字段:

    • gatewayClassName: gke-l7-rilb:指定派生此网关的 GatewayClass。gke-l7-rilb 对应于内部应用负载均衡器。
    • port: 80 指定网关仅开放端口 80 来监听 HTTP 流量。
  2. 在您的集群中部署网关:

    kubectl apply -f gateway.yaml
    
  3. 验证网关是否已正确部署。部署其所有资源可能需要几分钟时间。

    kubectl describe gateways.gateway.networking.k8s.io internal-http
    

    输出类似于以下内容:

    Name:         internal-http
    Namespace:    default
    Spec:
      Gateway Class Name:  gke-l7-rilb
      Listeners:
        Allowed Routes:
          Kinds:
            Group:  gateway.networking.k8s.io
            Kind:   HTTPRoute
          Namespaces:
            From:  Same
        Name:      http
        Port:      80
        Protocol:  HTTP
    Status:
      Addresses:
        Type:   IPAddress
        Value:  192.168.1.14
      Conditions:
        Last Transition Time:  1970-01-01T00:00:00Z
        Message:               Waiting for controller
        Reason:                NotReconciled
        Status:                False
        Type:                  Scheduled
    Events:
      Type    Reason  Age                From                       Message
      ----    ------  ----               ----                       -------
      Normal  ADD     92s                networking.gke.io/gateway  test/internal-http
      Normal  UPDATE  45s (x3 over 91s)  networking.gke.io/gateway  test/internal-http
      Normal  SYNC    45s                networking.gke.io/gateway  SYNC on test/internal-http was a success
    

    此时,您的集群中部署了一个网关,该网关已预配负载均衡器和 IP 地址。但是,该网关没有路由,因此不知道应该如何将流量发送到后端。如果没有路由,所有流量都会流向默认后端,这会返回 HTTP 404。接下来,您将部署应用和路由,告知网关如何到达应用后端。

部署演示应用

应用团队可以独立于网关的部署部署他们的应用和路由。在某些情况下,应用团队可能还希望拥有网关,并自行将其部署为专用于应用的资源。如需了解网关和路由的不同所有权模型,请参阅路由绑定。不过在此示例中,商店团队会部署其应用以及通过在上一部分中创建的 internal-http 网关公开其应用的附带 HTTPRoute。

HTTPRoute 资源有许多可配置的字段可用于流量匹配。如需了解 HTTPRoute 字段的说明,请参阅 API 规范

  1. 将商店应用(store-v1、store-v2 和 store-german 部署)部署到您的集群:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
    

    这将创建三个 Deployment 和三个 Service,分别名为 store-v1、store-v2 和 store-german。

  2. 验证应用已成功部署:

    kubectl get pod
    

    应用运行后,输出类似于以下内容:

    NAME                        READY   STATUS    RESTARTS   AGE
    store-german-66dcb75977-5gr2n   1/1     Running   0          38s
    store-v1-65b47557df-jkjbm       1/1     Running   0          14m
    store-v2-6856f59f7f-sq889       1/1     Running   0          14m
    
  3. 验证 Service 已部署:

    kubectl get service
    

    输出会显示每个商店 Deployment 的 Service:

    NAME           TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    store-german   ClusterIP   10.48.3.183   <none>        8080/TCP   4s
    store-v1       ClusterIP   10.48.2.224   <none>        8080/TCP   5s
    store-v2       ClusterIP   10.48.4.48    <none>        8080/TCP   5s
    

部署 HTTPRoute

路由资源定义了用于将流量从网关映射到 Kubernetes 后端的特定于协议的规则。HTTPRoute 资源会执行 HTTP 和 HTTPS 流量匹配和过滤,并且受所有 gke-l7 GatewayClass 支持。

在本部分中,您将部署一个 HTTPRoute,它会使用访问您的商店应用所需的路由规则对网关进行编程。

  1. 将以下 HTTPRoute 清单保存到名为 store-route.yaml 的文件中:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - name: store-v1
          port: 8080
      - matches:
        - headers:
          - name: env
            value: canary
        backendRefs:
        - name: store-v2
          port: 8080
      - matches:
        - path:
            value: /de
        backendRefs:
        - name: store-german
          port: 8080
    
  2. 在集群中部署 HTTPRoute:

    kubectl apply -f store-route.yaml
    

    store HTTPRoute 使用 parentRefs 属性绑定到 internal-http 网关:这些路由规则在底层的负载均衡器上配置,如下图所示:

    由商店 HTTPRoute 配置的路由规则

    这些路由规则通过以下方式处理 HTTP 流量:

    • 发送到 store.example.com/de 的流量路由到 Service store-german
    • 发送到 store.example.com 且具有 HTTP 标头 "env: canary" 的流量路由到 Service store-v2
    • 发送到 store.example.com 的其余流量路由到 Service store-v1
  3. 验证 HTTPRoute 已部署:

    kubectl describe httproute store
    

    输出类似于以下内容:

    Name:         store
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         HTTPRoute
    <...>
    Spec:
      Hostnames:
        store.example.com
      Parent Refs:
        Group:  gateway.networking.k8s.io
        Kind:   Gateway
        Name:   internal-http
      Rules:
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v1
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v2
          Port:    8080
          Weight:  1
        Matches:
          Headers:
            Name:   env
            Type:   Exact
            Value:  canary
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-german
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /de
    Status:
      Parents:
        Conditions:
          Last Transition Time:  2022-11-01T04:18:52Z
          Message:
          Reason:                Accepted
          Status:                True
          Type:                  Accepted
          Last Transition Time:  2022-11-01T04:18:52Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   internal-http
    Events:
      Type    Reason  Age                From                   Message
      ----    ------  ----               ----                   -------
      Normal  ADD     24m                sc-gateway-controller  default/store
      Normal  SYNC    16m (x4 over 23m)  sc-gateway-controller  Bind of HTTPRoute "default/store" to ParentRef {Group:       gateway.networking.k8s.io",
      <...>
    
  4. 验证 HTTPRoute 已绑定到网关:

    kubectl describe gateway
    

    输出类似于以下内容:

    Name:         internal-http
    Namespace:    default
    Labels:       <none>
    <...>
    Status:
      Addresses:
        Type:   IPAddress
        Value:  10.128.15.203
      Conditions:
        Last Transition Time:  2022-11-01T03:47:01Z
        Message:
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2022-11-01T03:47:01Z
        Message:
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2022-11-01T03:47:01Z
          Message:
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    http
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
          <...>
    

将流量发送到应用

现在,网关、路由和应用已在集群中部署,您可以将流量传递到您的应用。

  1. 从网关检索 IP 地址,以便将流量发送到您的应用:

    kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}"
    

    输出为一个 IP 地址。

  2. 在与集群连接的虚拟机 (VM) 实例上,通过 shell 将流量发送到此 IP 地址。为此,您可以创建一个虚拟机。这是必要的操作,因为网关具有内部 IP 地址,并且只能从 VPC 网络内部访问。由于 internal-http 是区域级负载均衡器,因此客户端 shell 必须与 GKE 集群位于同一区域。

    由于您没有 example.com 主机名,因此请手动设置主机标头,以便观察流量路由。首先尝试请求 store.example.com:

    curl -H "host: store.example.com" VIP
    

    VIP 替换为上一步中的 IP 地址。

    演示应用的输出显示了应用运行位置的相关信息:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v1-84b47c7f58-pmgmk",
      "pod_name_emoji": "💇🏼‍♀️",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:31:17",
      "zone": "ZONE_NAME"
    }
    
  3. 转到 store.example.com/de 中的德语版商店服务,测试路径匹配:

    curl -H "host: store.example.com" VIP/de
    

    输出会确认请求已由 store-german Pod 处理:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "Gutentag!", 
      "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal",
      "pod_name": "store-german-5cb6474c55-lq5pl", 
      "pod_name_emoji": "🧞‍♀",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:35:37",
      "zone": "ZONE_NAME"
    }
    
  4. 最后,使用 env: canary HTTP 标头将流量发送到 Canary 版商店服务:

    curl -H "host: store.example.com" -H "env: canary " VIP
    

    输出会确认请求已由 store-v2 Pod 处理:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v2", 
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v2-5788476cbd-s9thb", 
      "pod_name_emoji": "🦰",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:38:26",
      "zone": "ZONE_NAME"
    }
    

部署外部网关

外部网关公开可从互联网或 VPC 外部网络访问的应用。外部网关部署与内部网关部署类似,但您必须保护应用的安全,因为公共互联网可以访问网关。

您可以通过两种方式创建外部网关:全球级外部网关或区域级外部网关。

全球外部网关使用全球 IP 地址(或任播 IP 地址)作为在所有 Google Cloud Compute 区域中通告的网关的前端。将流量发送到此任播 IP 地址的客户端会路由到通告该 IP 地址的最近 Google 位置。全球外部网关仅在高级网络服务层级提供。

区域级外部网关使用区域级 IP 地址作为网关的前端,该网关仅在部署区域级外部网关的本地 Google Cloud Compute 区域中通告。将流量发送到此区域级 IP 地址的客户端会由其本地 ISP 和互联网进行路由,然后再到达通告该 IP 地址的 Google 区域。区域级外部网关仅在标准网络服务层级提供。

部署全球外部网关

以下示例展示了如何将多个证书附加到全球外部网关并将证书分组到证书映射,并使用 Certificate Manager 和 HTTPRoute 公开商店应用。

创建证书映射

如果每个网关需要 15 个或更多证书或者您需要使用通配符证书,Google 建议使用 Certificate Manager 来管理证书。

您还可以使用 Kubernetes Secret 或 Google 管理的 SSL 证书来保护外部网关。如需了解详情,请参阅网关安全性

在本部分中,您将使用 Certificate Manager 创建证书,以保护集群上运行的应用。

  1. 启用 Certificate Manager API:

    gcloud services enable certificatemanager.googleapis.com
    
  2. 创建证书映射:

    gcloud beta certificate-manager maps create store-example-com-map
    
  3. 将 Google 管理的证书和密钥加载到证书中:

    gcloud beta certificate-manager certificates create store-example-com-cert \
        --certificate-file="CERTIFICATE_FILE" \
        --private-key-file="PRIVATE_KEY_FILE"
    

    替换以下内容:

    • CERTIFICATE_FILE:您选择的新文件的名称。文件必须具有扩展名 .pem。例如 cert.pem
    • PRIVATE_KEY_FILE:您的私钥文件的名称。

    如需了解详情,请参阅创建私钥和证书

  4. 创建将证书分配给证书映射的 CertificateMapEntry

    gcloud beta certificate-manager maps entries create store-example-com-map-entry \
        --map=store-example-com-map \
        --hostname=store.example.com \
        --certificates=store-example-com-cert
    

如需了解如何使用其他证书来源(例如 Kubernetes Secret 或 SSL 证书)保护网关,请参阅保护网关安全

创建网关

网关资源表示在 Kubernetes 中路由流量的数据层面。网关可以表示许多不同类型的负载均衡和路由,具体取决于其使用的 GatewayClass。

如需详细了解网关资源,请参阅网关资源说明或 API 规范

在本部分中,您将创建一个网关。应用团队可以独立部署路由并将其安全地附加到网关,从而使用网关将应用公开给互联网。

  1. 将以下清单保存到名为 gateway.yaml 的文件中:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: external-http
      annotations:
        networking.gke.io/certmap: store-example-com-map
    spec:
      gatewayClassName: gke-l7-global-external-managed
      listeners:
      - name: https
        protocol: HTTPS
        port: 443
    
    

    此清单描述了具有以下字段的网关:

    • gatewayClassName: gke-l7-global-external-managed:指定此网关的 GatewayClass。此网关类使用全球外部应用负载均衡器。
    • protocol: HTTPSport: 443:指定网关为 HTTPS 流量开放端口 443。这些字段会启用 TLS。
    • networking.gke.io/certmap: store-example-com-map:指定 Certificate Manager 中证书映射的名称。

    没有 TLS 部分,因为 TLS 是使用注解 networking.gke.io/certmap 以及使用 Certificate Manager 配置的。

  2. 将清单应用到您的集群:

    kubectl apply -f gateway.yaml
    

    GKE 可能需要几分钟时间来部署资源。

  3. 验证网关已成功部署:

    kubectl describe gateway
    

    输出类似于以下内容:

    Name:         external-http
    Namespace:    default
    Labels:       <none>
    ...
    Spec:
      Gateway Class Name:  gke-l7-global-external-managed
      Listeners:
        Allowed Routes:
          Namespaces:
            From:  Same
        Name:      https
        Port:      443
        Protocol:  HTTPS
        Tls:
          Certificate Refs:
            Group:
            Kind:   Secret
            Name:   store-example-com
          Mode:     Terminate
     ...
    

    此输出显示集群中部署的网关具有负载均衡器和公共 IP 地址。该网关没有路由,这意味着它无法将流量发送到后端。如果没有路由,所有流量都会流向默认后端,这会返回 HTTP 404 响应。在下一部分中,您将部署路由,以指示网关将流量发送到后端。

部署演示应用

应用团队可以独立于网关的部署部署他们的应用和路由。在某些情况下,应用团队可能还希望拥有网关,并自行将其部署为专用于其应用的资源。如需了解网关和路由的不同所有权模型,请参阅路由绑定。在此示例中,商店团队会部署应用和附带的 HTTPRoute,以通过在上一部分中创建的 external-http 网关公开应用。

如需详细了解 HTTPRoute 字段,请参阅 API 规范

  1. 将示例应用部署到您的集群:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
    

    此示例应用创建了三个 Deployment 和三个 Service,分别名为 store-v1store-v2store-german

  2. 验证应用已成功部署:

    kubectl get pod
    

    输出类似于以下内容:

    NAME                            READY   STATUS    RESTARTS   AGE
    store-german-66dcb75977-5gr2n   1/1     Running   0          38s
    store-v1-65b47557df-jkjbm       1/1     Running   0          14m
    store-v2-6856f59f7f-sq889       1/1     Running   0          14m
    
  3. 验证 Service 已成功部署:

    kubectl get service
    

    输出类似于以下内容:

    NAME           TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    store-german   ClusterIP   10.48.3.183   <none>        8080/TCP   4s
    store-v1       ClusterIP   10.48.2.224   <none>        8080/TCP   5s
    store-v2       ClusterIP   10.48.4.48    <none>        8080/TCP   5s
    

创建 HTTPRoute

路由资源定义了用于将流量从网关映射到 Kubernetes 后端的特定于协议的规则。HTTPRoute 资源会执行 HTTP 和 HTTPS 流量匹配和过滤,并且受所有 gke-l7-* GatewayClass 支持。

在本部分中,您将部署 HTTPRoute,它会使用访问示例应用所需的路由规则来配置网关。

  1. 将以下清单保存到名为 store-route-external.yaml 的文件中:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-external
    spec:
      parentRefs:
      - kind: Gateway
        name: external-http
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - name: store-v1
          port: 8080
      - matches:
        - headers:
          - name: env
            value: canary
        backendRefs:
        - name: store-v2
          port: 8080
      - matches:
        - path:
            value: /de
        backendRefs:
        - name: store-german
          port: 8080
    

    此清单描述了引用 external-http 网关的 HTTPRoute。

  2. 将清单应用到您的集群:

    kubectl apply -f store-route-external.yaml
    

    store HTTPRoute 使用 parentRefs 属性绑定到 external-http 网关:下图展示了在底层负载均衡器上配置的路由规则:

    由商店 HTTPRoute 配置的路由规则

    路由规则对 HTTP 流量的处理方式如下:

    • 发送到 store.example.com/de 的流量路由到 Service store-german
    • 发送到 store.example.com 且具有 HTTP 标头 "env: canary" 的流量路由到 Service store-v2
    • 发送到 store.example.com 的其余流量路由到 Service store-v1
  3. 验证 HTTPRoute 已部署:

    kubectl describe httproute store-external
    

    输出类似于以下内容:

    Name:         store-external
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  gateway.networking.k8s.io/v1beta1
    Kind:         HTTPRoute
    <...>
    Spec:
      Hostnames:
        store.example.com
      Parent Refs:
        Group:  gateway.networking.k8s.io
        Kind:   Gateway
        Name:   external-http
      Rules:
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v1
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v2
          Port:    8080
          Weight:  1
        Matches:
          Headers:
            Name:   env
            Type:   Exact
            Value:  canary
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-german
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /de
    Status:
      Parents:
        Conditions:
          Last Transition Time:  2022-11-01T05:42:31Z
          Message:
          Reason:                Accepted
          Status:                True
          Type:                  Accepted
          Last Transition Time:  2022-11-01T05:43:18Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   external-http
    Events:
      Type     Reason  Age    From                   Message
      ----     ------  ----   ----                   -------
      Normal   ADD     2m48s  sc-gateway-controller  default/store-external
      Normal  SYNC  61s (x3 over 2m27s)  sc-gateway-controller  Bind of HTTPRoute "default/store-external" to ParentRef Group:       "gateway.networking.k8s.io",
      ...
    
  4. 验证 HTTPRoute 已绑定到网关:

    kubectl describe gateway external-http
    

    输出类似于以下内容:

    Name:         external-http
    Namespace:    default
    Labels:       <none>
    <...>
    Status:
      Addresses:
        Type:   IPAddress
        Value:  34.149.207.45
      Conditions:
        Last Transition Time:  2022-11-01T05:37:21Z
        Message:
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2022-11-01T05:43:18Z
        Message:
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2022-11-01T05:43:18Z
          Message:
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    https
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
          <...>
    

将流量发送到应用

现在,网关、路由和应用已在集群中部署,您可以将流量传递到您的应用。

  1. 获取网关的 IP 地址:

    kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}"
    

    输出为一个 IP 地址。

  2. 创建一个虚拟机:

    gcloud cloud-shell ssh
    
  3. 将流量从虚拟机发送到网关 IP 地址。您必须手动设置主机标头,因为您不拥有 example.com 主机名。

    curl -H "host: store.example.com" https://GATEWAY_IP_ADDRESS --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
    

    GATEWAY_IP_ADDRESS 替换为上一步中网关的 IP 地址。

    输出显示来自演示版应用有关应用运行位置的信息:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v1-84b47c7f58-pmgmk",
      "pod_name_emoji": "💇🏼‍♀️",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:31:17",
      "zone": "us-central1-a"
    }
    
  4. 转到 store.example.com/de 中的德语版 store 服务,以测试路径匹配:

    curl -H "host: store.example.com" https://GATEWAY_IP_ADDRESS/de --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
    

    输出会确认请求已由 store-german Pod 处理:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "Gutentag!",
      "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal",
      "pod_name": "store-german-5cb6474c55-lq5pl",
      "pod_name_emoji": "🧞‍♀",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:35:37",
      "zone": "us-central1-a"
    }
    
  5. 使用 env: canary HTTP 标头将流量发送到 store 服务的 Canary 版本:

    curl -H "host: store.example.com" -H "env: canary " https://GATEWAY_IP_ADDRESS/de --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
    

    输出会确认请求已由 store-v2 Pod 处理:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v2",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v2-5788476cbd-s9thb",
      "pod_name_emoji": "👩🏿",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:38:26",
      "zone": "us-central1-a"
    }
    

部署区域级外部网关

以下示例展示了如何使用自行管理的证书和 HTTPRoute 公开具有附加到区域外部网关的多份证书的商店应用。

为区域级网关创建代理子网

您必须先配置代理专用子网,然后才能创建使用区域级外部应用负载均衡器的网关。在使用区域级外部应用负载均衡器的 VPC 中,每个区域都必须具有一个 external_managed_proxy 子网。此子网为负载均衡器代理提供了内部 IP 地址。

创建证书以保护您的客户端流量

您可以使用证书授权机构 (CA) 颁发并验证的证书,也可以创建自签名证书。如需详细了解如何创建证书,请参阅将证书存储在 Kubernetes Secret 中

创建区域级外部 HTTP(S) 网关

  1. 为外部负载均衡器创建区域级静态 IP 地址。

    gcloud compute addresses create IP_ADDRESS_NAME \
      --region=COMPUTE_REGION \
      --network-tier=STANDARD
    

    替换以下内容:

    • IP_ADDRESS_NAME:新的静态 IP 地址的名称。
    • COMPUTE_REGION:集群在其中运行的 Compute Engine 区域。
  2. 使用自行管理的证书创建区域级外部应用负载均衡器网关,如下所示,并将清单保存为 regional-gateway.yaml

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: external-regional-http
      spec:
        gatewayClassName: gke-l7-regional-external-managed
        listeners:
        - name: https
          protocol: HTTPS
          port: 443
          tls:
            mode: Terminate
            certificateRefs:
            - name: store-example-com
        addresses:
        - type: NamedAddress
          value: IP_ADDRESS_NAME
    
  3. 应用 regional-gateway 清单:

      kubectl apply -f regional-gateway.yaml
    
  4. 验证配置。

      kubectl get gateway
    

    输出类似于以下内容:

    NAME            CLASS                              ADDRESS         READY   AGE
    external-http   gke-l7-regional-external-managed   35.118.32.224   True    49s
    

    如需了解更多详情,请使用 describe 命令:

    kubectl describe gateway
    

    输出类似于以下内容:

    Name:         external-regional-http
    Namespace:    default
    Labels:       <none>
    ...
    Spec:
      Gateway Class Name:  gke-l7-regional-external-managed
      Listeners:
        Allowed Routes:
          Namespaces:
            From:  Same
        Name:      https
        Port:      443
        Protocol:  HTTPS
        Tls:
          Certificate Refs:
            Group:
            Kind:   Secret
            Name:   store-example-com
          Mode:     Terminate
      ...
    

部署演示应用

您可以独立于 Gateway 的部署来部署应用和路由。

如需详细了解如何部署演示应用,请参阅部署演示应用

创建 HTTPRoute

您必须创建 HTTPRoute 才能执行 HTTP 和 HTTPS 流量匹配和过滤。

将流量发送到应用

部署应用并创建 HTTPRoute 后,您可以将流量传递给应用。

如需详细了解如何将流量发送到应用,请参阅将流量发送到应用

使用共享 Gateway

Gateway API 使用单独的资源(网关和路由资源)来部署负载均衡器和路由规则。这与 Ingress 不同,Ingress 会将所有内容组合到一个资源中。通过在资源之间拆分责任,网关可让负载均衡器及其路由规则单独部署,并由不同用户或团队进行部署。这样一来,网关即可成为共享网关,这些网关与多个不同路由连接,可以完全由独立团队拥有和管理,甚至可以跨不同命名空间。

针对共享网关部署路由

此示例基于部署内部 Gateway中部署的 internal-http Gateway。

在此示例中,网站团队将部署其应用、Service 和HTTPRoute,以将来自 Gateway 的流量与这些 Service 匹配。

  1. 部署示例应用:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/site.yaml
    
  2. 将以下清单保存到名为 site-route-internal.yaml 的文件中:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: site-internal
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "site.example.com"
      rules:
      - backendRefs:
        - name: site-v1
          port: 8080
    

    此清单描述了一个与 site.example.com 的所有流量匹配并将其路由到 site-v1 Service 的 HTTPRoute。

  3. 将清单应用到您的集群:

    kubectl apply -f site-route-internal.yaml
    
  4. 验证 HTTPRoute 是否已连接到 Gateway:

    kubectl describe httproute.gateway.networking.k8s.io site-internal
    

    输出类似于以下内容:

    Status:
      Parents:
        Conditions:
          Last Transition Time:  2023-01-09T15:05:43Z
          Message:
          Reason:                Accepted
          Status:                True
          Type:                  Accepted
          Last Transition Time:  2023-01-09T15:05:43Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   internal-http
          ...
    

    如果 Gateway 的 Accepted 条件为 True,则表示 HTTPRoute 已成功绑定到 Gateway。如需详细了解状态字段,请参阅路由状态

  5. 验证流向 Gateway 的流量是否已正确路由:

    curl -H "host: site.example.com" GATEWAY_IP_ADDRESS
    curl -H "host: store.example.com" GATEWAY_IP_ADDRESS
    

    GATEWAY_IP_ADDRESS 替换为 Gateway 的 IP 地址。

    您必须在 Gateway 所在的 VPC 中使用虚拟机 (VM)。

    输出类似于以下内容:

    {
      "cluster_name": "CLUSTER_NAME",
      "host_header": "site.example.com",
      "metadata": "site-v1",
      "pod_name": "site-v1-5d64fc4d7d-fz6f6",
      "pod_name_emoji": "👩🏼‍🍳",
      "project_id": "PROJECT_ID",
      "timestamp": "2022-11-02T19:07:01",
      "zone": "ZONE_NAME"
    }
    ...
    {
      "cluster_name": "CLUSTER_NAME",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "pod_name": "store-v1-6d8d58d78-vz8pn",
      "pod_name_emoji": "🧝🏻‍♂️",
      "project_id": "PROJECT_ID",
      "timestamp": "2022-11-02T19:07:01",
      "zone": "ZONE_NAME"
    }
    

配置 Gateway 默认后端

所有 gke-l7-* GatewayClass 都会向不匹配的流量返回 HTTP 404。您可以使用显式默认 Route 配置默认后端,该路由会将不匹配的流量发送到用户提供的 Service。

以下 HTTPRoute 示例演示了如何自定义默认后端。如果您应用与以下内容类似的 HTTPRoute,则其优先于隐式默认后端:

kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
  name: custom-default-backend
spec:
  parentRefs:
  - kind: Gateway
    name: my-internal-gateway
  rules:
  - backendRefs:
    - name: my-custom-default-backend-service
      port: 8080

此 HTTPRoute 匹配来自特定网关的所有流量。每个 Gateway 只能有一个规则,否则规则会发生冲突并且优先顺序适用。

您可以使用默认后端来阻止他人创建路由所有 Gateway 流量的默认路由后端。显式 HTTPRoute 始终优先于具有冲突路由规则的新 HTTPRoute。

为 Gateway 配置静态 IP 地址

每个 Gateway 都有一个 IP 地址,用于监听流量。如果您未在 Gateway 上指定 IP 地址,则 Gateway 控制器会自动提供 IP 地址。您还可以创建静态 IP 地址,以使 IP 地址的存在与 Gateway 生命周期无关。

部署网关后,其 IP 地址会显示在状态字段中:

kind: Gateway
...
status:
  addresses:
    - value: 10.15.32.3

根据 GatewayClass,IP 地址是从以下子网分配的:

GatewayClass 默认 IP 地址池
  • gke-l7-rilb
  • gke-l7-rilb-mc
  • 主节点 IPv4/IPv6 地址范围中的区域专用 IP 地址
  • gke-l7-regional-external-managed
  • gke-l7-regional-external-managed-mc
  • Google 的区域外部 IPv4/IPv6 范围中的区域公共 IP 地址
  • gke-l7-global-external-managed
  • gke-l7-global-external-managed-mc
  • gke-l7-gxlb
  • gke-l7-gxlb-mc
  • Google 的全球外部 IPv4/IPv6 范围中的全球公共 IP 地址

    addresses.NamedAddress 字段可让您指定独立于网关的 IP 地址。您可以在网关部署之前创建静态 IP 地址资源,并且 NamedAddress 会引用该资源。即使网关已删除,您也可以重复使用静态 IP 地址。

    使用已命名的 IP 地址

    您可以通过指定 NamedAddress 来配置 IP 地址。您必须先预配静态 IP 地址,然后才能创建 Gateway。

    1. 创建静态 IP 地址资源:

      gcloud compute addresses create IP_ADDRESS_NAME \
          --purpose=SHARED_LOADBALANCER_VIP \
          --region=COMPUTE_REGION \
          --subnet=SUBNET \
          --project=PROJECT_ID
      

      替换以下内容:

      • IP_ADDRESS_NAME:新的静态 IP 地址的名称
      • COMPUTE_REGION:对于区域级 Gateway,是集群在其中运行的 Compute Engine 区域。 对于全球外部 Gateway,不需要此标志。
      • SUBNET:IP 地址的子网。 对于全球外部 Gateway,不需要此标志。
      • PROJECT_ID:GKE 集群在其中运行的项目。
    2. 将以下清单保存到名为 named-ip-gateway.yaml 的文件中:

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: internal-http
      spec:
        gatewayClassName: gke-l7-rilb
        listeners:
        - name: http
          protocol: HTTP
          port: 80
        addresses:
        - type: NamedAddress
          value: IP_ADDRESS_NAME
      

      此清单描述了一个引用已命名的 IP 地址的 Gateway。

    3. 将清单应用到您的集群:

      kubectl apply -f named-ip-gateway.yaml
      
    4. 验证 Gateway IP 地址:

      kubectl describe gateway internal-http
      

      输出类似于以下内容:

      Name:         internal-http
      Namespace:    default
      Labels:       <none>
      ...
      Spec:
        Addresses:
          Type:              NamedAddress
          Value:             IP_ADDRESS_NAME
        Gateway Class Name:  gke-l7-rilb
        Listeners:
          Allowed Routes:
            Namespaces:
              From:  Same
          Name:      http
          Port:      80
          Protocol:  HTTP
      Status:
        Addresses:
          Type:   IPAddress
          Value:  10.15.32.103
      

    配置从 HTTP 到 HTTPS 的重定向

    Cloud Load Balancing 提供从 HTTP 到 HTTPS 的重定向功能。外部应用负载均衡器将未加密的 HTTP 请求重定向到使用相同 IP 地址的 HTTPS 负载均衡器。当您创建启用 HTTP 到 HTTPS 重定向的网关时,系统会自动创建这两个负载均衡器。对端口 80 上网关的外部 IP 地址的请求会自动重定向到端口 443 上的同一外部 IP 地址。

    默认情况下,网关上未定义 HTTP 到 HTTPS 重定向。

    如需将 HTTP 流量重定向到 HTTPS,请配置网关以同时处理 HTTP 和 HTTPS 流量。如果您停用 HTTP 或 HTTPS,则网关不会重定向流量。

    以下示例展示了如何使用 HTTP 到 HTTPS 重定向确保从客户端发送到 Web 应用的流量始终重定向到安全页面。

    重定向来自网关命名空间的 HTTP 流量

    在以下示例中,网关配置为允许 HTTP 监听器上的 Same(来自同一命名空间的连接),而 HTTPS 监听器向所有命名空间开放。若使用此配置,应该只有重定向 HTTPRoute 与网关位于同一命名空间。

    此配置可确保没有其他 HTTPRoute 可以绑定到网关的 HTTP 监听器。这要求 gateway-infra 命名空间中不允许应用团队的 HTTPRoute。

    1. 创建网关的命名空间 gateway-infra。将清单保存为 gateway-namespace.yaml

      apiVersion: v1
      kind: Namespace
      metadata:
        name: gateway-infra
      
    2. 应用清单:

      kubectl apply -f gateway-namespace.yaml
      
    3. 使用以下清单创建网关并将清单保存为 external-gateway.yaml

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: external-http
        namespace: gateway-infra
      spec:
        gatewayClassName: gke-l7-global-external-managed
        listeners:
        - name: http
          protocol: HTTP
          port: 80
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: Same
        - name: https
          protocol: HTTPS
          port: 443
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: All
          tls:
            mode: Terminate
            options:
              networking.gke.io/pre-shared-certs: store-example-com
      
      • allowedRoutes 部分中的 namespaces 字段将 HTTP 监听器限制为网关的命名空间 gateway-infra

      • HTTPS 监听器不包含对允许的命名空间的限制,因此所有命名空间都使用具有 HTTPRoute 的 HTTPS 监听器。

    4. 应用清单:

      kubectl apply -f external-gateway.yaml
      
    5. 如需强制进行 HTTPS 重定向,请使用以下清单创建默认 HTTPRoute 并将清单保存为 redirect-httproute.yaml

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: redirect
        namespace: gateway-infra
      spec:
        parentRefs:
        - namespace: gateway-infra
          name: external-http
          sectionName: http
        rules:
        - filters:
          - type: RequestRedirect
            requestRedirect:
              scheme: https
      
      • sectionName 字段指示网关仅在 HTTP 监听器上匹配。RequestRedirect 过滤条件会强制重定向到 HTTPS 监听器。

      此配置会将在网关端口 80 上收到的所有流量重定向到端口 443 上的监听器,从而在客户端和负载均衡器之间强制执行安全通信。

    6. 应用清单:

      kubectl apply -f redirect-httproute.yaml
      
    7. 使用以下清单为应用创建 Service。将清单保存为 service-deployment.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: store-v1
      spec:
        selector:
          app: store
          version: v1
        ports:
        - port: 8080
          targetPort: 8080
      
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: store-v1
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: store
            version: v1
        template:
          metadata:
            labels:
              app: store
              version: v1
          spec:
            containers:
            - name: whereami
              image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
              ports:
              - containerPort: 8080
              env:
              - name: METADATA
                value: "store-v1"
      
    8. 应用清单:

      kubectl apply -f service-deployment.yaml
      
    9. 为仅允许 HTTPS 的应用创建 HTTPRoute。将清单保存为 httproute.yaml

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: store-external
        labels:
          gateway: external-http
      spec:
        parentRefs:
        - name: external-http
          namespace: gateway-infra
          sectionName: https
        hostnames:
        - "store.example.com"
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
      
    10. 应用清单:

      kubectl apply -f httproute.yaml
      

    重定向来自基础架构命名空间的 HTTP 流量

    在某些情况下,基础架构或平台管理团队与应用团队之间没有明显的区别,因此防止网关滥用可能成为一个难题。

    以下示例进一步限制了 HTTP 监听器的使用,以防止应用团队意外使用非安全协议。此示例将网关配置为仅当路由在给定命名空间 (http-redirect) 中时才允许 HTTPRoute 使用 HTTP 监听器,同时它将 HTTPS 监听器向所有命名空间开放。您可以使用 Kubernetes RBAC 限制 http-redirect 命名空间,这样应用团队就不会错误地在此命名空间中创建 HTTPRoute。

    1. 创建网关的命名空间。将清单保存为 gateway-namespace.yaml

      apiVersion: v1
      kind: Namespace
      metadata:
        name: gateway-infra
      
    2. 应用清单:

      kubectl apply -f gateway-namespace.yaml
      
    3. 创建网关的命名空间,并将清单保存为 redirect-namespace.yaml

      apiVersion: v1
      kind: Namespace
      metadata:
        name: http-redirect
        labels:
          otherInfra: httpToHttps
      
      • 此命名空间设置了特定标签。
    4. 应用清单:

      kubectl apply -f redirect-namespace.yaml
      
    5. 如需限制 HTTP 监听器的使用,请使用以下清单创建网关。将清单保存为 external-gateway.yaml

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: external-http
        namespace: gateway-infra
      spec:
        gatewayClassName: gke-l7-global-external-managed
        listeners:
        - name: http
          protocol: HTTP
          port: 80
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: selector
              selector:
                matchLabels:
                  otherInfra: httpToHttps
        - name: https
          protocol: HTTPS
          port: 443
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: All
          tls:
            mode: Terminate
            options:
              networking.gke.io/pre-shared-certs: store-example-com
        ```
      
      • namespace 字段指定在 gateway-infra 命名空间中创建网关。

      • allowedRoutes 部分中的 namespaces 字段将 HTTP 监听器限制为与标签 otherInfra: httpToHttps 匹配的命名空间。

    6. 应用清单:

      kubectl apply -f external-gateway.yaml
      
    7. 如需强制进行 HTTPS 重定向,请使用以下清单创建默认 HTTPRoute。将清单保存为 http-redirect.yaml

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: redirect
        namespace: http-redirect
      spec:
        parentRefs:
        - namespace: gateway-infra
          name: external-http
          sectionName: http
        rules:
        - filters:
          - type: RequestRedirect
            requestRedirect:
              scheme: https
      
      • sectionName 字段指示网关仅在 HTTP 监听器上匹配。RequestRedirect 过滤条件会强制重定向到 HTTPS 监听器。
    8. 应用清单:

      kubectl apply -f http-redirect.yaml
      
    9. 使用以下清单为应用创建 Service。将清单保存为 service-deployment.yaml

      apiVersion: v1
      kind: Service
      metadata:
        name: store-v1
      spec:
        selector:
          app: store
          version: v1
        ports:
        - port: 8080
          targetPort: 8080
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: store-v1
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: store
            version: v1
        template:
          metadata:
            labels:
              app: store
              version: v1
          spec:
            containers:
            - name: whereami
              image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
              ports:
              - containerPort: 8080
              env:
              - name: METADATA
                value: "store-v1"
      
    10. 应用清单:

      kubectl apply -f service-deployment.yaml
      
    11. 使用以下清单为仅允许 HTTPS 的应用创建 HTTPRoute。将清单保存为 http-route.yaml

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1beta1
      metadata:
        name: store-external
        labels:
          gateway: external-http
      spec:
        parentRefs:
        - name: external-http
          namespace: gateway-infra
          sectionName: https
        hostnames:
        - "store.example.com"
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
      
    12. 应用清单:

      kubectl apply -f http-route.yaml
      

    配置路径重定向和网址重写

    路径重定向涉及将传入请求从一个网址路径重定向到另一个网址路径。借助路径重定向,您可以在需要处理过期或已弃用的网址时更改网址结构。

    网址重写有助于在服务器上处理传入网址之前修改该网址。它允许您更改网址的结构或格式,而无需实际更改底层内容或文件结构。网址重写对创建方便记忆且易于理解的人性化和搜索引擎优化 (SEO) 型网址非常有用。默认情况下,系统不会配置路径重定向和网址重写,您需要使用 HTTPRoute 中的过滤条件明确配置这些重定向或重写。

    GKE Gateway 支持路径重定向和网址重写。如需了解详情,请参阅 HTTP 路径重定向和重写

    配置路径重定向

    您可以将路径重定向配置为替换整个路径,也可以仅替换网址中的前缀。

    替换整个路径

    1. 如需替换整个路径,请在 HTTPRoute 中配置过滤条件,以将网址路径中包含前缀 /any-path 的任何网址替换为严格值 /new-path

    2. 如下所示创建 HTTPRoute 清单,并将其命名为 store.yaml

        apiVersion: gateway.networking.k8s.io/v1beta1
        kind: HTTPRoute
        metadata:
          name: store
        spec:
          parentRefs:
            - kind: Gateway
              name: external-http
          hostnames:
          - store.example.com
          rules:
          - matches:
            - path:
                type: PathPrefix
                value: /any-path
            filters:
            - type: RequestRedirect
              requestRedirect:
                path:
                  type: ReplaceFullPath
                  replaceFullPath: /new-path
                statusCode: 302
      

      例如,此清单为 HTTPRoute 设置路由规则,如下所示:到网址 https://store.example.com/any-path/... 的任意路由应重定向到新位置 https://store.example.com/new-path/(严格)。

    3. 应用清单:

      kubectl apply -f store.yaml
      

    此路由规则遵循严格的重定向规则,这意味着浏览器不会尝试缓存重定向,而是重定向到最新版本。

    仅替换前缀

    1. 如需仅替换前缀,请在 HTTPRoute 中配置过滤条件,以将网址路径中包含前缀 /any-prefix 的任何网址替换为严格值 /new-prefix

    2. 如下所示创建 HTTPRoute 清单,并将其命名为 store.yaml

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
        - matches:
            - path:
                type: PathPrefix
                value: /any-prefix
          filters:
          - type: RequestRedirect
            requestRedirect:
              path:
                type: ReplacePrefixMatch
                replacePrefixMatch: /new-prefix
              statusCode: 302
      

      例如,此清单为 HTTPRoute 设置路由规则,如下所示:到网址 https://store.example.com/any-path/v1/... 的任意路由应重定向到新位置 https://store.example.com/new-path/v1/...(仅替换前缀)。

    3. 应用清单:

        kubectl apply -f store.yaml
      

    此路由规则遵循唯一的重定向规则,可确保浏览器始终将您重定向到相同的预期页面。

    配置网址重写

    设置网址重写可更改网址对用户的显示方式。您可以使用网址重写功能,让网址更加方便用户使用,改进搜索引擎优化 (SEO),或将用户重定向到新网页。

    重写整个主机名

    要重写整个主机名,请执行以下操作:

    1. 在 HTTPRoute 中配置过滤条件,指示网关将请求标头中的 Host 信息从 www.example.com 替换为 store.example.com。,然后再将请求转发到后端服务。

    2. 如下所示创建 HTTPRoute 清单,并将其命名为 www.yaml

        apiVersion: gateway.networking.k8s.io/v1beta1
        kind: HTTPRoute
        metadata:
          name: www
        spec:
          parentRefs:
            - kind: Gateway
              name: external-http
          hostnames:
          - www.example.com
          rules:
          - filters:
            - type: URLRewrite
              urlRewrite:
                hostname: store.example.com
            backendRefs:
            - name: store-v1
              port: 8080
      

      例如,通过上述配置,任何对 https://www.example.com 的请求都将转发到带有 Host: store.example.com 标头(而不是 Host: www.example.com)的后端服务。

    3. 应用清单:

        kubectl apply -f www.yaml
      

    使用路径修饰符进行重写

    您可以将重写与路径修饰符结合使用,以在将请求中继到后端服务之前提供高级网址和路径修改。

    如需使用路径修饰符进行重写,请执行以下操作:

    1. 在 HTTPRoute 中配置过滤条件,指示网关将请求标头中的“主机”信息从 www.example.com 更改为 store.example.com,并将值 /store 替换为 /,然后再将请求转发到后端服务。

    2. 如下所示创建 HTTPRoute 清单,并将其命名为 www.yaml

        apiVersion: gateway.networking.k8s.io/v1beta1
        kind: HTTPRoute
        metadata:
          name: www
        spec:
          parentRefs:
            - kind: Gateway
              name: external-http
          hostnames:
          - www.example.com
          rules:
          - matches:
            - path:
                type: PathPrefix
                value: /store
            filters:
            - type: URLRewrite
              urlRewrite:
                hostname: store.example.com
                path:
                  type: ReplacePrefixMatch
                  replacePrefixMatch: /de
            backendRefs:
            - name: store-german
              port: 8080
      

      例如,通过上述配置,任何对 https://www.example.com/store/... 的请求都将转发到请求标头中带有 Host: store.example.com(而不是 Host: www.example.com)的后端服务,并且 /store 将被重写为 /de

    3. 应用清单:

      kubectl apply -f www.yaml
      

    验证配置

    如需在使用网址重写或路径重定向过滤条件创建 HTTPRoute 后验证过滤条件是否已应用,请执行以下操作:

    kubectl get httproute www -o yaml
    

    输出类似于以下内容:

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        annotations:
          kubectl.kubernetes.io/last-applied-configuration: |
            {"apiVersion":"gateway.networking.k8s.io/v1beta1","kind":"HTTPRoute","metadata":{"annotations":{},"name":"www","namespace":"default"},"spec":{"hostnames":["www.example.com"],"parentRefs":[{"kind":"Gateway","name":"external-http"}],"rules":[{"backendRefs":[{"name":"store-german","port":8080}],"filters":[{"type":"URLRewrite","urlRewrite":{"hostname":"store.example.com","path":{"replacePrefixMatch":"/de","type":"ReplacePrefixMatch"}}}],"matches":[{"path":{"type":"PathPrefix","value":"/store"}}]}]}}
        creationTimestamp: "2023-06-22T01:00:42Z"
        generation: 3
        name: www
        namespace: default
        resourceVersion: "51268631"
        uid: e516493e-806d-44d6-ae0d-1c9ff25682cf
      spec:
        hostnames:
        - www.example.com
        parentRefs:
        - group: gateway.networking.k8s.io
          kind: Gateway
          name: external-http
        rules:
        - backendRefs:
          - group: ""
            kind: Service
            name: store-german
            port: 8080
            weight: 1
          filters:
          - type: URLRewrite
            urlRewrite:
              hostname: store.example.com
              path:
                replacePrefixMatch: /de
                type: ReplacePrefixMatch
          matches:
          - path:
              type: PathPrefix
              value: /store
      status:
        parents:
        - conditions:
          - lastTransitionTime: "2023-06-22T01:11:26Z"
            message: ""
            observedGeneration: 2
            reason: Accepted
            status: "True"
            type: Accepted
          - lastTransitionTime: "2023-06-22T01:11:26Z"
            message: ""
            observedGeneration: 2
            reason: ReconciliationSucceeded
            status: "True"
            type: Reconciled
          controllerName: networking.gke.io/gateway
          parentRef:
            group: gateway.networking.k8s.io
            kind: Gateway
            name: external-http
    
    

    如需了解更多详情,请使用 describe 命令:

    kubectl describe httproute
    

    配置自定义请求和响应标头

    使用自定义请求和响应标头,您可以为 HTTP(S) 请求和响应指定其他标头。根据负载均衡器检测到的信息,这些标头可以包含以下信息:

    • 客户端的延迟时间
    • 客户端 IP 地址的地理位置
    • TLS 连接的参数

    默认情况下,向后端服务发送/从后端服务接收的请求不会添加自定义标头,您需要使用 HTTPRoute 中的过滤条件明确配置自定义标头。

    您可以通过在 HTTPRoute 的规则中添加过滤条件部分来配置自定义标头,如下所示:

    配置自定义请求标头

    使用 RequestHeaderModifier 过滤条件创建 HTTPRoute 清单,然后将其保存为 http-route-request.yaml:

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        <...>
        rules:
            filters:
              - type: RequestHeaderModifier
                requestHeaderModifier:
                  <...>
    

    应用清单:

      kubectl apply -f http-route-request.yaml
    

    配置自定义响应标头

    使用 ResponseHeaderModifier 过滤条件创建 HTTPRoute 清单,并将其保存为 http-route-response.yaml:

    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: HTTPRoute
    metadata:
      name: store
    spec:
      <...>
      rules:
          filters:
            - type: ResponseHeaderModifier
              responseHeaderModifier:
                <...>
    

    应用清单:

      kubectl apply -f http-route-response.yaml
    

    您可以按照 Gateway API 实现中的说明添加、设置和移除标头。您可以使用 Google Cloud 支持的变量通过自定义标头配置 HTTPRoute。

    示例 1

    如需配置在将客户端位置信息发送到后端服务之前将该信息添加到 HTTP 请求的 HTTPRoute,请创建 HTTPRoute 清单并将其命名为 external-http-request.yaml

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
          - matches:
            - path:
                type: PathPrefix
                value: /fr
            filters:
              - type: RequestHeaderModifier
                requestHeaderModifier:
                  add:
                    - name: X-Client-Geo-Location
                      value: "{client_region},{client_city}"
            backendRefs:
              - name: store-french
                port: 8080
    

    例如,对于位于法国特拉斯堡的客户端,网关会将标头添加为 X-Client-Geo-Location:FR,Strasbourg

    示例 2

    如需配置添加自定义响应标头以支持 HTTP 严格传输安全协议的 HTTPRoute,请创建 HTTPRoute 清单并将其命名为 external-http-response.yaml

      apiVersion: gateway.networking.k8s.io/v1beta1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
          - matches:
            - path:
                type: PathPrefix
                value: /de
            filters:
              - type: ResponseHeaderModifier
                responseHeaderModifier:
                  add:
                    - name: Strict-Transport-Security
                      value: max-age=63072000
            backendRefs:
              - name: store-german
                port: 8080
    

    验证配置

    1. 如需在配置自定义请求和响应标头后验证配置,请执行以下操作:

        kubectl get httproute
      

      输出类似于以下内容:

        NAME    HOSTNAMES               AGE
        store   ["store.example.com"]   4d23h
      
    2. 如需了解更多详情,请使用 describe 命令:

        kubectl describe httproute
      

      输出类似于以下内容:

        Name:         store
        Namespace:    default
        Labels:       <none>
        Annotations:  <none>
        API Version:  gateway.networking.k8s.io/v1beta1
        Kind:         HTTPRoute
        Metadata:
          Creation Timestamp:  2023-05-27T00:51:01Z
          Generation:          5
          Resource Version:    25418887
          UID:                 2e07a1b8-420b-41b4-acd1-cecbfcd39f42
        Spec:
          Hostnames:
            store.example.com
          Parent Refs:
            Group:  gateway.networking.k8s.io
            Kind:   Gateway
            Name:   external-http
          Rules:
            Backend Refs:
              Group:
              Kind:    Service
              Name:    store-v1
              Port:    8080
              Weight:  1
            Matches:
              Path:
                Type:   PathPrefix
                Value:  /
            Backend Refs:
              Group:
              Kind:    Service
              Name:    store-v2
              Port:    8080
              Weight:  1
            Matches:
              Headers:
                Name:   env
                Type:   Exact
                Value:  canary
              Path:
                Type:   PathPrefix
                Value:  /
            Backend Refs:
              Group:
              Kind:    Service
              Name:    store-german
              Port:    8080
              Weight:  1
            Filters:
              Request Header Modifier:
                Add:
                  Name:   X-Client-Geo-Location
                  Value:  {client_region},{client_city}
              Type:       RequestHeaderModifier
            Matches:
              Path:
                Type:   PathPrefix
                Value:  /de
        Status:
          <...>
      

    路由状态

    HTTPRoute 资源会发出条件和事件,以帮助用户了解 HTTPRoute 是否已成功与一个或多个 Gateway 绑定,或者 HTTPRoute 是否被拒绝。

    HTTPRoute 条件

    HTTPRoute 条件指示 Route 的状态及其绑定到的 Gateway。由于一个 Route 可以绑定到多个 Gateway,因此这是一个 Gateway 以及 Route 与每个 Gateway 之间的各个条件的列表。

    • Accepted=True 表示 HTTPRoute 已成功绑定到 Gateway。
    • Accepted=False 表示 HTTPRoute 已被拒绝与此 Gateway 绑定。

    如果 Gateway bindings 标题下未列出任何 Gateway,则 HTTPRoute 标签和 Gateway 标签选择器可能不匹配。如果 Route 未被任何 Gateway 选择,则可能会发生这种情况。

    HTTPRoute 事件

    HTTPRoute 事件提供有关 HTTPRoute 状态的详细信息。事件分组的原因如下:

    • ADD 事件由添加的资源触发。
    • UPDATE 事件由更新的资源触发。
    • SYNC 事件由定期协调触发。

    路由合并、优先权和验证

    路由优先权

    Gateway API 针对具有重叠路由规则的 Route 如何匹配流量定义了严格的优先权规则。两个重叠 HTTPRoute 之间的优先权如下所示:

    1. 主机名合并:最长/最具体的主机名匹配。
    2. 路径合并:最长/最具体的路径匹配。
    3. 标头合并:匹配的 HTTP 标头的最大数。
    4. 冲突:如果前三个规则未确立优先权,则优先权转给时间戳最早的 HTTPRoute 资源。

    路由合并

    对于 gke-l7 GatewayClass,给定网关的所有 HTTPRoutes 都会合并到同一个网址映射资源中。HTTPRoute 的合并在一起的方式取决于 HTTPRoute 之间的重叠类型。来自前面的示例的 HTTPRoute 可以拆分为三个单独的 HTTPRoute,用于说明路由合并和优先权:

    1. 路由合并:所有三个 HTTPRoute 都与同一 internal-http 网关连接,因此它们会合并在一起。
    2. 主机名合并:对于 store.example.com,所有三个路由都匹配,因此它们的主机名规则会合并。
    3. 路径合并:store-german-route 具有更具体的路径 /de,因此不会进一步合并。store-v1-route 和 store-v2-route 同样与同一 /* 路径匹配,因此它们会在该路径上合并。
    4. 标头合并:store-v2-route 具有一组比 store-v1-route 更具体的 HTTP 标头匹配项,因此不会进一步合并。
    5. 冲突:由于路由可以按主机名、路径和标头进行合并,因此不会发生冲突,并且所有路由规则都应用于流量。

    前面的示例中使用的单个 HTTPRoute 相当于这三个单独的路由:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-v1-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - kind: Service
          name: store-v1
          port: 8080
    ---
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-v2-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - headers:
          - type: Exact
            name: env
            value: canary
        backendRefs:
        - kind: Service
          name: store-v2
          port: 8080
    ---
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: store-german-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /de
        backendRefs:
        - kind: Service
          name: store-german
          port: 8080
    

    Kubernetes 网关和 Istio 网关

    请注意,Kubernetes Gateway API 和 Istio API 都有一个名为 Gateway 的资源。虽然它们执行类似的功能,但并不是相同的资源。如果您在同一 Kubernetes 集群中同时使用 Istio 和 Gateway API,则当您在命令行中使用 kubectl 时,这些名称将重叠。kubectl get gateway 可能会返回 Kubernetes 网关资源,但不会返回 Istio 网关资源,反之亦然。

    $ kubectl api-resources
    NAME       SHORTNAMES   APIGROUP                       NAMESPACED   KIND
    gateways   gw           networking.istio.io/v1beta1    true         Gateway
    gateways   gtw          networking.k8s.io/v1beta1      true         Gateway
    

    如果您使用的是 Istio 并升级到 GKE 1.20 及更高版本,则建议开始使用网关资源简称或指定 API 组。Kubernetes 网关的简称为 gtw,Istio 网关的简称为 gw。以下命令会分别返回 Kubernetes 网关资源和 Istio 网关资源。

    # Kubernetes Gateway
    $ kubectl get gtw
    NAME                        CLASS
    multi-cluster-gateway       gke-l7-global-external-managed-mc
    
    $ kubectl get gateway.networking.x-k8s.io
    NAME                        CLASS
    multi-cluster-gateway       gke-l7-global-external-managed-mc
    
    # Istio Gateway
    $ kubectl get gw
    NAME               AGE
    bookinfo-gateway   64m
    
    $ kubectl get gateway.networking.istio.io
    NAME               AGE
    bookinfo-gateway   64m
    

    问题排查

    区域中缺少代理专用子网

    具体情况:

    创建区域级 Gateway(内部或外部)时,可能会出现以下问题:

    generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/[REGION_NAME]/targetHttpProxies/gkegw-x5vt-default-internal-http-[ID]'. A reserved managed proxy subnetwork with purpose REGIONAL_MANAGED_PROXY is required.
    

    原因:

    此错误消息表示 Gateway 的区域中不存在代理专用子网。

    临时解决方法:

    如需解决此问题,请配置代理专用子网

    区域中已存在用途错误的代理专用子网

    具体情况:

    为区域级 Gateway(内部或外部)创建代理专用子网时,可能会出现以下问题:

    ERROR: (gcloud.compute.networks.subnets.create) Could not fetch resource:
     - The resource 'projects/[PROJECT_NAME]/regions/[REGION_NAME]/subnetworks/[PROXY_ONLY_SUBNET_NAME]' already exists
    

    原因:

    此错误消息表示您尝试在已具有代理专用子网的区域中创建区域级代理专用子网。

    临时解决方法:

    如需解决此问题,请按照以下步骤操作:

    1. 检查该区域中是否已存在代理专用子网,并验证其用途是否正确:

      1. 列出您的子网,以确定哪个是该区域中的代理专用子网:

        gcloud compute networks subnets list --regions=COMPUTE_REGION
        

        COMPUTE_REGION 替换为您要在其中创建区域级 Gateway 的 Compute Engine 区域。

      2. 描述该区域中的代理专用子网,以确定其用途:

        gcloud compute networks subnets describe PROXY_ONLY_SUBNET \
            --region COMPUTE_REGION | grep -E 'name|purpose'
        

        PROXY_ONLY_SUBNET 替换为代理专用子网。

      GKE Gateway 仅支持区域级 Gateway(内部或区域级)的 REGIONAL_MANAGED_PROXY 代理专用子网。

    2. 如果该区域中的现有代理专用子网是使用 INTERNAL_HTTPS_LOAD_BALANCER 用途创建的,请将其用途迁移到 REGIONAL_MANAGED_PROXY

    后续步骤