在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:本文属于翻译,原文