可以在 Kubernetes 中通过 API 网关暴露微服务吗?

阅读数:5447 2019 年 5 月 23 日

长话短说:可以。看一下KongAmbassadorGloo等 Ingress 控制器就知道了。

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

简单来说,Ingress 是作为反向代理或负载均衡器:所有外部流量都先路由到 Ingress,然后再路由到其他组件。
图片
虽然最流行的 Ingress 组件是ingress-nginx 项目,但是,在选择和使用 Ingress 时还有其他几个选项。

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

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

谈到 Kubernetes 中的 API 网关,你有三个常见的选项。

选项 1——API 网关的王者:Kong

如果你正在构建 API,那么你可能会对Kong Ingress提供的功能感兴趣。

Kong 是基于 Nginx 构建的一个 API 网关

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

有趣的是,Kong 被包装成一个 Kubernetes Ingress。因此,你可以在集群中使用它作为用户和后端之间的网关。你可以使用标准的 Ingress 对象向外部流量暴露你的 API:

复制代码
#ingress.yaml
apiVersion: extensions/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 的请求,则可以用以下方法定义该限制:

复制代码
#limit-by-ip.yaml
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: rl-by-ip
config:
hour: 100
limit_by: ip
second: 10
plugin: rate-limiting

你可以在 ingress.yaml 文件中通过注解引用该限制:

复制代码
#ingress.yaml
apiVersion: extensions/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——现代化 API 网关 Ambassador

Ambassador是另外一个 Kubernetes Ingress,基于 Envoy 构建,提供了一个健壮的 API 网关。

Ambassador Ingress 是一个现代化的 Kubernetes Ingress 控制器,它提供了健壮的协议支持、速率限制、身份验证 API 和可观测性集成。

Ambassador 与 Kong 的主要区别在于 Ambassador 是为 Kubernetes 设计的,并与之很好地集成。

Kong 是 2015 年开源的,当时 Kubernetes Ingress 控制器还没有那么先进。

但即使 Ambassador 在设计时考虑了 Kubernetes,它也没有利用人们熟悉的 Kubernetes Ingress。相反,服务是通过注解向外部暴露的:

复制代码
#service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
service: api-service
name: api-service
annotations:
getambassador.io/config: |
---
{1} 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

这种新方法非常方便,因为你可以在一个地方为部署和 Pod 定义所有路由。但是,在注解中使用 YAML 作为自由文本可能会导致错误和混淆。在普通的 YAML 中都很难正确地设置格式,更不用说在更大的 YAML 中作为字符串了。如果希望对 API 应用速率限制,以下就是 Ambassador 中的做法。你有一个 RateLimiting 对象,它定义了需求:

复制代码
#rate-limit.yaml
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

你可以在服务中像下面这样引用速率限制:

复制代码
#service.yaml
apiVersion: v1
kind: Service
metadata:
name: api-service
annotations:
getambassador.io/config: |
---
{1} 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 并不是唯一基于 Envoy 且可以用作 API 网关的 Ingress。 Gloo 是一个 Kubernetes Ingress,也是一个 API 网关,能够提供速率限制、断路器、重试、缓存、外部身份验证和授权、转换、服务网格集成和安全性。

Glue 的卖点是它能够自动发现应用程序的 API 端点,并自动理解实参和形参。

我理解,这很难让人相信(他们的文档在这个意义上没有提供什么帮助),所以这里有一个例子。 假设你有一个用于地址簿的 REST API。该应用暴露了以下端点:

  • GET /users/{id}:获取用户资料;
  • GET /users:获取所有用户;
  • POST /users/find:查找特定的用户。

如果你的 API 是使用标准工具(如 OpenAPI)开发的,那么 Gloo 将自动使用 OpenAPI 定义来检查你的 API 并存储这三个端点。如果在发现阶段之后列出 Gloo 提供的所有端点,你将看到:

复制代码
#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 与无服务器时,它可以作为一个完美的搭档。

回顾

下面是对这三个 Ingress 控制器的简单回顾:

Kong Ambassador Gloo
协议 http、https、grpc、tcp、udp http、https、grpc、tcp、udp、tcp+ssl http、https、grpc
基础 Nginx Envoy Envoy
弹性 主动和被动健康检查、断路器、速率限制、重试 速率限制 速率限制、断路器、重试、缓存
状态 在 PostgreSQL 或 Cassandra 中配置,状态保存在 CRD 中 Service CRD
路由定义 作为 Ingress 清单 在 Service 中 作为 Ingress 清单
身份验证 Basic Auth、HMAC、JWT、Key、LDAP、OAuth 2.0、PASETO、OIDC(仅限企业版) Basic Auth、OIDC Basic Auth、OIDC
可扩展性 插件 无,外部集成 插件
仪表板 Kong 企业仪表板或开源社区项目 Dashboard 企业版仪表板

我应该用哪一个?

  • 如果你想要一个经过实战检验的 API 网关,Kong 仍然是你最好的选择。它可能不是最耀眼的,但其文档是最好的,而且网上有很多资源。它的生产里程也比任何其他网关都要长。
  • 如果你需要一个灵活的 API 网关,它可以很好地与新旧基础设施配合使用,那么你应该看看Gloo。自动发现 API 和转换请求的能力非常有吸引力。
  • 如果你希望在你的服务中设置所有网络的简单性,你应该考虑 Ambassador。它有很好的入门教程和文档。注意,YAML 缩进是一个空字符串。

更多选项

如果你认为 Ambassador、Kong 或 Gloo 都不是你想要的,你可参考以下方法:

查看英文原文:Can you expose your microservices with an API gateway in Kubernetes?

收藏

评论

微博

发表评论

注册/登录 InfoQ 发表评论