API网关功能以及未来展望
Contents
我们平台项目中其实一直在考虑API网关的功能扩展, 目前使用的K8s Ingress以及Istio提供的Istio gateway, 额外功能实在不多, 仅仅能实现暴露接口的需求. 我近期也认真调研了下市场中的API网关产品, 针对这些产品, 简单介绍下功能以及给出一些自己对于未来发展方向的考量. 希望能抛砖引玉. 愿读者分享自己对于API网关的展望. 我提了一些方案, 有兴趣的读者可以业余一起做做看.
极简功能
目前我们所使用的网关有两种, 我在之前的博客中都有介绍: Kubernetes Ingress, Istio Ingress Gateway. 用的功能不多, 基本只有灰度和转发, 鉴权, 限流的功能完全没依靠它们实现.
Kubernetes Ingress
我们使用的是K8s社区基于OpenResty的实现, 与Service来配合使用:
1 |
|
Istio Ingress Gateway
由于某些原因, 不得不使用这种Ingress, 需要一起使用Gateway和VirtualService, 也需要Service
1 | # 指定要接收流量的gateway |
现有的网关与插件功能
我个人认为网关不应该只有普通的转发功能, 还包括鉴权, 限流等功能, 这些功能应该是网关的一部分, 并且应该是可以插件化的. 我不一定要求直接编辑Nginx配置, 但是当我想增加扩展的时候, 希望可以有这么一个选项. 下面就按照我自己的调研内容.
Kong
之前看到Kong这个产品, 它的底层使用了OpenResty, 但是实现了插件系统, 可以说是Kubernetes社区Ingress的增强版. 也支持Python, Golang的一类插件, 我简单介绍下使用方式:
1 |
|
我比较喜欢它的交互逻辑, 当你有多个域名时, 每个域名可以设置自己启用的插件及其配置. 它已经是成熟的商业化产品, 所以可用性方面还是很强的, 很可惜目前还不支持Wasm.
Istio
Istio中使用的Envoy, 已经支持了wasm插件.
1 | apiVersion: extensions.istio.io/v1alpha1 |
不过即使是最新版本的Istio对插件的支持都不怎么样, 没法单独针对一个virtual service增加插件. 这里的selector是针对ingress gateway的. 也就是说, 所有网关上的virtual service都会被影响. 而且多个插件的行为是使用proiority来控制的, 用户的交互会十分困难, 可用性太差了.
几种可能方向与技术预研
针对几种可能的方案, 我做了一些简单的探索和研究. 这里我贴出的方案, 我都调研了其可能的实现策略, 也都有把握将其落地. 读者有什么想法也可以一起与我交流.
针对Kong可能的优化
单从交互逻辑以及可用性方面, 我觉得没什么可优化的, 唯一让我觉得难受的地方就是无法使用wasm类型的插件.
有几种可能的方案:
- 类似kong的Golang, Python插件, 远程rpc调用来实现
- Lua实现vm, 直接运行Wasm代码
- 将Wasm嵌入到OpenResty, 这是一种支持Wasm的思路: https://github.com/api7/wasm-nginx-module
我臆测这是Kong团队会考量后两种. 对于第一种, Python, Golang类插件所带来的维护成本, 用户体验也并不友好. 后面两种, 它对于Wasm是原生的支持. 不管是后期维护, 还是性能方面, 感觉都会好很多.
针对Istio可能的优化
交互逻辑上
由于Envoy原生支持Wasm, 所以这块我比较看好. 但是如果想要作为网关, 交互逻辑上可能需要改造下, 绑定到VirtualService或是Gateway上是比较合理的.
1 |
|
Envoy Lua插件支持
为什么要支持Lua插件 我看中的是Kong现有的插件生态. 几乎所有的Lua插件都是经过了企业级的认证, 如果能在Istio+Envoy中直接使用, 相信很多用户会愿意使用Envoy作为网关.
Lua插件的支持其实有两种可行方案的:
Lua直接编译到wasm, 据我搜集到的资料来看, 没有现成的编译器, 需要自己手写
近期看到, 网易数帆针对Envoy添加了Lua支持, 也就可以考虑模拟Kong的PDK来使用其插件
https://xie.infoq.cn/article/1cb74a7512460b7d4dbc9f42c
博客中内容, 我觉得性能检测那边有点问题, 无论何种语言编写的wasm插件, 它已经变成了类似汇编的字节码, 性能差距不应该很大, 博客中以C++来做最有的效果衡量让我感觉不是很有说服力. 但是博客切实的将Lua嵌入到了Envoy, 性能可以慢慢优化, 做出来成品还是很重要的.
扩展型sidecar
我的博客中有许多讨论PaaS平台建设的文章, 我本人也在维护一个PaaS平台, 所以我也从PaaS的角度给出一些方案.
上面两种改造方案是需要我们去改进控制器以及底层代码来实现的. 对于一个PaaS平台来说, 我们不会深入到这样的底层系统, 对它改造太困难了.
如果我们想要拥有完善的网关功能, 同时考虑用户的交互逻辑, 比较好的策略是用户在代码中指定一些特殊配置, 无论是使用nginx
, lua
或是wasm
配置,
我们都对其支持. 使用类似Istio中sidecar的形式, 该sidecar仅作为API网关, 并不截取所有流量. 这样考虑有两点:
- 性能问题, sidecar与pod扩缩容绑定, 理论上讲与Istio的性能一致
- 扩展性很重要, 如果我们只是简单的使用Istio, 用户的需求很可能无法尽快满足, 这一点上的响应速度会很慢
个人看法与PaaS平台方向
技术本身没有什么好坏, 只有适合不适合.
对于PaaS平台, 可扩展性和简易的交互逻辑是很重要的, 我们有成百上千个小项目, 就会有各种各样的需求. 我们不能寄希望于完全使用Istio的描述文件来扩展平台功能, 而是应该总结需求的底层逻辑, 在现有方案无法支持的情况下提出备用方案给用户. 我们应该会采用扩展型sidecar的形式, 允许用户写一部分配置并托管到Git仓库.
我个人喜好, 当我个人用K8s维护几个小的项目时, 我自己倒是很希望一些功能的插件化, 因此我个人比较喜欢类似Kong插件的形式进行交互, 但是我又想要有Wasm的支持. 所以我会偏好Istio+Envoy的形式, 如果能够改进Wasm的插件形式并且使用有Lua功能支持的Envoy, 我可能会把自己的项目全部切到Istio上. 业余时间应该我会考虑改进Istio的控制器.
总结
文章篇幅比较多, 你可以把它理解为一份调查报告. 基本都是现有的业务逻辑分析, 还有个人拙见. 大佬们觉得对于哪种方向有看法或是兴趣, 都很欢迎与我讨论和沟通.