部署网关

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

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

如需了解更具体的网关配置(例如跨命名空间路由和 HTTP 流量分配),请参阅 Gateway API 用户指南

准备工作

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

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

GKE Gateway Controller 要求

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

限制和局限

使用 GKE 网关时,请了解以下局限性和限制:

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

    最佳实践

    为获得最佳性能,请将网关数量限制为最多 100 个。超出此限制可能会影响性能或导致延迟时间增加。

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

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

  • 您无法直接在主机名中指定端口号(例如 web.example.com:80)以进行流量路由。

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

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

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

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

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

  • 在配置 HTTPRoute 自定义请求和响应标头时,不支持以下 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 网关不支持引用同时被 GKE Ingress 引用的 Service。

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

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

  • 如果您将 GKE 网关与 external-dns 搭配使用,并且网关的健康状况不佳,则默认情况下,与网关关联的所有 DNS 记录都会从您的 DNS 区域中删除。

    最佳实践

    运行 external-dns 时,设置 policy=upsert-only 标志。 此配置有助于防止删除现有 DNS 记录。

  • 如果从 GKE 网关通过路由(Service 上的独立 NEG 注解)引用的 Service 中移除端口,您还必须更新该 Service 上的独立 NEG 控制器才能移除该端口。否则,NEG 控制器最终会停止同步此 Service 的 Pod 端点。如需了解详情,请参阅从 Service 中移除端口后,NEG 控制器停止管理端点

  • 使用可用区级集群的多集群网关 (MCG) 部署在集群升级期间容易发生服务中断故障。 出现此问题的原因是,当可用区级集群的控制平面暂时不可用时,旧版网络端点组 (NEG) 发现机制可能会错误地报告零个后端。我们正在努力解决此问题,以便从长远来看,此问题不会再出现。为避免出现这种单点故障,请使用具有 MCG 的 区域级 GKE 集群。

在集群中启用 Gateway API

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

在更新现有 GKE 集群以启用 Gateway API 之前,请先确保满足所需的最低要求,然后再继续更新。

如需在现有 GKE 集群(Autopilot 或 Standard)上启用 Gateway API,请使用以下命令。集群最多可能需要 45 分钟来协调和安装 CRD。

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 功能

系统只会自动安装单集群 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 网络的名称。确保这是与您的 GKE 集群所在的 VPC 网络和您部署网关的 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/v1 metadata:    name: internal-http spec:   # Specify an existing GatewayClass.   gatewayClassName: gke-l7-rilb   listeners:   # Listen for HTTP traffic on port 80.   - name: http     protocol: HTTP     port: 80 

    此清单包含以下字段:

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

    此网关配置为仅处理端口 80 上的 HTTP 流量。默认情况下,不支持 HTTPS(端口 443),如果您尝试通过 HTTPS 进行连接,请求可能会失败。

  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:  2025-03-19T19:53:46Z      Message:               The OSS Gateway API has deprecated this condition, do not depend on it.      Observed Generation:   1      Reason:                Scheduled      Status:                True      Type:                  Scheduled      Last Transition Time:  2025-03-19T19:53:46Z      Message:      Observed Generation:   1      Reason:                Accepted      Status:                True      Type:                  Accepted      Last Transition Time:  2025-03-19T19:53:46Z      Message:      Observed Generation:   1      Reason:                Programmed      Status:                True # Indicates that the Gateway is ready.      Type:                  Programmed      Last Transition Time:  2025-03-19T19:53:46Z      Message:               The OSS Gateway API has altered the "Ready" condition semantics and reserved it for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.      Observed Generation:   1      Reason:                Ready      Status:                True      Type:                  Ready      Last Transition Time:  2025-03-19T19:53:46Z      Message:      Observed Generation:   1      Reason:                Healthy      Status:                True      Type:                  networking.gke.io/GatewayHealthy 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 

    在此输出中,Programmed 条件的 True 状态表示网关已准备就绪。

    此时,您的集群中部署了一个网关,该网关已预配负载均衡器和 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/v1 metadata:   name: store spec:   # Attach the HTTPRoute to a Gateway.   parentRefs:   - kind: Gateway     name: internal-http   # Route requests that have `store.example.com` in the Host header.   hostnames:   - "store.example.com"   rules:   # Send requests with the `env: canary` header to the `store-v2` Service.   - matches:     - headers:       - name: env         value: canary     backendRefs:     - name: store-v2       port: 8080   # Send requests with `/de` in the path to the `store-german` Service.   - matches:     - path:         value: /de     backendRefs:     - name: store-german       port: 8080   # Send unmatched requests to the store-v1 Service.   - backendRefs:     - name: store-v1       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/v1 Kind:         HTTPRoute # Multiple lines are omitted here. 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",   # Multiple lines are omitted here. 
  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       <...> 

将流量发送到应用

现在,网关、路由和应用已在集群中部署,您可以将流量传递到您的应用。 网关配置为仅在端口 80 上传送 HTTP 流量。除非已单独配置 TLS,否则通过 HTTPS 发出的请求可能会失败。

  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 集群位于同一区域。

    向 store.example.com 发出请求:

    curl http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -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-10-25T13:31:17",   "zone": "ZONE_NAME" } 
  3. 转到 store.example.com/de 中的德语版商店服务,测试路径匹配:

    curl http://store.example.com/de --resolve store.example.com:80:GATEWAY_IP_ADDRESS -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-10-25T13:35:37",   "zone": "ZONE_NAME" } 
  4. 最后,使用 env: canary HTTP 标头将流量发送到 Canary 版商店服务:

    curl -H "env: canary" http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -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-10-25T13:38:26",   "zone": "ZONE_NAME" } 

部署外部网关

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

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

  • 全球外部网关:此网关使用全球 IP 地址(或任播 IP 地址)作为网关的前端。此 IP 地址在所有 Google Cloud 计算区域中都会进行通告。将流量发送到此任播 IP 地址的客户端会路由到通告该 IP 地址的最近 Google 位置。全球外部网关仅在高级网络服务层级提供。
  • 区域级外部网关:此网关使用区域级 IP 地址作为网关的前端。此网关的行为取决于您选择的网络服务层级:
    • 如果您选择标准网络服务层级(默认),则区域级 IP 地址仅在部署区域级外部网关的本地 Google Cloud 计算区域中通告。将流量发送到此 IP 地址的客户端会由其本地 ISP 和公共互联网进行路由,然后再到达通告该 IP 地址的 Google 区域。
    • 如果您选择高级网络服务层级,系统会在 Google 的全球网络中通告区域级 IP 地址。这意味着,即使目的地是区域 IP 地址,客户端流量也会在离客户端最近的 Google 边缘对接点进入 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/v1 metadata:   name: external-http   annotations:     networking.gke.io/certmap: store-example-com-map spec:   # This GatewayClass uses a global external Application Load Balancer.   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/v1 metadata:   name: store-external spec:   parentRefs:   # Bind the route to the 'external-http' Gateway.   - kind: Gateway     name: external-http   hostnames:   - "store.example.com"   rules:   # Default rule for store.example.com that sends traffic to the store-v1 service.   - backendRefs:     - name: store-v1       port: 8080   # Match requests with the "env: canary" header and send them to the store-v2 service.   - matches:     - headers:       - name: env         value: canary     backendRefs:     - name: store-v2       port: 8080   # Match requests with the path "/de" and sends them to the store-german service.   - 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/v1 Kind:         HTTPRoute # Multiple lines are omitted here. 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:     # This section shows the status of this route in relation to each Gateway attached.     Conditions:       Last Transition Time:  2022-11-01T05:42:31Z       Message:       Reason:                Accepted       Status:                True # Means that the Gateway has validated and accepted this route's configuration.       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> # Multiple lines are omitted here. 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       # Multiple lines are omitted here. 

将流量发送到应用

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

  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 https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v 

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

    cacert.pem:您生成的证书文件。您必须将此文件保存在用于连接到网关的机器上。

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

    {   "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 https://store.example.com/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 "env: canary" https://store.example.com --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 中

如需保护客户端与区域网关之间的流量,您可以使用以下方法:

  • Google 管理的或自行管理的 Certificate Manager 证书
  • 自行管理的区域性 SSL 证书
  • Kubernetes Secret

CertificateMap 或 Google 管理的 SSL 证书。

如需了解详情,请参阅证书和 Google Cloud 负载均衡器

创建区域级外部 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/v1   metadata:     name: external-regional-http   spec:     # Name of an existing GatewayClass.     gatewayClassName: gke-l7-regional-external-managed     # Listen for HTTPS traffic on port 443     listeners:     - name: https       protocol: HTTPS       port: 443       tls:         # Terminate the TLS session with the client at the Gateway.         mode: Terminate         # Certificates for the Gateway to use to create a new TLS session.         certificateRefs:         - name: store-example-com     # The name of the static IP address of the external load balancer.     # You can also use the `IPAddress` type to specify the actual IP address.     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/v1 metadata:   name: site-internal spec:   # Attach the HTTPRoute to the `internal-http` Gateway.   parentRefs:   - kind: Gateway     name: internal-http   # Route requests that have `site.example.com` in the Host header.   hostnames:   - "site.example.com"   # Send all requests to the `site-v1` Service.   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 替换为内部网关的 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" } 

    此输出表明,带有 site.example.com Host 标头的请求会到达 site-v1 服务,而带有 store.example.com Host 标头的请求会到达 store-v1 服务。

配置网络层级

您可以使用网关定义中 addresses[] 数组内的 type 字段,为区域级外部应用负载均衡器的监听器地址指定网络层级。如果您未指定网络层级,网关将默认使用标准层级的临时 IP 地址。

请将以下值用于 type 字段:

  • networking.gke.io/premium-ephemeral-ipv4-address:分配高级层级 IP 地址。
  • networking.gke.io/standard-ephemeral-ipv4-address:分配标准层级 IP 地址。

如需分配来自这两个网络层级的 IP 地址,请在 addresses 字段中指定这两种类型。

以下示例展示了如何 Google Cloud 为网关分配高级层级 IP 地址。如需预配标准层级 IP 地址,请使用 networking.gke.io/standard-ephemeral-ipv4-address

  1. 将以下示例清单保存为 external-regional-http.yaml

    kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata:   name: external-regional-http spec:   # Name of an existing GatewayClass.   gatewayClassName: gke-l7-regional-external-managed   # Listen for HTTPS traffic on port 443.   listeners:   - name: https     protocol: HTTPS     port: 443     tls:       # Terminate the TLS session with the client at the Gateway.       mode: Terminate       # Certificates for the Gateway to use to create a new TLS session.       certificateRefs:       - name: store-example-com     addresses:     # Request a Premium Tier ephemeral IPv4 address for the Gateway.     - type: networking.gke.io/premium-ephemeral-ipv4-address 
  2. 应用示例清单:

    kubectl apply -f external-regional-http.yaml 

配置 Gateway 默认后端

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

即使没有明确的后端定义,网关也会配置为处理 404(未找到)和 500(服务器错误)等错误代码。默认行为可能因网关实现而异。如需更好地控制错误处理,请考虑配置自定义后端。

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

kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata:   name: custom-default-backend spec:   parentRefs:   - kind: Gateway     name: my-internal-gateway   # Omit the `hostnames` field to route all unmatched traffic from the   # attached Gateway.   rules:   - backendRefs:     - name: my-custom-default-backend-service       port: 8080 

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

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

为 Gateway 配置静态 IP 地址

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

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

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

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

GatewayClasses 默认 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 来配置 IPv4 或 IPv6 地址。您必须先预配静态 IP 地址,然后才能创建网关。

    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 区域。对于全球级外部网关,不需要此标志。
      • SUBNET:IP 地址的子网。对于全球级外部网关,不需要此标志。
      • PROJECT_ID:GKE 集群在其中运行的项目。
    2. 将以下清单保存到名为 named-ip-gateway.yaml 的文件中:

      kind: Gateway apiVersion: gateway.networking.k8s.io/v1 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 应用的流量始终重定向到安全页面。

    gke-l7-gxlbgke-l7-gxlb-mc GatewayClass 不支持从 HTTP 到 HTTPS 的重定向。如需详细了解每个 GatewayClass 支持的不同功能,请参阅 GatewayClass 功能

    请注意,HTTPRoute 中的 hostnames 部分是可选的。您可以省略 hostnames 部分,为特定 HTTP 端口上的所有主机名创建全方位重定向。此外,您还可以使用通配符重定向,例如:

    ... hostnames: - "*.example.com" # Matches all subdomains of example.com ... 

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

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

    以下示例进一步限制了 HTTP 监听器的使用,以防止应用团队意外使用非安全协议。此示例将网关配置为仅当路由位于具有 otherInfra: httpToHttps 标签的命名空间中时才允许 HTTPRoute 使用 HTTP 监听器。不过,网关允许任何命名空间中的 HTTPRoute 使用 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 

      http-redirect 命名空间具有 otherInfra: httpToHttps 标签。

    4. 应用清单:

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

      kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata:   name: external-http   namespace: gateway-infra spec:   # Name of an existing GatewayClass.   gatewayClassName: gke-l7-global-external-managed   listeners:   - name: http     protocol: HTTP     port: 80     #  Allow only HTTPRoutes from namespaces that have the     # `otherInfra: httpToHttps` label to use this listener.     allowedRoutes:       kinds:       - kind: HTTPRoute       namespaces:         from: Selector         selector:           matchLabels:             otherInfra: httpToHttps   - name: https     protocol: HTTPS     port: 443     # Allow HTTPRoutes from any namespace to use this listener.     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/v1 metadata:   name: redirect   # Create the HTTPRoute in the `http-redirect` namespace.   namespace: http-redirect spec:   # Attach the HTTPRoute to the `http` listener in the `external-http`   # Gateway.   parentRefs:   - namespace: gateway-infra     name: external-http     sectionName: http   rules:   # Respond to the request with an HTTPS redirection.   - 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         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/v1 metadata:   name: store-external   labels:     gateway: external-http spec:   # Attach the HTTPRoute to the HTTPS listener in the `external-http`   # Gateway.   parentRefs:   - name: external-http     namespace: gateway-infra     sectionName: https   # Match requests that have the `store.example.com` Host header.   hostnames:   - "store.example.com"   # Route requests to the `store-v1` Service.   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/v1   kind: HTTPRoute   metadata:     name: store   spec:     parentRefs:     - kind: Gateway       name: external-http     hostnames:     - store.example.com     rules:     - matches:       - path:           # Match requests by a prefix, like `/any-path` and `/any-path/home`.           type: PathPrefix           value: /any-path       filters:       - type: RequestRedirect         requestRedirect:           path:             # Replace the full path with `/new-path`. For example, both             # `/any-path/home` and `/any-path` become `/new-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/v1 kind: HTTPRoute metadata:   name: store spec:   parentRefs:     - kind: Gateway       name: external-http   hostnames:   - store.example.com   rules:   - matches:       - path:           # Match requests by prefix, like `/any-prefix` and           # `/any-prefix/home`.           type: PathPrefix           value: /any-prefix     filters:     - type: RequestRedirect       requestRedirect:         path:           # Replace the matched prefix with `/new-prefix`. For example,           # `/any-prefix` becomes `/new-prefix` and `/any-prefix/home`           # becomes `/new-prefix/home`.           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/v1   kind: HTTPRoute   metadata:     name: www   spec:     parentRefs:       - kind: Gateway         name: external-http     hostnames:     - www.example.com     rules:     - filters:       - type: URLRewrite         # Replace the hostname in the URL with `store.example.com`.         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 替换为 to store.example.com,并将 /store 值替换为 /,然后再将请求转发到后端服务。

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

        apiVersion: gateway.networking.k8s.io/v1   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         # For URLs that have `/store` in the path, replace the hostname with         # store.example.com and replace the `/store` prefix with `/de`.         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/v1   kind: HTTPRoute   metadata:     annotations:       kubectl.kubernetes.io/last-applied-configuration: |         {"apiVersion":"gateway.networking.k8s.io/v1","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/v1   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/v1 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/v1   kind: HTTPRoute   metadata:     name: store   spec:     parentRefs:       - kind: Gateway         name: external-http     hostnames:     - store.example.com     rules:       - matches:         - path:             type: PathPrefix             value: /fr         filters:           # Add custom headers to requests that have `/fr` in the path.           - 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/v1   kind: HTTPRoute   metadata:     name: store   spec:     parentRefs:       - kind: Gateway         name: external-http     hostnames:     - store.example.com     rules:       - matches:         - path:             type: PathPrefix             value: /de         filters:           # Add custom headers to responses to requests that have `/de` in the           # path.           - 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/v1   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 针对具有重叠路由规则的路由应如何匹配流量定义了严格的优先权规则。两个重叠 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/v1 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/v1 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/v1 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(内部或外部)创建代理专用子网时,可能会出现以下问题:

    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 仅支持区域级网关(内部或区域级)的 REGIONAL_MANAGED_PROXY 代理专用子网。

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

    没有健康的上行

    具体情况:

    创建网关但无法访问后端服务(503 响应代码)时,可能会出现以下问题:

    no healthy upstream 

    原因:

    此错误消息表示健康检查探测器找不到健康状况良好的后端服务。您的后端服务可能处于健康状况良好状态,但您可能需要自定义健康检查。

    临时解决方法:

    如需解决此问题,请使用 HealthCheckPolicy 根据应用的要求自定义监控状况检查(例如 /health)。

    后续步骤