乐趣区

您可以在Kubernetes中使用API​​网关公开微服务吗

在 Kubernetes 中,Ingress 是一个组件,可将流量从群集外部路由到群集中的服务和 Pod。

简而言之,Ingress 充当反向代理或负载平衡器:所有外部流量都路由到 Ingress,然后路由到其他组件。

尽管最受欢迎的 Ingress 是 ingress-nginx 项目,但是在选择和使用 Ingress 时还有其他几种选择。

您可以从以下 Ingress 控制器中选择:

  • 处理诸如 Contour 或 Treafik Ingress 之类的 HTTP 流量
  • 支持 UDP 和 TCP 流量,例如 Citrix Ingress
  • 支持 Websocket,例如 HAProxy Ingress

还有其他混合式 Ingress 控制器可以与现有的云提供商集成,例如 Zalando 的 Skipper Ingress。

当谈到 Kubernetes 中的 API 网关时,有一些流行的选择可供选择。

选项 1 — API 网关之王:Kong

如果要构建 API,则可能会对 Kong Ingress 提供的功能感兴趣。

Kong 是建立在 Nginx 之上的 API 网关。

Kong 专注于 API 管理,并提供身份验证,速率限制,重试,断路器等功能。

Kong 的有趣之处在于它以 Kubernetes Ingress 的形式打包。

因此,它可以在您的群集中用作用户和后端服务之间的网关。

您可以使用标准 Ingress 对象将 API 暴露给外部流量:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            backend:
              serviceName: api-service
              servicePort: 80

但是

在安装过程中,Kong 的控制器会注册自定义资源定义(CRD)。

这些自定义扩展之一与 Kong 的插件有关。

如果您希望通过 IP 地址限制对 Ingress 的请求,则可以使用以下方法创建限制的定义:

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: rl-by-ip
config:
  hour: 100
  limit_by: ip
  second: 10
plugin: rate-limiting

您可以在 Ingress 中使用以下注释来引用限制:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    plugins.konghq.com: rl-by-ip
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            backend:
              serviceName: api-service
              servicePort: 80

您可以在官方文档中浏览有关 Kong 的自定义资源定义(CRD)。

但是 Kong 不是唯一的选择。

选项 2 –Ambassador,现代 API 网关

Ambassador 是另一个基于 Envoy 构建的 Kubernetes Ingress,它提供了强大的 API 网关。

Ambassador Ingress 是 Kubernetes Ingress 控制器的现代代表,它提供了强大的协议支持以及速率限制,身份验证 API 和可观察性集成。

与 Kong 的主要区别在于 Ambassador 是为 Kubernetes 构建的,并与它很好地集成在一起。

Kong 于 2015 年开源,当时 Kubernetes Ingress 控制器还不那么先进。

即使在设计 Ambassador 时就考虑到 Kubernetes,它也不会利用熟悉的 Kubernetes Ingress。

而是使用注释将服务公开给外界:

apiVersion: v1
kind: Service
metadata:
  labels:
    service: api-service
  name: api-service
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v0
      kind: Mapping
      name: example_mapping
      prefix: /
      service: example.com:80
      host_rewrite: example.com
spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80
  selector:
    service: api-backend

新颖的方法非常方便,因为您可以在一个地方为 Deployments 和 Pod 定义所有路由。

但是,将 YAML 作为注释中的自由文本可能会导致错误和混乱。

在标准 YAML 中很难正确设置格式,更不用说在更多 YAML 中使用字符串了。

如果您希望对 API 应用速率限制,这就是 Ambassador 中的样子。

您有一个 RateLimiting 对象,它定义了需求:

apiVersion: getambassador.io/v1beta1
kind: RateLimit
metadata:
 name: basic-rate-limit
spec:
 domain: ambassador
 limits:
  - pattern: [{x_limited_user: "false"}, {generic_key: "qotm"}]
    rate: 5
    unit: minute
  - pattern: [{x_limited_user: "true"}, {generic_key: "qotm"}]
    rate: 5
    unit: minute

您可以通过以下方式在服务中引用速率限制:

apiVersion: v1
kind: Service
metadata:
  name: api-service
  annotations:
    getambassador.io/config: |
      ---
      apiVersion: ambassador/v1
      kind: RateLimitService
      name: basic-rate-limit
      service: "api-service:5000"
spec:
  type: ClusterIP
  selector:
    app: api-service
  ports:
    - port: 5000
      targetPort: http-api

Ambassador 提供了有关速率限制的出色教程,因此,如果您对使用该功能感兴趣,可以直接转到 Ambassador 的官方文档。

您可以使用用于路由的自定义过滤器扩展 Ambassador,但它没有像 Kong 那样提供充满活力的插件生态系统。

选项 3 - 集大成者 gloo

Ambassador 并不是唯一可以用作 API 网关的由 Envoy 驱动的 Ingress。

Gloo 是 Kubernetes Ingress,也是 API 网关。它能够提供速率限制,熔断,重试,缓存,外部身份验证和授权,转换,服务网格集成和安全性。

Gloo 的卖点是它能够自动发现您的应用程序的 API 端点并自动理解参数。

可能很难相信(有时他们的文档也无济于事),所以这里有个例子。

假设您有一个通讯录的 REST API。

该应用程序公开以下端点:

  • GET /users/{id},获取用户的个人资料
  • GET /users,获取所有用户
  • POST /users/find,找到一个特定的用户

如果您的 API 是使用标准工具(例如 OpenAPI)开发的,那么 Gloo 会自动使用 OpenAPI 定义来内省您的 API 并存储三个端点。

如果在发现阶段之后列出了 Gloo 服务的所有端点,那么您将看到:

upstreamSpec:
  kube:
    selector:
      app: addressbook
    serviceName: addressbook
    serviceNamespace: default
    servicePort: 8080
    serviceSpec:
      rest:
        swaggerInfo:
          url: http://addressbook.default.svc.cluster.local:8080/swagger.json
        transformations:
          findUserById:
            body:
              text: '{"id": {{ default(id,"") }}}'
            headers:
              :method:
                text: POST
              :path:
                text: /users/find
              content-type:
                text: application/json
          getUser:
            body: {}
            headers:
              :method:
                text: GET
              :path:
                text: /user/{{default(id, "") }}
              content-length:
                text: '0'
              content-type: {}
              transfer-encoding: {}
          getUsers:
            body: {}
            headers:
              :method:
                text: GET
              :path:
                text: /users
              content-length:
                text: '0'
              content-type: {}
              transfer-encoding: {}

Gloo 具有端点列表之后,您可以使用该列表在传入请求到达后端之前将转换应用于传入请求。

例如,您可能希望从传入的请求中收集所有标头,然后在请求到达应用程序之前将它们添加到 JSON 有效负载中。

或者,您可以公开 JSON API,并让 Gloo 应用转换以在消息到达旧组件之前将消息呈现为 SOAP。

能够发现 API 和应用转换使 Gloo 特别适用于具有多种技术的环境 - 或当您正处于从旧系统到新堆栈的迁移过程中。

Gloo 可以发现其他种类的终端节点,例如 AWS Lambdas。

当您希望混合搭配 Kubernetes 和无服务器时,这使其成为完美的伴侣。

将 Istio 用作 API 网关

API 网关和服务网格之间有什么区别?

难道两个都没有做同一件事吗?

两者都提供:

  • 路由流量
  • 验证,例如 OAuth,JWT 等。
  • 限速
  • 断路器
  • 重试
  • 等等

但是,有一个区别。

诸如 Kong 和 Ambassador 之类的 API 网关主要侧重于处理外部流量并将其路由到集群内部。

外部流量是一个广泛的标签,其中包括:

  • 快速和慢速的客户
  • 行为良好且恶意的用户

换句话说,API 网关旨在保护您的应用程序不受外界干扰。

相反,服务网格主要用于观察和保护基础结构中的应用程序。

服务网格的典型用途包括:

  • 监视和观察应用之间的请求
  • 使用加密(相互 TLS)保护服务之间的连接
  • 通过断路器,重试等提高弹性

由于服务网格是与您的应用程序一起部署的,因此它们受益于:

  • 低延迟和高带宽
  • 不太可能被滥用

换句话说,服务网格的主要目的是管理内部服务到服务的通信,而 API 网关主要用于外部客户端到服务的通信。

但这并不意味着您不能将 Istio 用作 API 网关。

不过,可能会阻止您的是 Istio 的首要任务不是处理外部流量。

让我们看一个例子。

通常的做法是,通过 JWT 或 OAuth 身份验证在 API 网关后面保护您的 API 调用。

Istio 提供了 JWT,但是您必须在 Lua 中注入自定义代码才能使其与 OAuth 一起使用。

另一方面,Kong 为此提供了一个插件,因为这是常见的要求。

企业 API 网关(例如 Google Apigee)具有计费功能。

这些功能不太可能在服务网格中复制,因为重点不在管理 API 上。

如果您不关心计费该怎么办,还可以将服务网格用作 API 网关吗?

是的,您可以,还有一些您应该知道的事情。

关于 API 网关和服务网格的一般说明

根据您要实现的目标,服务网格和 API 网关的功能可能会大大重叠。

由于每个主要的 API 网关供应商都在扩展到服务网格,因此它们将来可能会重叠得更多。

  • Kong 宣布了 Kuma 一个可以与 Kong 或 Istio 集成的服务网格
  • http://Solo.io 宣布了与 Gloo 集成的服务网格 SuperGloo
  • Containous 宣布 Maesh 与 Traefik 集成的服务网格

而且,看到更多服务网格决定像 Istio 一样启动 API 网关也就不足为奇了。

总结

如果必须为 Kubernetes 选择 API 网关,应该使用哪一个?

  • 如果您需要经过生产验证的 API 网关,那么 Kong 仍然是您的最佳选择。它可能不是最光辉的,但是该文档非常有用,在线资源丰富。与其他网关相比,它的生产里程也最多。
  • 如果您需要一个灵活的 API 网关,可以很好地与新旧基础架构配合使用,则应该看看 Gloo。自动发现 API 和转换请求的能力引人注目。
  • 如果您希望在服务中轻松设置所有网络,则应考虑使用 Ambassador。它具有出色的教程和文档入门。请注意,YAML 缩进是一个自由字符串。

如果必须选择 API 网关或服务网格,则应使用哪一个?

从 API 网关开始仍然是确保内部应用程序不受外部客户端保护的最佳选择。

随着应用程序数量的增加,您可以探索如何利用服务网格来观察,监视和保护它们之间的流量。

PS:本文属于翻译,原文

退出移动版