前几天 Gateway API 宣布在 0.8.0 中支持服务网格,这意味着 GAMMA(Gateway API for Mesh Management and Administration)有了新进展,虽然目前还是实验阶段。去年 6 月 Gateway API 发布 0.5.0 时,我还写了一篇 SMI 与 Gateway API 的 GAMMA 倡议意味着什么?。如今,SMI 作为 sandbox 项目的年度审查已经 过了几个月仍未提交,唏嘘。
废话不多说,我们来看下 0.8.0 下的 Gateway API 如何在 Service Mesh 中工作。
TL;DR
Gateway API 对服务网格的支持仍然是实验阶段,但是已经有厂商跟进(当然也都是实验阶段)。
相比 Gateway API 处理南北向流量将路由绑定到 Gateway 资源 相比,在网格中路由则是与 Service 进行绑定。简单理解成 Service 代理了 Gateway 的角色,不过该 Service 是目标 Service。
Gateway API 中的服务网格
要说服务网格,我们先来看下服务 Service
。
抽象 Service
Service
中 Kubernetes 中是一个独立的资源,这里说的抽象是从逻辑上进行抽象,抽象成前端和后端两部分。
前端(Frontend)通常就是 Service
的 DNS 名字或者 ClusterIP
;后端(Backend)则是通过标签选择器选择的 Endpoint
或者 EndpointSlice
。
路由与服务
把路由直接绑定到 Service 上,被认为是当下最优的选择。Service
与其他资源的耦合度太高,比如 IP 分配、DNS、端点集合、负载均衡等等,但在目前的网格设计中也是唯一的最优选择,未来会寻求更好的选择,比如 ServiceBinding
(见后文)
这样做的好处呢,就是将服务的前后端分别与现在的 xRoute
API 中的 parentRef
和 backendRef
关联,无需引入额外的 API。
不同的时候,在 xRoute
API 中的 backendRef
也可以是一个 Service
,但是最终在路由请求时,目标还是 Endpoint
或者 EndpointSlice
,只不过他们与 parentRef
中的 Service
不是强关联的。
kind: HTTPRoute
metadata:
name: smiley-route
namespace: faces
spec:
parentRefs:
- name: smiley
kind: Service
group: core
port: 80
rules:
...
如果一个 Service 上配置了多个路由,匹配到多条路由的请求将被拒绝。
请求流程
- 客户端发送请求
- 网格数据面代理拦截请求
- 通过虚拟 IP 地址、DNS 主机名、或者名字来确认流量是属于哪个
Service
(不会使用xRoute
上的hostname
字段) - 如果
Service
没有配置路由,将使用请求的原始目的地进行转发 - 找到匹配的优先级最高(消费者路由高于生产者路由,见下文)的路由进行转发
- 如果配置了路由,但都无法匹配,则拒绝请求
路由的命名空间
为什么要提命名空间,是因为路由与服务在相同或者不同命名空间下所代表的含义不同。
同命名空间
路由 smiley-route
与 Service smiley
位于同一个命名空间 faces
,该路由上设置了请求超时时间 100ms
。这意味着,所有访问 Service smiley
(来自任一命名空间下的任一工作负载)并匹配 smiley-route
路由规则的请求,都受该超时配置的影响。
这种路由被称为 生产者路由(Producer Route),影响目标为该服务的所有请求。
kind: HTTPRoute
metadata:
name: smiley-route
namespace: faces
spec:
parentRefs:
- name: smiley
namespace: faces
kind: Service
group: core
port: 80
rules:
...
timeouts:
request: 100ms
不同命名空间
路由 smiley-route
与 Service smiley
位于不同的命名空间,与上面不同的是,所有访问 Service smiley
(来自命名空间 fast-clients
下的任一工作负载)并匹配 smiley-route
路由规则的请求,都受该超时配置的影响。
这种路由被称为 消费者路由(Consumer Route),影响同命名空间下访问木雕服务的所有请求。
kind: HTTPRoute
metadata:
name: smiley-route
namespace: fast-clients
spec:
parentRefs:
- name: smiley
namespace: faces
kind: Service
group: core
port: 80
rules:
...
timeouts:
request: 100ms
同一 Service 上的多个路由
这里的前提条件是这些路由都位于同一命名空间下,即同为生产者路由,或同为消费者路由。这种情况将会遵循 路由合并规则 多这个路由进行合并,如果要为同一命名空间下的多个工作负载配置不同的消费者路由,目前还无法实现。唯一的
比如下面定义了两个消费者路由 smiley-route-50
和 smiley-route-100
kind: HTTPRoute
metadata:
name: smiley-route-50
namespace: fast-clients
spec:
parentRefs:
- name: smiley
namespace: faces
kind: Service
group: core
port: 80
rules:
...
timeouts:
request: 50ms
---
kind: HTTPRoute
metadata:
name: smiley-route-100
namespace: fast-clients
spec:
parentRefs:
- name: smiley
namespace: faces
kind: Service
group: core
port: 80
rules:
...
timeouts:
request: 100ms
路由与策略
之前也写文介绍过 Gateway API 中的策略,有兴趣的可以看一下 一文搞懂 Kubernetes Gateway API 的 Policy Attachment。
在网格中策略附加可以非常简单。策略可以应用于任何命名空间中的任何资源,但如果目标位于不同的命名空间中,则它只能应用于来自同一命名空间的请求(跟随消费者路由的逻辑)。
网格一致性测试
首先来看下何为 一致性配置文件:
Gateway API 会提供用于一致性测试的配置文件,在运行一致性测试可以选择这些配置文件。然后将一致性结果报告回网关 API 项目并获得认证(例如徽章)。除了测试核心的功能,也可以自主添加厂商的特定实现中的扩展功能进行测试。
这些 Gateway API 的实现会将测试报告提交到 官方仓库的一致性测试报告目录 中,可以作为大家选型时的依据之一。
目前有 HTTP
、TLS
、TLSPassthrough
(基本上都是根据 xRoute 来进行组织,因此后续也会有 GRPC
、TCP
、UDP
)。针对服务网格,也提出了 mesh
配置文件。
官方博客 中提到 Kuma 2.3+、Linkerd 2.14+、和 Istio 1.16+ 中的 Gateway API 实现已经全部通过 mesh
一致性测试,但截止目前未看到测试报告,估计还在上传中。