在 2021 年我们举办的几乎每场有关 Ingress 控制器和服务网格的网络研讨会中,我们都听到过类似的问题:“这个工具与 API 网关有何不同?”或“在 Kubernetes 中我是否同时需要 API 网关和 Ingress 控制器(或服务网格)?”
这种混乱是完全可以理解的,原因有二:
在这篇博客中,我们将讨论这些工具的区别以及哪些工具适用于 Kubernetes 特定的 API 网关用例。 如需深入了解(包括演示),请观看网络研讨会“Kubernetes 的 API 网关用例” 。
从本质上讲,API 网关、Ingress 控制器和服务网格都是一种代理,旨在将流量引入和绕过您的环境。
API 网关将 API 请求从客户端路由到适当的服务。 但是对这个简单定义的一个很大的误解是认为 API 网关是一项独特的技术。 它不是。 相反,“API 网关”描述了一组可以通过不同类型的代理实现的用例——最常见的是 ADC 或负载均衡器和反向代理,以及越来越多的 Ingress 控制器或服务网格。
对于作为 API 网关的工具必须具备哪些功能,业界并没有达成太多共识。 我们通常会看到客户需要以下能力(按用例分组):
几乎所有这些用例都是 Kubernetes 中常用的。 协议转换和请求/响应标头和正文操作不太常见,因为它们通常与不适合 Kubernetes 和微服务环境的遗留 API 相关联。
在我们的博客上将NGINX 部署为 API 网关(第 1 部分)中了解有关 API 网关用例的更多信息。
Ingress 控制器(也称为 Kubernetes Ingress 控制器 - 简称 KIC)是一种专门的第 4 层和第 7 层代理,可将流量引入 Kubernetes、服务,然后再返回(称为入口出口或南北流量)。 除了流量管理之外,Ingress 控制器还可用于可视性和故障排除、安全性和身份以及除最先进的 API 网关用例之外的所有用例。
欲详细了解如何使用 Ingress 控制器进行不仅仅是基本的流量管理,请参阅《Ingress 控制器选择指南(第 1 部分)》: 确定您的需求 在我们的博客上。
服务网格处理 Kubernetes 服务之间的流量(称为服务到服务或东西向流量),通常用于实现端到端加密(E2EE)。 随着越来越多的组织启动高级部署或对 E2EE 有要求,服务网格的采用率虽然不高,但正在不断增长。 服务网格可以用作非常接近应用程序的分布式(轻量级)API网关,这通过服务网格边车在数据平面级别实现。
在我们的博客“如何选择服务网格”中了解有关服务网格的更多信息 - 以及何时准备好使用服务网格。
正如我们在 Mark Church 在NGINX Sprint 2.0关于Kubernetes 和application网络的未来的主题演讲中听到的那样,“API 网关、负载均衡器和服务网格将会变得越来越相似,并提供类似的功能”。 我们完全同意这一说法,并进一步补充一点,一切都取决于你在哪里(以及如何)使用工具来完成工作,从而选择合适的工具。 毕竟,砍刀和黄油刀都是用来切割的,但您可能不会在早上吃吐司时使用前者。
那么,您如何决定哪种工具适合您? 我们会简单一点:如果您需要 Kubernetes 内部的 API 网关功能,那么最好选择可以使用原生 Kubernetes 配置工具(例如 YAML)进行配置的工具。 通常,这是一个 Ingress 控制器或服务网格。 但是我们听到您说,“我的 API 网关工具比我的 Ingress 控制器(或服务网格)具有更多的功能——我是不是错过了什么?” 不! 更多功能并不等于更好的工具,特别是在 Kubernetes 中,工具的复杂性可能是一个致命问题。
笔记: Kubernetes‑native (与Knative不同)是指为 Kubernetes 设计和构建的工具。 通常,它们与 Kubernetes CLI 一起工作,可以使用 Helm 进行安装,并与 Kubernetes 功能集成。
大多数 Kubernetes 用户更喜欢以 Kubernetes 原生方式配置的工具,因为这样可以避免改变开发或 GitOps 体验。 YAML 友好工具有三大优点:
入口控制器有可能实现许多 API 网关用例。 除了定义中概述的之外,我们发现组织最看重可以实现以下功能的 Ingress 控制器:
您想要实现方法级匹配和路由,使用 Ingress 控制器拒绝 API 请求中的POST
方法。
一些攻击者通过发送不符合 API 定义的请求类型来寻找 API 中的漏洞 - 例如,向定义为仅接受GET
请求的 API 发送POST
请求。 Web应用防火墙 (WAF) 无法检测到这些类型的攻击 - 它们仅检查请求字符串和正文是否存在攻击 - 因此最佳做法是在 Ingress 层使用 API 网关来阻止恶意请求。
举例来说,假设新的 API /coffee/{coffee-store}/brand
刚刚添加到您的集群。 第一步是使用 NGINX Ingress Controller 公开 API - 只需将 API 添加到上游
字段即可。
api版本:k8s.nginx.org/v1kind: 虚拟服务器
元数据:
名称:cafe
规范:
主机:cafe.example.com
tls:
秘密:cafe-secret
上游:
-名称:tea
服务:tea-svc
端口: 80
-名称:coffee
服务:coffee-svc
端口: 80
为了启用方法级匹配,您需要向路线
字段添加/coffee/{coffee-store}/brand
路径,并添加两个使用$request_method
变量区分GET
和POST
请求的条件
。 任何使用 HTTP GET
方法的流量都会自动传递到咖啡
服务。 使用POST
方法的流量将被定向到错误页面,并显示“您
被
拒绝!”
消息。 就这样,您就保护了新 API 免受不必要的POST
流量的侵害。
路线: - 路径:/coffee/{coffee-store}/brand
匹配:
- 条件:
- 变量:$request_method
值: POST
操作:
返回:
代码: 403
类型:text/plain
正文: “您被拒绝了!”
- 条件:
- 变量:$request_method
值: GET
操作:
密码:咖啡
- 路径:/茶
操作:
密码:茶
有关如何使用方法级路由和匹配错误页面的更多详细信息,请查看NGINX Ingress Controller 文档。 有关使用 Ingress 控制器实现 API 网关功能的安全相关示例,请阅读我们博客上的使用 Okta 和 NGINX Ingress Controller 为 Kubernetes 实现 OpenID Connect 身份验证。
对于大多数 API 网关用例来说,服务网格不是必需的(甚至最初也没有帮助),因为您可能想要完成的大多数工作都可以(并且应该)在 Ingress 层发生。 但是随着架构复杂性的增加,您更有可能从使用服务网格中获得价值。 我们发现最有益的用例与 E2EE 和流量分割有关 - 例如 A/B 测试、金丝雀部署和蓝绿部署。
您想要在服务之间设置金丝雀部署,并根据 HTTP/S 标准进行条件路由。
其优点是,您可以逐步推出 API 更改(例如新功能或版本),而不会影响大部分生产流量。
目前,您的 NGINX Ingress Controller 在由 NGINX Service Mesh 管理的两个服务之间路由流量: Coffee.frontdoor.svc
和Tea.frontdoor.svc
。 这些服务从 NGINX Ingress Controller 接收流量并将其路由到适当的应用程序功能,包括Tea.cream1.svc
。 您决定重构Tea.cream1.svc
,并将新版本命名为 Tea.cream2.svc
。 您希望 Beta 测试人员针对新功能提供反馈,因此您根据 Beta 测试人员的唯一会话 cookie 配置金丝雀流量分割,确保您的常规用户只能体验Tea.cream1.svc
。
使用 NGINX Service Mesh,首先在Tea.frontdoor.svc
所依赖的所有服务(包括Tea.cream1.svc
和Tea.cream2.svc
)之间创建流量分割。 要启用条件路由,您需要创建一个HTTPRouteGroup
资源(名为tea-hrg
)并将其与流量分割关联起来,结果是只有来自 beta 用户的请求(会话 cookie 设置为version=beta 的
请求)才会从Tea.frontdoor.svc
路由到Tea.cream2.svc
。 您的常规用户将继续仅体验Tea.frontdoor.svc
背后的版本 1 服务。
api版本:split.smi-spec.io/v1alpha3kind: TrafficSplit
元数据:
名称:tea-svc
规格:
服务:tea.1
后端:
-服务:tea.1
权重: 0
- 服务:茶.2
重量: 100
匹配项:
- 种类: HTTPRouteGroup
名称:tea-hrg
apiVersion:specs.smi-spec.io/v1alpha3
种类: HTTPRouteGroup
元数据:
名称:tea-hrg
命名空间:默认
规范:
匹配:
-名称:beta-session-cookie
标头:
-cookie:“version=beta”
此示例以 0-100 的比例开始您的金丝雀部署,这意味着您的所有 beta 测试人员都会体验Tea.cream2.svc
,但当然您可以从符合您的 beta 测试策略的任何比例开始。 一旦您的 Beta 测试完成,您可以使用简单的金丝雀部署(不使用 cookie 路由)来测试Tea.cream2.svc
的弹性。
请查看我们的文档以获取有关使用 NGINX Service Mesh 进行流量分割的更多详细信息。 上述流量分割配置是自引用的,因为根服务也被列为后端服务。 服务网格接口规范( smi-spec ) 目前不支持此配置;不过,该规范目前处于 alpha 阶段,可能会发生变化。
虽然 Kubernetes 的大多数 API 网关用例可以(并且应该)通过 Ingress 控制器或服务网格来解决,但在某些特殊情况下,API 网关工具(例如 NGINX Plus)是合适的。
虽然多个团队或项目可以共享一组 Ingress 控制器,或者可以根据每个环境专门使用 Ingress 控制器,但您可能选择在 Kubernetes 内部部署专用 API 网关,而不是利用现有的 Ingress 控制器。 在 Kubernetes 内部同时使用 Ingress 控制器和 API 网关可以为组织提供灵活性以实现业务需求。 一些场景包括:
将现有 API 迁移到 Kubernetes 环境时,您可以将这些 API 发布到部署在 Kubernetes 之外的 API 网关工具。 在这种情况下,API 流量通常通过外部负载均衡器(用于集群之间的负载均衡)路由,然后路由到配置为 API 网关的负载均衡器,最后路由到 Kubernetes 集群内的 Ingress 控制器。
虽然大多数现代 API 都是使用 REST 创建的(部分原因是 RESTful 或 gRPC 服务和 API 能够充分利用 Kubernetes 平台),但您可能仍有一些尚未重新架构的 SOAP API。 虽然不建议在 Kubernetes 中使用 SOAP API,因为它们并未针对微服务进行优化,但您最终可能需要在 Kubernetes 中部署 SOAP API,直到可以重新架构为止。 API 可能需要与基于 REST 的 API 客户端进行通信,在这种情况下,您需要一种在 SOAP 和 REST 协议之间进行转换的方法。 虽然您可以使用 Ingress 控制器执行此功能,但我们不建议这样做,因为它非常耗费资源。 相反,我们建议将 API 网关工具部署为每个 pod 或每个服务的代理,以在 SOAP 和 REST 之间进行转换。
我们中只有相对较少的客户对管理跨 Kubernetes 环境内部和外部的 API 感兴趣。 如果 API 管理策略比选择 Kubernetes 原生工具的优先级更高,那么部署在 Kubernetes 中的“Kubernetes 友好型”API 网关(可以与 API 管理解决方案集成)可能是正确的选择。
笔记: 与 Kubernetes 原生工具不同, Kubernetes 友好型工具(有时也称为Kubernetes 适应型工具)并非为 Kubernetes 设计,无法使用 Kubernetes 配置进行管理。但是,它们灵活轻便,可以在 Kubernetes 中运行,不会增加显著的延迟或需要大量的解决方法。
NGINX 为所有三种类型的部署场景提供了选项。
Kubernetes 原生工具:
首先申请 NGINX Ingress Controller 与 NGINX App Protect WAF 和 DoS 的30 天免费试用版,然后下载始终免费的 NGINX Service Mesh。
对于 Kubernetes 环境内部或外部的 Kubernetes 友好型 API 网关:
要了解有关使用 NGINX Plus 作为 API 网关的更多信息,请申请30 天免费试用,并参阅将 NGINX 部署为 API 网关。
“这篇博文可能引用了不再可用和/或不再支持的产品。 有关 F5 NGINX 产品和解决方案的最新信息,请探索我们的NGINX 产品系列。 NGINX 现在是 F5 的一部分。 所有之前的 NGINX.com 链接都将重定向至 F5.com 上的类似 NGINX 内容。”