Kubernetes Gateway API 是一个由 SIG-Network 孵化和维护的 开放、标准、可扩展的 API,旨在为 Kubernetes 集群内部和外部的统一流量管理提供更强大、更灵活、更具表现力的方式。

它被视为 Ingress API 的继任者和演进,解决了 Ingress 在灵活性、可扩展性、角色分离和 L4-L7 支持方面的诸多局限性。Gateway API 不仅仅关注 HTTP 流量,还支持 TCP、UDP 以及 TLS 路由,覆盖了更广泛的网络场景。

为什么需要 Gateway API#

在 Gateway API 出现之前,Kubernetes 主要使用 Ingress 来管理集群的 L7 HTTP/HTTPS 流量。然而,Ingress 存在一些固有的局限性,促使了 Gateway API 的诞生:

  1. 功能有限: Ingress 本身功能非常基础,只支持主机和路径路由。任何高级功能(如流量拆分、重写、限速、认证等)都必须通过特定于 Ingress 控制器(如 NGINX Ingress, Traefik, AWS ALB Ingress 等)的 注解(Annotations) 来实现。
  2. 可移植性差: 注解是特定于实现的,这意味着用 NGINX Ingress 注解编写的规则无法直接移植到 Traefik 或其他 Ingress 控制器上,造成供应商锁定。
  3. 缺乏角色分离: Ingress 资源将网络基础设施的配置(例如暴露的端口、TLS 证书)与应用程序的路由规则混在一起,这使得集群管理员和应用开发者之间的职责难以清晰划分。
  4. L4 流量支持不足: Ingress 仅专注于 HTTP/HTTPS (L7) 流量。对于 TCP、UDP 或 TLS 直通(Passthrough)等 L4 流量,通常需要使用 LoadBalancer 类型的 Service 或其他的解决方案。
  5. 表达能力有限: 难以表达复杂的路由策略,如基于请求头、查询参数的匹配,细粒度的流量权重分配等。

Gateway API 旨在解决这些问题,提供一个更加健壮和通用的流量管理框架。

核心概念和资源抽象#

b7bc67456d46c298701f7df89586462f_MD5

Gateway API 定义了一组分层且互操作的资源对象,用于构建从网络入口到后端服务的完整流量路径。主要的关键资源包括:

  1. GatewayClass
    • 目的: 定义了具体的网关实现类型(例如:NGINX, Istio, GKE, AWS ALB, Contour, Envoy 等)。
    • 谁创建: 通常由基础设施提供商(如云服务商)或平台管理员创建,以注册他们的网关控制器。
    • 作用: 类似于 IngressClass,通过 controllerName 指明由哪个控制器来处理此类的 Gateway 资源。
    • 作用域: Cluster scope
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: example-nginx # GatewayClass 的名称,被 Gateway 引用
spec:
  controllerName: k8s.io/gateway-nginx # 声明 Nginx Gateway 控制器会管理这类 Gateway
  description: "GatewayClass for Nginx based HTTP/HTTPS traffic management."
  # parametersRef: # 可选,指向一个自定义资源,用于控制器特定的全局配置
  #   group: gateway.nginx.org
  #   kind: NginxGatewayParameters
  #   name: nginx-global-config
  1. Gateway
    • 目的: 代表在集群中运行的网络监听器,例如一个真实的负载均衡器、代理服务器或边缘路由器。
    • 谁创建: 通常由集群操作员平台管理员创建。
    • 作用: 定义了监听的协议 (HTTP, HTTPS, TLS, TCP, UDP)、端口,负责对外暴露集群的 IP 地址或 Hostname,以及绑定 TLS 证书。一个 Gateway 可以关联一个 GatewayClass
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
  namespace: gateway-system # Gateway 通常部署在专用命名空间
spec:
  gatewayClassName: example-nginx # 引用一个 GatewayClass
  listeners:
    - name: http
      port: 80
      protocol: HTTP
      hostname: "www.example.com" # 监听此主机名
      allowedRoutes: # 允许哪些路由绑定
        namespaces:
          from: Same # 仅允许 Gateway 所在命名空间的路由绑定
        # from: All # 允许所有命名空间的路由绑定 (需要 ReferenceGrant)
        kinds:
          - group: gateway.networking.k8s.io
            kind: HTTPRoute
    - name: https
      port: 443
      protocol: HTTPS
      hostname: "*.example.com" # 监听所有子域名
      tls:
        mode: Terminate
        certificateRefs: # 引用 TLS 证书 Secret
          - group: ""
            kind: Secret
            name: example-com-tls # Secret 必须在 Gateway 同一命名空间
            # 可以是其他命名空间的 Secret,但需要 ReferenceGrant 授权
      allowedRoutes:
        namespaces:
          from: All # 此 HTTPS 监听器允许所有命名空间的路由绑定
        kinds:
          - group: gateway.networking.k8s.io
            kind: HTTPRoute
  # addresses: # 也可以在这里请求特定的 IP,但控制器可能不接受
  #   - type: IPAddress
  #     value: "192.0.2.1"
  1. Route

    • 目的: 定义了从 Gateway 到后端服务的具体路由规则。这是 Gateway API 最具扩展性的部分,它根据不同的协议提供了多种路由类型:
      • HTTPRoute 最常使用,用于 HTTP/HTTPS 流量。支持主机名、路径、HTTP 方法、请求头、查询参数等多种匹配规则,以及流量权重、重写、重定向等高级功能。
      • GRPCRoute
    • 谁创建: 通常由应用程序开发者服务所有者创建。
    • 作用: 将流量从 Gateway 路由到一个或多个 Kubernetes Service 或其他后端端点。
  2. ReferenceGrant (引用授权)

    • 目的: 提供了一个安全机制,允许跨命名空间引用资源(例如,一个 HTTPRoute 在 app-ns 命名空间中引用 Gateway 命名空间中的 Secret 来获取 TLS 证书,或者引用 backend-ns 命名空间中的 Service)。
    • 谁创建: 通常由拥有被引用资源的命名空间管理员创建。
    • 作用: 增强了安全性,避免了恶意用户在其他命名空间中创建的路由来劫持流量或访问敏感信息。

HTTPRoute#

关键字段#

parentRefs #
  • 目的: 将 HTTPRoute 绑定到一个或多个 Gateway 资源上。这是路由生效的前提。
  • 字段:
    • group: (可选) 默认为 gateway.networking.k8s.io
    • kind: (可选) 默认为 Gateway
    • name必须,指定 Gateway 的名称。
    • namespace: (可选) 如果 Gateway 在不同命名空间,必须指定。注意: 跨命名空间引用 Gateway 需要 ReferenceGrant 授权。
    • sectionName: (可选) 如果 Gateway 具有多个监听器 (Listener),可以使用此字段指定要绑定到哪个特定的 Listener。如果未指定,通常会绑定到第一个兼容的 Listener,或者控制器会根据 HTTPRoute 的 hostnames 字段尝试匹配 Listener。
parentRefs:
  - name: my-gateway # 引用名为 my-gateway 的 Gateway
    namespace: gateway-ns # 如果 gateway 在 gateway-ns 命名空间
    sectionName: https-listener # 绑定到 Gateway 中名为 https-listener 的监听器
hostnames#
  • 目的: 定义 HTTPRoute 匹配的域名或主机名。
  • 字段: hostnames 是一个字符串数组。
  • 匹配规则:
    • 精确匹配: 例如 example.com
    • 通配符匹配: 例如 *.example.com (匹配 www.example.comapp.example.com 等,但不会匹配 example.com 本身)。
  • 优先级: 精确匹配的 hostnames 优先级高于通配符匹配。如果一个请求同时匹配多个 HTTPRoute 的 hostnames,控制器将选择最精确的那个。
hostnames:
  - "www.example.com"
  - "*.dev.example.com"
rules#

这是 HTTPRoute 最核心的部分,它定义了一组匹配条件、可选的流量修改和最终的后端转发。一个 HTTPRoute 可以包含多个 rules,它们按顺序评估,直到找到第一个匹配的规则。

每个 rule 包含以下子字段:

matches #
  • 目的: 定义哪些 HTTP 请求属性必须满足,此规则才会被应用。所有 matches 字段都是可选的,如果未指定,则默认匹配所有请求。
  • 字段: matches 是一个数组,每个元素可以包含:
    • path:
      • type: (可选) 匹配类型。
        • PathPrefix (默认): 路径前缀匹配,例如 /foo 会匹配 /foo/foo/bar
        • Exact: 精确匹配,例如 /foo 只匹配 /foo
        • RegularExpression: 正则表达式匹配,例如 ^/api/v1/.*
      • value: 要匹配的路径字符串。
    • headers:
      • type: (可选) 匹配类型。
        • Exact (默认): 精确匹配头部值。
        • RegularExpression: 正则表达式匹配头部值。
        • Present: 只要头部存在即可,不需要匹配值。
      • name: HTTP 头部的名称 (不区分大小写)。
      • value: 要匹配的头部值 (如果 type 是 Exact 或 RegularExpression)。
    • queryParams:
      • type: 同 headers
      • name: 查询参数的名称。
      • value: 要匹配的查询参数值。
    • method:
      • type: 匹配类型 (Exact 是唯一选项)。
      • value: 要匹配的 HTTP 方法 (GET, POST, PUT, DELETE, etc.)。
matches:
  - path:
      type: PathPrefix
      value: "/api/v1/users" # 匹配 /api/v1/users 或 /api/v1/users/123
    headers:
      - name: X-Version
        value: "v2" # 匹配头部 X-Version: v2
    method:
      value: "GET" # 匹配 GET 请求
filters #
  • 目的: 在请求被转发到后端服务之前,对请求或响应进行操作。
  • 字段: filters 是一个数组,每个元素可以包含多种过滤器类型:
    • RequestHeaderModifier: 修改请求头。
      • set: 设置或替换请求头值。
      • add: 添加请求头值(如果已存在,则追加)。
      • remove: 移除指定的请求头。
    • ResponseHeaderModifier: (部分实现支持) 修改响应头。同 RequestHeaderModifier
    • RequestRedirect: 将请求重定向到另一个 URL。
      • scheme: 协议 (http, https)。
      • hostname: 新主机名。
      • port: 新端口。
      • path: 路径重定向规则。
        • typeReplaceFullPathReplacePrefixMatch (替换匹配到的部分), RewriteSubset (重写部分路径)。
        • value: 新路径或前缀。
      • statusCode: HTTP 状态码 (301, 302, etc.)。
    • URLRewrite: 重写请求的 URL,但不会发送重定向。
      • hostname: 重写请求的主机名。
      • path: 路径重写规则。
        • typeReplaceFullPathReplacePrefixMatchRewriteSubsetExact.
        • value: 新路径或前缀。
    • RequestMirror: (部分实现支持) 将请求镜像到另一个后端,通常用于测试或影子发布。镜像流量不会影响客户端响应。
      • backendRef: 镜像到的后端服务引用。
    • ExtensionRef: 允许通过扩展机制添加自定义过滤器。
filters:
  - type: RequestHeaderModifier
    requestHeaderModifier:
      add:
        - name: X-Internal-Request
          value: "true" # 为请求添加一个内部头部
  - type: URLRewrite
    urlRewrite:
      path:
        type: ReplacePrefixMatch
        value: "/v2" # 如果匹配到 /api/v1/users(定义在 PathPrefix 中),重写为 /v2
backendRefs #
  • 目的: 定义匹配到的请求应该转发到哪些后端服务。
  • 字段: backendRefs 是一个数组,每个元素可以包含:
    • group: (可选) 默认为 "" (核心 API 组,用于 Service)。
    • kind: (可选) 默认为 Service
    • name必须,后端服务的名称。
    • namespace: (可选) 如果 Service 在不同命名空间,必须指定。注意: 跨命名空间引用 Service 需要 ReferenceGrant 授权。
    • port必须,后端服务监听的端口。
    • weight: (可选) 0 到 10000 之间的整数。如果指定了多个 backendRefs,可以设置权重进行流量百分比分配(A/B 测试、金丝雀发布)。所有 backendRefs 的 weight 总和通常为 100 或 10000 (取决于实现约定),未指定的后端默认为 1
backendRefs:
  - name: my-service-v1 # 转发到 my-service-v1
    port: 80
    weight: 90 # 90% 流量
  - name: my-service-v2 # 转发到 my-service-v2
    port: 80
    weight: 10 # 10% 流量

备注#

  1. HTTPRoute 看上去只默认支持 wrr,对于其它类型的负载均衡算法没有原生支持。可能需要使用 Annotation 或者 ExtensionRef 来实现。

ReferenceGrant#

6e7dffc7988ff656860d323100f9830f_MD5

ReferenceGrant 是 Gateway API 中的一个核心安全机制,它解决了跨命名空间引用问题,即允许一个命名空间中的资源(例如 HTTPRoute)引用另一个命名空间中的资源(例如 ServiceGateway

在 Kubernetes 中,默认情况下,资源是无法跨命名空间“看到”或“引用”彼此的,这是一种安全沙箱机制。Gateway API 中的路由和 Gateway 资源经常需要引用位于不同命名空间中的后端服务或 Gateway 本身。如果没有 ReferenceGrant,这种跨命名空间引用将被默认阻止,从而导致 Gateway 无法正确路由流量。

ReferenceGrant 的作用就是显式地授权一个命名空间中的资源引用另一个命名空间中的特定类型的资源。它是一个授权许可,而不是一个配置指令。

一个配置样例如下:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: foo
  namespace: foo
spec:
  rules:
  - matches:
    - path: /bar
    backendRefs:
      - name: bar
        namespace: bar
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: bar
  namespace: bar
spec:
  from:
  - group: gateway.networking.k8s.io
    kind: HTTPRoute
    namespace: foo
  to:
  - group: ""
    kind: Service

备注#

  1. ReferenceGrant 机制的实现完全依赖于 Gateway 控制器。如果一个 Gateway 控制器选择忽略 ReferenceGrant,那么它可以直接实现跨命名空间引用,而不会依赖 ReferenceGrant 资源。这样带来的缺陷是对约定的 Gateway API 规范的违背和潜在的安全风险。

核心特性与优势#

  1. 强大的表达能力:

    • 支持更复杂的路由匹配条件(HTTP 方法、请求头、查询参数)。
    • 细粒度的流量权重分配,轻松实现 A/B 测试、金丝雀发布等。
    • 灵活的流量操纵(URL 重写、重定向)。
    • 多层次的规则定义,更好地组织和管理路由。
  2. 出色的可扩展性:

    • 支持 Policy 附件:可以通过 Policy 资源将额外的配置(如限速、认证、WAF 规则)附加到 Gateway、Route 或 Service 上,而无需修改核心 API 对象。
    • 自定义 Route 类型:允许开发者定义自己的 Route 类型来支持特殊的协议或路由需求。
  3. 清晰的角色分离:

    • 基础设施提供商: 负责注册 GatewayClass
    • 集群操作员: 负责部署和管理 Gateway 资源,定义对外暴露的方式、监听端口和协议。
    • 应用程序开开发者: 专注于创建 Route 资源,定义如何将流量路由到他们的服务。
    • 这种分离降低了操作的复杂性,提高了安全性,并允许不同团队独立工作。
  4. 多协议支持:

    • 原生支持 HTTP、HTTPS、TLS、TCP 和 UDP 流量的路由。
  5. 增强的安全性:

    • ReferenceGrant 机制通过明确的授权来限制跨命名空间资源引用,防止未授权的访问和配置。
  6. 更好的可移植性:

    • 作为标准 API,所有兼容 Gateway API 的控制器都将遵循相同的规范,这意味着路由配置在不同实现之间是高度可移植的。

Reference#