vlambda博客
学习文章列表

API 网关功能以及未来展望


API 网关功能以及未来展望

我们平台项目中其实一直在考虑 API 网关的功能扩展,目前使用的 K8s Ingress 以及 Istio 提供的 Istio gateway,额外功能实在不多,仅仅能实现暴露接口的需求。我近期也认真调研了下市场中的 API 网关产品,针对这些产品,简单介绍下功能以及给出一些自己对于未来发展方向的考量,希望能抛砖引玉,愿读者分享自己对于 API 网关的展望。我提了一些方案,有兴趣的读者可以业余一起做做看。

API 网关功能以及未来展望

极简功能

目前我们所使用的网关有两种,我在之前的博客中都有介绍 :  Kubernetes Ingress[1]Istio Ingress Gateway[2]。用的功能不多,基本只有灰度和转发,鉴权,限流的功能完全没依靠它们实现。

Kubernetes Ingress

我们使用的是 K8s 社区基于 OpenResty 的实现,与 Service 来配合使用:

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: arya-prod
spec:
  rules:
  - host: arya.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: arya-svc
          servicePort: 80

Istio Ingress Gateway

由于某些原因,不得不使用这种 Ingress,需要一起使用 Gateway 和 VirtualService,也需要 Service。

# 指定要接收流量的gateway
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: arya-gateway
  namespace:  xxx-group-2
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "arya-python3.istio.xxx.com"

# virtual-service用于说明gateway的流量如何处理
# 可以看到,这里是允许使用前缀路径来做转发的,这种方案可以不需要DestinationRule
# 完全用kubernetes的service来做
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: arya-virtual-service
  namespace:  xxx-group-2
spec:
  hosts:
  - "arya-python3.istio.xxx.com"
  gateways:
  - arya-gateway
  http:
  - match:
    - uri:
        prefix: /static
    route:
    - destination:
        host: prod-arya-python3-static
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: prod-arya-python3

现有的网关与插件功能

我个人认为网关不应该只有普通的转发功能,还包括鉴权,限流等功能,这些功能应该是网关的一部分,并且应该是可以插件化的。我不一定要求直接编辑 Nginx 配置,但是当我想增加扩展的时候,希望可以有这么一个选项。下面就按照我自己的调研内容。

Kong

Kong 文档[3]

之前看到 Kong 这个产品,它的底层使用了 OpenResty,但是实现了插件系统,可以说是 Kubernetes 社区 Ingress 的增强版。也支持 Python,Golang 的一类插件,我简单介绍下使用方式:

---
apiVersion: configuration.konghq.com/v1
plugin: openid-connect
kind: KongPlugin
metadata:
  name: oidc-auth
config:
  issuer: https://accounts.google.com/.well-known/openid-configuration
  client_id:
  - <client-id>
  client_secret:
  - <client-secret>
  redirect_uri:
  - http://192.0.2.8.xip.io
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: productpage
  namespace: bookinfo
  annotations:
    konghq.com/plugins: oidc-auth  # 多个插件可以使用数组
spec:
  ingressClassName: kong
  rules:
  - http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: productpage
            port:
              number: 9080

我比较喜欢它的交互逻辑,当你有多个域名时,每个域名可以设置自己启用的插件及其配置。它已经是成熟的商业化产品,所以可用性方面还是很强的,很可惜目前还不支持 Wasm。

Istio

Istio 文档[4]

Istio 中使用的 Envoy,已经支持了 wasm 插件。

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: openid-connect
  namespace: istio-ingress
spec:
  selector:
    labels:
      istio: ingressgateway
  url: oci://private-registry:5000/openid-connect/openid:latest
  imagePullPolicy: IfNotPresent
  imagePullSecret: private-registry-pull-secret
  phase: AUTHN
  pluginConfig:
    openid_server: authn
    openid_realm: ingress

不过即使是最新版本的 Istio 对插件的支持都不怎么样,没法单独针对一个 virtual service 增加插件。这里的 selector 是针对 ingress gateway 的,也就是说,所有网关上的 virtual service 都会被影响。而且多个插件的行为是使用 proiority 来控制的,用户的交互会十分困难,可用性太差了。

几种可能方向与技术预研

针对几种可能的方案,我做了一些简单的探索和研究。这里我贴出的方案,我都调研了其可能的实现策略,也都有把握将其落地。读者有什么想法也可以一起与我交流。

针对 Kong 可能的优化

单从交互逻辑以及可用性方面,我觉得没什么可优化的,唯一让我觉得难受的地方就是无法使用 wasm 类型的插件。

有几种可能的方案:

  1. 类似 kong 的 Golang,Python 插件,远程 rpc 调用来实现
  2. Lua 实现 vm,直接运行 Wasm 代码
  3. 将 Wasm 嵌入到 OpenResty,这是一种支持 Wasm 的思路 : https://github.com/api7/wasm-nginx-module

我臆测这是 Kong 团队会考量后两种。对于第一种,Python,Golang 类插件所带来的维护成本,用户体验也并不友好 . 后面两种,它对于 Wasm 是原生的支持。不管是后期维护,还是性能方面,感觉都会好很多。

针对 Istio 可能的优化

交互逻辑上

由于 Envoy 原生支持 Wasm,所以这块我比较看好。但是如果想要作为网关,交互逻辑上可能需要改造下,绑定到 VirtualService 或是 Gateway 上是比较合理的。

---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: arya-virtual-service
  namespace:  xxx-group-2
  annotations:
    istio.io/plugins: oidc-auth  # 多个插件可以使用数组
spec:
  hosts:
  - "arya-python3.istio.xxx.com"
  gateways:
  - arya-gateway
  http:
  - match:
    - uri:
        prefix: /static
    route:
    - destination:
        host: prod-arya-python3-static
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        host: prod-arya-python3

Envoy Lua 插件支持

为什么要支持 Lua 插件 我看中的是 Kong 现有的插件生态。几乎所有的 Lua 插件都是经过了企业级的认证,如果能在 Istio+Envoy 中直接使用,相信很多用户会愿意使用 Envoy 作为网关。

Lua 插件的支持其实有两种可行方案的:

  1. Lua 直接编译到 wasm,据我搜集到的资料来看,没有现成的编译器,需要自己手写
  2. 近期看到,网易数帆针对 Envoy 添加了 Lua 支持,也就可以考虑模拟 Kong 的 PDK 来使用其插件

https://xie.infoq.cn/article/1cb74a7512460b7d4dbc9f42c

博客中内容,我觉得性能检测那边有点问题,无论何种语言编写的 wasm 插件,它已经变成了类似汇编的字节码,性能差距不应该很大,博客中以 C++来做最有的效果衡量让我感觉不是很有说服力。但是博客切实的将 Lua 嵌入到了 Envoy,性能可以慢慢优化,做出来成品还是很重要的。

扩展型 sidecar

我的博客中有许多讨论 PaaS 平台建设的文章,我本人也在维护一个 PaaS 平台,所以我也从 PaaS 的角度给出一些方案。

上面两种改造方案是需要我们去改进控制器以及底层代码来实现的。对于一个 PaaS 平台来说,我们不会深入到这样的底层系统,对它改造太困难了。如果我们想要拥有完善的网关功能,同时考虑用户的交互逻辑,比较好的策略是用户在代码中指定一些特殊配置,无论是使用 nginxlua 或是 wasm 配置,我们都对其支持。使用类似 Istio 中 sidecar 的形式,该 sidecar 仅作为 API 网关,并不截取所有流量。这样考虑有两点:

  1. 性能问题,sidecar 与 pod 扩缩容绑定,理论上讲与 Istio 的性能一致
  2. 扩展性很重要,如果我们只是简单的使用 Istio,用户的需求很可能无法尽快满足,这一点上的响应速度会很慢
API 网关功能以及未来展望

个人看法与 PaaS 平台方向

技术本身没有什么好坏,只有适合不适合。

对于 PaaS 平台,可扩展性和简易的交互逻辑是很重要的,我们有成百上千个小项目,就会有各种各样的需求。我们不能寄希望于完全使用 Istio 的描述文件来扩展平台功能,而是应该总结需求的底层逻辑,在现有方案无法支持的情况下提出备用方案给用户。我们应该会采用扩展型 sidecar 的形式,允许用户写一部分配置并托管到 Git 仓库。

我个人喜好,当我个人用 K8s 维护几个小的项目时,我自己倒是很希望一些功能的插件化,因此我个人比较喜欢类似 Kong 插件的形式进行交互,但是我又想要有 Wasm 的支持。所以我会偏好 Istio+Envoy 的形式,如果能够改进 Wasm 的插件形式并且使用有 Lua 功能支持的 Envoy,我可能会把自己的项目全部切到 Istio 上。业余时间应该我会考虑改进 Istio 的控制器。

总结

文章篇幅比较多,你可以把它理解为一份调查报告。基本都是现有的业务逻辑分析,还有个人拙见。大佬们觉得对于哪种方向有看法或是兴趣,都很欢迎与我讨论和沟通。

引用链接

[1]

Kubernetes Ingress: https://corvo.myseu.cn/2019/11/05/2019-11-05-Kubernetes中Ingress的使用/

[2]

Istio Ingress Gateway: https://corvo.myseu.cn/2021/06/22/2021-06-22-Istio-%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8(Gateway)/

[3]

Kong 文档: https://docs.konghq.com/kubernetes-ingress-controller/2.3.x/guides/configure-acl-plugin/

[4]

Istio 文档: https://istio.io/latest/docs/reference/config/proxy_extensions/wasm-plugin/


API 网关功能以及未来展望

API 网关功能以及未来展望


你可能还喜欢

RethinkDB:为什么我们失败了

API 网关功能以及未来展望

云原生是一种信仰 🤘

后台回复◉k8s◉获取史上最方便快捷的 Kubernetes 高可用部署工具,只需一条命令,连 ssh 都不需要!



API 网关功能以及未来展望

点击 "阅读原文" 获取更好的阅读体验!