我们在 2021 年举办的 Ingress Controller 和 Service Mesh 网络研讨会中,几乎每场都会听到以下类似的问题:“这个工具与 API 网关有什么不同?”,或者,“我需要在 Kubernetes 中同时使用 API 网关和 Ingress Controller(或 Service Mesh)吗?”。
我们完全可以理解这些困惑,原因有二:
- Ingress Controller 和 Service Mesh 适用于多种 API 网关用例。
- 一些厂商将他们的 API 网关工具定位为 Ingress Controller 或 Service Mesh 的替代方案,或者将这三种功能全部整合到一个工具中。
本文将探讨这些工具的不同之处,以及针对不同的 Kubernetes API 网关用例该选用哪种工具。有关详细内容(包括演示),请观看网络研讨会:“Kubernetes 的 API 网关用例”。
定义
API 网关、Ingress Controller 和 Service Mesh 本质上都是一种代理,旨在管理您多种环境内的流量进入和流动。
什么是 API 网关?
API 网关将 API 请求从客户端路由到适当的服务,但人们却对这个简单定义存在很大的误解,认为 API 网关是一种独特的技术,实则不然。“API 网关”描述了一组可以通过不同类型的代理(ADC 或负载均衡器和反向代理最为常见,Ingress Controller 和 Service Mesh 日渐兴起)实现的用例。
对于一个工具必须具备哪些功能才能充当 API 网关,业界尚未达成共识。我们发现,客户通常需要以下能力(按用例分):
弹性用例
- A/B 测试、灰度部署和和蓝绿部署
- 协议转换(例如在 JSON 和 XML 之间转换)
- 速率限制
- 服务发现
流量管理用例
- 基于方法(method-based)的路由和匹配
- 请求/响应标头和正文操作
- 在七层请求路由
安全用例
- API 模式实施
- 客户端身份验证和授权
- 自定义响应
- 细粒度访问控制
- TLS 终止
几乎上述所有用例在 Kubernetes 中都很常见。协议转换以及请求/响应标头和正文操作相对少见一些,因为它们通常与不太适合 Kubernetes 和微服务环境的传统 API 相关联。
如欲了解有关 API 网关用例的更多信息,请参阅我们的博文“将 NGINX 部署为 API 网关(第 1 部分)” 。
什么是 Ingress Controller?
Ingress controller (也叫 Kubernetes Ingress Controller,简称 KIC)是一个专用的四层和七层代理,用于管理进出 Kubernetes 环境和服务的流量(称为出入向流量或南北向流量)。除了流量管理之外,Ingress Controller 还可提供可视化和故障排除、安全防护和身份验证,并且几乎可以实现最高级的 API 网关用例。
如欲了解关于 Ingress Controller 基本流量管理之外的功能,请参阅我们的博文“Ingress Controller 选购指南,第 1 部分:确定您的需求”。
什么是 Service Mesh?
Service Mesh 负责处理 Kubernetes service 之间的流量(简称 service 到 service 流量或东西向流量),通常用于实现端到端加密 (E2EE)。随着越来越多的企业开启高级部署或产生 E2EE 需求,原本应用较少的 Service Mesh 正日益受到更多关注。Service Mesh 能够在非常靠近应用的地方用作分布式(轻量级)API 网关,这可以通过 Service Mesh sidecar 在数据平面上实现。
如欲了解有关 Service Mesh 以及使用场景的更多信息,或准备使用 Service Mesh 请参阅我们的博文“如何选择 Service Mesh”。
为 Kubernetes 环境使用 Kubernetes 原生工具
Mark Church 在 NGINX Sprint 2.0 主旨演讲“Kubernetes 和应用网络的未来”中说道,“未来,API 网关、负载均衡器和 Service Mesh 的特征和功能将会变得越来越相近”。我们完全同意这种说法,但我们的侧重点是如何根据工具的使用位置(或方式)选择合适的工具。毕竟合适的才是好用的。
那么如何确定哪种工具适合您呢?我们有个简单的办法:如果您需要在 Kubernetes 内使用 API 网关功能,通常来说最好选择可以使用 Kubernetes 原生配置工具(例如 YAML)进行配置的工具,也就是 Ingress Controller 或 Service Mesh。但有人疑惑:“我的 API 网关工具的功能比 Ingress Controller(或 Service Mesh)多很多,是我忽略了什么吗?”不是!功能越多不等于工具越好,尤其在 Kubernetes 中,工具太过复杂反而会成为一大致命因素。
注: “Kubernetes 原生”(不同于 Knative)指专门为 Kubernetes 设计和构建的工具。通常,它们与 Kubernetes CLI 一起使用,可以使用 Helm 安装,并与 Kubernetes 功能集成。
大多数 Kubernetes 用户更喜欢以 Kubernetes 原生方式配置的工具,因为这样可以避免调整开发或 GitOps 体验。YAML 友好型工具有三大优势:
- 由于 Kubernetes 团队都熟悉 YAML 语言,如果您使用现有 Kubernetes 工具实现 API 网关功能,他们的学习难度就会大大降低甚至为零。您的团队可以运用现有技能完成工作,而无需费心学习如何配置那些可能只是偶尔用到的新工具。
- 与其他 Kubernetes 工具一样,YAML 友好型工具也能够以同样的方式实现自动化。只要是可以干净利索地融入工作流程的工具,就都会受到团队的欢迎,使用率也会因此增加。
- 您可以使用 Ingress Controller 或 Service Mesh 或同时使用两者来压缩您的 Kubernetes 流量管理工具堆栈。毕竟,每一次额外的跳转都很重要,我们没有理由增加不必要的延迟或单点故障。当然,减少 Kubernetes 中的技术部署数量也有利于降低预算和提高整体安全性。
南北向 API 网关用例:使用 Ingress Controller
Ingress Controller 能够支持多种 API 网关用例。除了上文“定义”中所述的用例之外,我们发现企业最看重可以实现以下功能的 Ingress Controller:
- 卸载身份验证和授权
- 基于授权的路由
- 7 层路由和匹配(HTTP、HTTP/S、标头、cookie、方法)
- 协议兼容性(HTTP、HTTP/2、WebSocket、gRPC)
- 速率限制
示例场景:方法级路由
若您想要实现方法级的匹配和路由,您需要使用 Ingress Controller 来拒绝 API 请求中的 POST
方法。
一些攻击者会通过发送不符合 API 定义的请求类型来寻找 API 中的漏洞,例如向定义为只接收 GET
请求的 API 发送 POST
请求。Web 应用防火墙 (WAF) 无法检测到这些类型的攻击(它们只检查攻击的请求字符串和正文),因此最好在 Ingress 层中使用 API 网关,以阻止恶意请求。
举例来说,假设您的集群刚刚添加了新的 API /coffee/{coffee-store}/brand
。第一步是使用 NGINX Ingress Controller 暴露 API(只需将 API 添加到 upstreams
字段)。
apiVersion: k8s.nginx.org/v1kind: VirtualServer
metadata:
name: cafe
spec:
host: cafe.example.com
tls:
secret: cafe-secret
upstreams:
-name: tea
service: tea-svc
port: 80
-name: coffee
service: coffee-svc
port: 80
要启用方法级匹配(method-level matching),您应在 routes
字段中添加 /coffee/{coffee-store}/brand
路径,并添加两个使用 $request_method
变量的conditions
,以区分 GET
和 POST
请求。任何使用 HTTP GET
方法的流量都会自动传递到 coffee
服务。使用 POST
方法的流量将被定向到一个错误页面,并提示 "You
are
rejected!"
这样,您就可以保护新 API 不受非法 POST
流量的影响。
routes: - path: /coffee/{coffee-store}/brand
matches:
- conditions:
- variable: $request_method
value: POST
action:
return:
code: 403
type: text/plain
body: "You are rejected!"
- conditions:
- variable: $request_method
value: GET
action:
pass: coffee
- path: /tea
action:
pass:tea
有关如何使用方法级路由和匹配并弹出错误页面的更多信息,请参阅 NGINX Ingress Controller 文档。有关使用 Ingress Controller 实现 API 网关功能的安全性相关的示例,请阅读我们博文“借助 Okta 和 NGINX Ingress Controller 实现 Kubernetes 的 OpenID Connect 身份验证”。
东西向 API 网关用例:使用 Service Mesh
对于大多数 API 网关用例来说,Service Mesh 不是必需的,甚至一开始也不会提供任何帮助,因为您想做的大多数事情都可以在 Ingress 层完成,也理应在这里完成。但随着架构复杂性的增加,Service Mesh 的价值也将日益彰显。我们发现,E2EE 和流量分割用例(例如 A/B 测试、灰度部署和蓝绿部署)最能体现 Service Mesh 的价值。
示例场景:灰度部署
您希望使用基于 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 服务。
apiVersion: split.smi-spec.io/v1alpha3kind: TrafficSplit
metadata:
name: tea-svc
spec:
service: tea.1
backends:
- service: tea.1
weight: 0
- service: tea.2
weight: 100
matches:
- kind: HTTPRouteGroup
name: tea-hrg
apiVersion: specs.smi-spec.io/v1alpha3
kind: HTTPRouteGroup
metadata:
name: tea-hrg
namespace: default
spec:
matches:
- name: beta-session-cookie
headers:
- cookie: "version=beta"
此示例的灰度部署使用 0-100 分割,这意味着您的所有 Beta 测试人员都将体验 Tea.cream2.svc
,当然,您也可以根据您的 Beta 测试策略选择合适的比例。Beta 测试完成后,您可以使用一个简单的灰度部署(不包含 cookie 路由)来测试 Tea.cream2.svc
的弹性。
有关 NGINX Service Mesh 流量分割的更多信息,请参阅我们的文档。上面的流量分割配置是自引用的,因为根服务也被列为后端服务。Service Mesh 接口规范 (smi-spec) 目前不支持此配置,但是该规范目前处于 alpha 阶段,可能会进行修改。
何时(以及如何)为 Kubernetes 应用部署 API 网关工具
虽然 Kubernetes 的大多数 API 网关用例可以(并且应该)用 Ingress Controller 或 Service Mesh 解决,但在一些特殊情况下 API 网关工具(例如 NGINX Plus)也适用。
业务要求
虽然多个团队或项目可以使用同一套 Ingress Controller,也可以在不同的环境中使用不同的 Ingress Controller,但出于各种原因,您可能会选择在 Kubernetes 内部部署专用的 API 网关,而不是利用现有的 Ingress Controller。在 Kubernetes 中同时使用 Ingress Controller 和 API 网关可以为企业提供出色的灵活性以满足业务需求。部分场景包括:
- 您的 API 网关团队不熟悉 Kubernetes,也不使用 YAML。例如,如果他们不熟悉 NGINX 配置——那么在 Kubernetes 中将 NGINX Plus 部署为 API 网关后可以减少团队间冲突和并减缓学习曲线。
- 您的平台运营团队更喜欢只使用 Ingress Controller 管理应用流量。
- 您有一个只适用于集群中某一服务的 API 网关用例。与其使用 Incress Controller 为所有南北向流量应用某种策略,不如部署 API 网关,只在需要的地方应用该策略。
将 API 迁移到 Kubernetes 环境中
在将现有 API 迁移到 Kubernetes 环境中时,您可以将这些 API 发布到部署在 Kubernetes 外部的 API 网关工具上。在这种情况下,API 流量通常通过外部负载均衡器(用于集群之间的负载均衡)进行路由,然后进入被配置为 API 网关的负载均衡器,最后进入 Kubernetes 集群中的 Ingress Controller。
支持 Kubernetes 中的 SOAP API
虽然大多数现代 API 都是使用 REST 创建的(部分原因是 RESTful 或 gRPC 服务和 API 能够充分利用 Kubernetes 平台),但您可能仍有一些 SOAP API 没有进行重新架构。虽然我们不建议在 Kubernetes 中使用 SOAP API(因为它没有针对微服务进行优化),但是在还没有重新生成架构前您可能还是需要在 Kubernetes 中部署它的。API 有可能需要与基于 REST 的 API 客户端通信,在这种情况下,您需要一种在 SOAP 和 REST 协议之间进行转换的方法。虽然您可以使用 Ingress Controller 执行此功能,但我们不建议您这样做,因为这种做法非常耗费资源。我们建议您按 pod 或按服务将 API 网关工具部署为代理,以便在 SOAP 和 REST 之间进行转换。
Kubernetes 内外的 API 流量管理
我们还有一小部分客户比较关注 Kubernetes 内外的 API 流量管理。如果 API 管理策略的优先级高于选择 Kubernetes 原生工具,那么部署在 Kubernetes 中的“Kubernetes 友好型”API 网关(可以与 API 管理解决方案集成)可能是您正确的选择。
注: 与 Kubernetes 原生工具不同,Kubernetes 友好型工具(有时也称为 Kubernetes 适应型工具)不是专为 Kubernetes 设计的,不能使用 Kubernetes 配置来管理。但是,它们轻巧便捷,便于在 Kubernetes 中执行,既不会显著增加延迟,也无需进行大量的变通。
开始使用 NGINX
NGINX 为上述三种部署场景提供了选项。
Kubernetes 原生工具:
- NGINX Ingress Controller —— 面向 Kubernetes 的基于 NGINX Plus 的 Ingress Controller ,可实现高级的流量控制和整形、监控和可视化、身份验证和单点登录 (SSO)。
- NGINX Service Mesh —— 一种对开发人员友好的轻量级、可立即使用的 Service Mesh,能够将 NGINX Plus 用作企业级 sidecar。
欢迎申请 NGINX Ingress Controller(带有 NGINX App Protect WAF 和 DoS)30 天免费试用版,并下载永久免费的 NGINX Service Mesh。
对于 Kubernetes 环境内外的 Kubernetes 友好型 API 网关:
- NGINX Plus—— 可用作一体化负载均衡器、反向代理、Web 服务器和 API 网关,并具有高可用性、主动健康检查、DNS 系统发现、会话持久化和 RESTful API 等企业级特性。可与 NGINX Controller 相集成,打造 API 全生命周期解决方案。
如欲详细了解如何将 NGINX Plus 用作 API 网关,请申请30 天免费试用版,并参阅“将 NGINX 部署为 API 网关”。