一文搞懂 Kubernetes Gateway API 的 Policy Attachment
点击上方蓝字
关注我们
在《SMI 与 Gateway API 的 GAMMA 倡议意味着什么?》的一文中,介绍过 Kubernetes Gateway API 处理东西向(网格)流量的可能性。让我们重新看下 Gateway API 中对流量定义(路由)的定义,以 HTTP 路由为例:
apiVersion: gateway.networking.k8s.io/v1beta1kind: HTTPRoutemetadata:name: my-routenamespace: gateway-api-example-ns2spec:parentRefs:- kind: Gatewayname: foo-gatewaynamespace: gateway-api-example-ns1hostnames:- foo.example.comrules:- backendRefs:- name: foo-svcport: 8080
上面的 YAML 中,使用 parentRefs 字段将路由策略附加到了网关资源 foo-gateway 上。网关 foo-gateway 会根据请求头部的 HOST 来选择合适的 HTTPRoute,然后将流量代理到上游 Service foo-svc。简单来说,就是定义了“网关 -> 路由 -> 后端”的映射。
通过对流量的定义以及处理流量的资源的选择,实现7层 HTTP 协议的反向代理和负载均衡。但在实际的场景下,简单的代理路由策略还并不够,可能还需要配合治理策略来提升服务的健壮性,比如限流、重试、超时、熔断、自定义健康检查等等。
我们看下 Istio 的超时配置,首先使用了 reviews 进行流量的匹配,然后再根据路由的策略 uri 前缀 /review 进行路由匹配,将流量代理到目的地 v2 的 reviews。与此同时,该路由的超时为 0.5s。
apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: reviewsspec:hosts:- reviewshttp:- match:- uri:prefix: "/review"route:- destination:host: reviewssubset: v2timeout: 0.5s
在这段定义中耦合了流量匹配、路由匹配、后端指定、超时,如果需要配置重试呢,再加个 retries 字段。如此一来,灵活性大打折扣。
微软MVP实验室研究员
目标
Kubernetes Gateway API 的 策略附件(Policy Attachment)的设计目标:
策略和资源关联标准化
支持策略的默认值和覆盖值
不同资源上策略生效的优先级
为资源施加策略的时候,既要考虑通用性(标准化)又要考虑灵活性(策略值优先级)。
这里说的资源可以是网关相关的任何资源,比如 GatewayClass、Gateway、路由(如 HTTPRoute、TCPRoute、GRPCRoute)、Kubernetes 核心资源(如 Namespace、Service)。后面几种资源还会分命名空间,比如是请求发起方(Gateway、服务消费方)或者请求接收方(服务提供方)的命名空间。
resource-level
这些资源的影响范围各有不同,我们暂且称为粒度,比如 GatewayClass 影响某类网关实现所有实例上的流量;Gateway 资源则特指进入某个网关实例的流量;Namespace 特指由该命名空间下的资源发出或者接收的流量;路由则特指具有某种特征的流量,并且路由的定义可以定义在发起方的命名空间,也可以定义在接收方的命名空间。
可见虽然策略是附加在资源上,但作用的最终目标还是流量:南北向流量和东西向流量,分别对应入口策略和网格策略。▍入口策略
ingress-policy-attachment
▍网格策略
设计
▍策略与资源关联标准化
策略与资源关联的设计引入了 Target Reference API 的概念,即每个策略上必须要有一个 targetRef 字段,通过该字段将资源与策略进行关联,完成解耦。
targetRef 字段一次只能指定一个资源,但是每个策略配置配置不同粒度的资源。比如上面的重试策略,附加在同命名空间下名为 example 的 HTTPRoute 上。将所有具有该特征的流量,连接超时为3,读取超时为5。targetRef 字段的结构固定的,由 Gateway API 的 PolicyTargetReference 进行定义,包含了资源的最最基础信息。apiVersion: networking.example.net/v1alpha1kind: TimeoutPolicymetadata:name: foospec:default:connectionTimeout: 3readTimeout: 5targetRef:kind: HTTPRoutename: example
type PolicyTargetReference struct {Group Group `json:"group"`Kind Kind `json:"kind"`Name ObjectName `json:"name"`Namespace *Namespace `json:"namespace,omitempty"`}
▍默认值和覆盖值
默认值体现的是缺省状态下的策略设置,比如前面具有 HTTPRoute example 描述的特征的流量,通过 spec.default 配置了默认超时时间。
下面的策略,则使用 spec.override 对所有进入 Gateway 资源 example(网关实例)的流量连接超时为5。
那最终哪个值会生效呢?我们可以这样理解,所有的覆盖值的优先级会高于默认值。也就是符合匹配策略条件的流量,会优先使用覆盖值。
apiVersion: networking.example.net/v1alpha1kind: TimeoutPolicymetadata:name: foospec:override:connectionTimeout: 5targetRef:kind: Gatewayname: example
▍策略的优先级
默认值和覆盖值的优先级已经有了,上面在介绍资源的时候提到了资源的级别,并且策略也可以附加到不同的资源上。比如下面的策略定义了读取超时的默认值以及连接超时的覆盖值,附加到了 Service example 上,实际作用的资源是后端(Backend)工作负载。
apiVersion: networking.example.net/v1alpha1kind: TimeoutPolicymetadata:name: foospec:override:connectionTimeout: 1default:readTimeout: 10targetRef:kind: Servicename: example
流量的路径是 Gateway example -> HTTPRoute example -> Backend example。
对于覆盖值,优先级与资源的级别相同;而默认值,则与资源的级别正好相反。因此,最终的生效设置是:
connectionTimeout: 5 # from gateway overridereadTimeout: 10 # from backend default
现状
截止文章发出时,了解到的 Linkerd 在1.12中参考 Policy Attachment 的设计实现了 AuthorizationPolicy,并计划待 Gateway API 中的设计稳定后切换到 Gateway API 的 CRD。
如果你了解有其他的 Policy Attachment 实现,可以在文章下面留言。参考资料
策略附件(Policy Attachment): https://gateway-api.sigs.k8s.io/references/policy-attachment/ Target Reference API: https://gateway-api.sigs.k8s.io/references/policy-attachment/#target-reference-api
*未经授权请勿私自转载此文章及图片。
微软最有价值专家(MVP)
https://mvp.microsoft.com/zh-cn
谢谢你读完了本文!欢迎在评论区留言分享你的想法,并且转发到朋友圈。
点击「阅读原文」加入微软 MVP~