从 Envoy Gateway 看 Gateway API 扩展性

从 Envoy Gateway 看 Gateway API 扩展性

概览

gwapi

Gateway API 支持三种扩展方式,如:

  • 针对 GatewayClass 提供 parametersRef
  • 针对 xRoute 提供 per-route、per-backend 的 implementation-specific filter (ExtensionRef)
  • 针对 Gateway 和 xRoute 整体 提供 PolicyAttachment

对比

下面通过一个表格来对比三种扩展的区别:

扩展方式生效对象生效范围面向角色作用
parametersRefGatewayClassGatewayClass 下所有的 Gateway 资源infrastructure provider为所管理 Gateway 提供通用配置
PolicyAttachmentGateway、xRoute网关级别、整体 Route 级别(xRoute下所有 Rule 生效)operator、developer为 Gateway 和 整体 Route 提供默认和覆盖值
ExtensionRefxRoute路由 (Rule) 级别、服务 (Backend) 级别developer为某个路由或者某个服务提供扩展能力

根据上面的表格,可以看出,三种扩展方式,分别在不同对象,不同范围内生效。

在不同场景下,我们可以根据具体需求选择扩展方式:

  • 针对只能在 路由/服务 级别生效的扩展能力,推荐使用 ExtensionRef,面向开发者(对 Envoy 来说,不是所有 filter 都支持路由级别的,这些扩展不适合使用 ExtensionRef 作为扩展)。
  • 针对需要针对整个 Gateway / 整体 Route 下所有 Rule 的场景,如安全相关,可以考虑使用 PolicyAttachment,这样不用在每个 Route 的每个 Rule 里配置重复的扩展配置,面向集群管理员和开发者。
  • 针对整体 Gateway 的通用配置,如所有网关的副本数等,应该在 GC 上使用 parametersRef,面向集群管理员,基础设施提供商。

Envoy Gateway 扩展 Gateway API

Envoy Gateway 基于 Gateway API 作为顶层配置语言,在实现了所有核心 Gateway API 定义的同时,也基于 Gateway API 的扩展点进行了扩展。

下面我们通过 Envoy Gateway 去看三种 Gateway API 扩展的具体实例

从 EnvoyProxy CRD 看 GatewayClass parametersRef

GatewayClass 往往被供应商所维护,定义了 Gateway 具体的实现,如:

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: eg
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller

在集群中安装好 Envoy Gateway 后,这个 GatewayClass 会被 Envoy Gateway 识别(对比 controllerName)。Gateway 资源的创建时需要指定关联的 GatewayClass,也意味着这个 Gateway 资源会被 Envoy Gateway 控制面所管理,如:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: eg
spec:
  gatewayClassName: eg
  listeners:
    - name: http
      protocol: HTTP
      port: 8080

创建 Gateway 资源后,集群中会自动创建 EnvoyProxy 的实例,由于 EnvoyProxy 的资源(Deployment/Service)是由 Envoy Gateway 控制面所管理,假如这个时候用户想对创建的 EnvoyProxy 实例资源进行修改怎么办?比如更改 EnvoyProxy 的 Service Annotation 或者 Service Type。

在 GatewayClass 的层级,Gateway API 提供了 parametersRef 支持引用自定义资源,去管理此 GatewayClass 所有的资源。

Envoy Gateway 于是定义了一个 CRD 叫做 EnvoyProxy,用户可以通过创建 EnvoyProxy CR,去对 EnvoyProxy 进行定制化,如:

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
  name: custom-proxy-config
  namespace: envoy-gateway-system
spec:
  provider:
    type: Kubernetes
    kubernetes:
      envoyService:
        annotations:
          custom1: svc-annotation1
          custom2: svc-annotation2

此 EnvoyProxy CR 描述了对创建的 EnvoyProxy Service,添加了两个自定义 annotations。创建了 EnvoyProxy CR 之后,需要在 GatewayClass 中引用:

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: eg
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller
  parametersRef:
    group: gateway.envoyproxy.io
    kind: EnvoyProxy
    name: custom-proxy-config
    namespace: envoy-gateway-system

接着 Envoy Gateway 控制面会读取这个 CR 并将配置更新到 EnvoyProxy Kubernetes 资源中。

从 EnvoyPatchPolicy 看 PolicyAttachment

除了 parametersRef,Gateway API 还提供了 PolicyAttachment 这种机制,扩展的对象是整体的 Gateway 或者 xRoute(HTTPRoute、gRPCRoute、UDPRoute)。

EnvoyPatchPolicy 是 Envoy Gateway 基于 PolicyAttachment 机制提供的一个 CRD,用于对指定的 Gateway(EnvoyProxy 实例)更新它的 xDS 配置信息,如:

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyPatchPolicy
metadata:
  name: custom-response-patch-policy
  namespace: default
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: Gateway
    name: eg
    namespace: default
  type: JSONPatch
  jsonPatches:
    - type: "type.googleapis.com/envoy.config.listener.v3.Listener"
      # The listener name is of the form <GatewayNamespace>/<GatewayName>/<GatewayListenerName>
      name: default/eg/http
      operation:
        op: add
        path: "/default_filter_chain/filters/0/typed_config/local_reply_config"
        value:
          mappers:
          - filter:
              status_code_filter:
                comparison:
                 op: EQ
                 value:
                   default_value: 404
                   runtime_key: key_b
            status_code: 406
            body:
              inline_string: "could not find what you are looking for"

可以看到上述 EnvoyPatchPolicy 的对象是:

  targetRef:
    group: gateway.networking.k8s.io
    kind: Gateway
    name: eg
    namespace: default

Envoy Gateway 控制面在读取到这个信息后,会将上述 xDS 配置 Patch 到对应 EnvoyProxy 中。

相比 GatewayClass,可以看到这种方式更灵活,场景也相对不同,扩展的对象也从 GatewayClass 变为单个 Gateway 或 Route 资源。

从 ratelimit filter 看 extensionRefs

Gateway API 在 xRoute 中,比如 HTTPRoute,可以在 RouteRules 中添加自定义的 Filter,扩展对象进一步缩小,将面对单个路由规则以及后端服务。

Envoy Gateway 之前在实现全局限流时,也是基于这种方式,定义了 RateLimitFilter 这个 CRD 去描述限流规则,然后在 HTTPRoute 引用它,如:

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: RateLimitFilter
metadata:
  name: ratelimit-specific-user
spec:
  type: Global
  global:
    rules:
    - clientSelectors:
      - headers:
        - name: x-user-id
          value: one
      limit:
        requests: 3
        unit: Hour

对应的 HTTPRoute 配置为:

apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: http-ratelimit
spec:
  parentRefs:
  - name: eg
  hostnames:
  - ratelimit.example 
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    filters:
    - type: ExtensionRef
      extensionRef:
        group: gateway.envoyproxy.io
        kind: RateLimitFilter
        name: ratelimit-specific-user
    backendRefs:
    - group: ""
      kind: Service
      name: backend
      port: 3000

可以看到在 filters 中引用了 ExtensionRef 类型的 Filter,此类型即为自定义的 Filter,会在路由 match 到指定规则后生效。

相比于上两种扩展方式,这个扩展范围更小,面向的是路由规则。

说到最后

本文通过 Envoy Gateway 介绍了三种扩展 Gateway API 的方式,大家也能感受到 Gateway API 在扩展性设计上考虑了很多。

为什么提供这么多扩展方式?求同存异 是 Gateway API 的理念之一。

Gateway API 提供了核心流量规则的描述,同时也支持额外的自定义需求。

比如云厂商在创建 Gateway 后指定的 LB 参数,同时也包括一些 Gateway Specific 的 API,比如 EnvoyPatchPolicy / WASMExtensionPolicy 等这些 EnvoyProxy 特有的能力。

Ingress 往往扩展都往 annotation 这样的非结构化数据上丢的,在 API 可移植性上存在巨大的阻碍,单单 nginx-ingress 的 annotation 就有上百种,更别说其他 Ingress 实现了。

标准化引用 CRD,在 Kubernetes 中,不管是 API 描述,校验,维护、升级上,都远好于 annotation 的 string map,也更适合复杂场景的描述。

相关文章

Envoy Gateway 快速开始

Envoy Gateway 快速开始

本文介绍如何快速部署 Envoy Gateway,以及通过一个简单的例子,来展示如何通过 Envoy Gateway 访问 kubernetes 集群中的服务。

阅读更多
Envoy Gateway 架构设计与开源贡献

Envoy Gateway 架构设计与开源贡献

本文通过介绍 Envoy Gateway 设计与架构,提供开源贡献的指南

阅读更多
Envoy Gateway 治理多集群服务流量

Envoy Gateway 治理多集群服务流量

Envoy Gateway + MCS + Submariner 治理多集群服务流量

阅读更多