一、API Gateway
网关,就是指一个流量的集中式出入口。而 API Gateway,顾名思义,就是在 Gateway 上再添加了一些 API 相关的功能后得到的东西。
具体而言,API Gateway 就是比普通的网关多干了一些以前我们在应用内部实现的事:身份认证,权限控制,基于来源的流量控制,日志服务等,甚至是直接在第七层魔改 HTTP 请求的内容。好处有:
- API Gateway 把这些功能都从微服务层抽离到了网关层,降低了应用层的复杂度。
- API Gateway 可以将后端微服务的 API 进一步封装成粗粒度 API,降低客户端的请求次数。
- API Gateway 可以将后端 API 封装成更通用的格式,保证后端 API 变动不会影响客户端。
- 等等
Kubernetes 的网关 Ingress 就是一个普通的网关,官方的 Ingress 定义只能进行简单的七层转发配置,第四层转发都不支持。没有 API 层面的东西。
因此很多社区的 Ingerss 实现都通过添加 Annotation 或者 CRDs 来添加额外的特性。
而作为一个 API Gateway,Kong 要比官方的 Ingress Controller 强大很多,它首先兼容了 K8s 的 Ingress 定义,然后又通过 CRDs 添加了一些额外的功能/特性。所有参数都以 K8s yaml 的形式保存与配置。
可以说 Kong 的 “K8s 本地化”是做得非常好了,使用体验上也很不错。
另外服务网格 Istio 为了提升自己对入口网关的掌控力,统一网关层和服务网格的配置,完全抛弃了 Ingress 定义,自己做了一套独立的入口网关,叫 Ingress Gateway.
这个 IngerssGateway 本身就是一个 Envoy,能和 Istio 服务网格无缝融合。这样 Istio 的 Policy/Security 等配置就能直接应用在网关上,不需要在服务网格内部处理(个人猜测)。
API 网关使用 JWT 进行身份验证时,只需要 JWK 公钥(登录时才需要私钥生成 JWT),在 API Gateway 里设置好公钥,就能统一进行身份认证。
选择 API 网关
首先看一下 API Gateway - CNCF LandScape
其中最著名的应该就是 Kong 了,试用后发现 kong 和 kubernetes 的兼容层 Kong/kubernetes-ingress-controller 做得还是比较好的,
通过 Annotation 和 CRDs(k8s 自定义资源)对 Kong 进行配置,Annotation 只用于简单的配置绑定,大部分配置都通过 CRDs 的 yaml 配置实现。体验上比一些纯粹使用 Annotaion 的应用要好不少。
Kong 目前也在积极向服务网格靠拢,不仅自己实现了一套新服务网格 Kuma,也做了 Kong API Gateway 和 Istio 的兼容(虽然说还完全没搜到 Kong+Istio 的落地项目)。
另外国内近期开源了一个新兴的 API Gateway —— APISIX,这同样是一个基于 Openresty,使用 lua 编写的 API Gateway。
不过相比 Kong,它目前对 Kubernetes 的支持还比较弱,近期才添加了通过 yaml 文件进行配置的功能,而和 k8s ingress 的结合现在连 alpha 都算不上。
如果要放在 k8s 里跑,目前只能以 configmap 的方式将 yaml 配置映射到容器中,apisix 自己会轮询该 yaml 的修改。
二、服务网格
Gateway 是控制集群流量的出入,被称作南北向流量管理。
而 Service Mesh 目前主要被用于集群内部微服务之间的流量管控,被称作东西向流量的管理。(目前已经出现了 Service Mesh 和 API Gateway 相互融合的趋势)
Gateway 只需要在集群入口处设置一个「关卡」,而 Service Mesh 为了管理服务之间的流量,它需要在每个容器(微服务)旁边都设置一个网络「关卡」,这被称为 SideCar 模式。
选择服务网格
主流的服务网格目前就两个:Linkerd2 和 Istio,功能方面现在 Linkerd2 正在追赶 Istio。
Istio 现在比 Linkerd2 多一个 Policy 策略限制和认证授权(Authentication/Authorization)功能,这些功能其实属于 API Gateway 的范畴。可见服务网格正在吸收 API Gateway 的一些长处。
其他的流量切分、故障注入、链路追踪/流量拓扑、mTLS 等都大同小异,只是这些功能 Linkerd2 可能没有 Istio 成熟。
Istio 的优势在于功能丰富,而且比较稳定,缺点是性能差,配置复杂。
Linkerd2 优势在于性能优越,配置也可能会更简单些,但是重构后稳定性还需要考察,功能上也没有 Istio 强。
API Gateway 与 Service Mesh(服务网格)
这两个东西并不是非常的泾渭分明,比如 Istio 作为一个服务网格,也搞了一套自己的 IngressGateway 和 EgressGateway,而且 Istio 本身也通过 Policy 和 Authentication/Authorization 实现了一部分 API Gateway 的功能。
现在问题就来了:Istio 弄了一套自己的路由规则,Kong 又是以 k8s Ingress 为基础实现的 k8s 集成。那如果为了使用一部分 Kong 支持而 Istio 没有的特性,我们要同时在 K8s 中用这两个东西呢?该怎么办?我的配置到底是用 Istio IngressGateway 还是 Ingress?Kong 和 Istio 要如何交互?
Kong-Ingress-Controller 在去年 9 月发布的 0.6 版本中,给出的解决方案是:
- 入口网关的规则使用 Kong Ingress 配置,也就是抛弃掉 Istio 的 IngressGateway
- Kong-Ingress-Controller 通过 Envoy SideCar 将流量导入到 Istio 服务网格中。
官方给的示意图如下,可和 Istio 部署示意图 对比查看:
如何为服务网格选择入口网关? 里详细说明了上述集成方案的由来,他给出的图比 Kong 官方的更清楚些:
Kong 使用 k8s Ingerss 和自己的 CRDs 替换掉了 Istio 官方的 Gateway,Istio 服务网格层的 VirtualService 等不变。
这样的一个方案,显然存在性能损耗,Gateway 那里多了一跳(Proxy)。以后的前进方向肯定是 API Gateway 和 Service Mesh 相互融合,待观察了。
Istio
Kong 和 Istio 的集成方式不能令人满意。
一番搜索发现 Istio 本身也支持 jwt 验证,试用之下感觉还行。
另外 Istio 之前通过 Mixer 提供了 rate limiting 等功能,但是这个 Mixer 由于性能问题现在已经被阉割掉了。官方给出的方案是编写 Envoey 的 WASM 插件来实现这个功能。这个有待考察。
总结
目前没有什么好用的方案,等社区发展吧。。
参考
- 谈谈微服务中的 API 网关(API Gateway)
- Kubernetes 中使用 API Gateway 替代 Ingress
- 谈谈 API 网关
- 如何为服务网格选择入口网关?
- The Difference Between API Gateways and Service Mesh
- Api Gateway vs Service Mesh
- 基于 Apache APISIX 的下一代微服务架构
- Kong Ingress Controller 0.6 Released with Support for Admission Controller, Istio, and Kuma
- 浅谈 k8s ingress controller 选型