定义
它们的核心,API网关、Ingress Controller和服务网格都是一种代理,他们就是将流量通过他们来管理。
什么是API Getway?
API网关将API请求从客户端路由到适当的服务。但是关于这个简单定义的一个很大的误解是认为API网关是一种独特的技术。事实并非如此。相反,API网关描述了一组用例,这些用例可以通过不同类型的代理实现,最常见的是ADC或负载平衡器和反向代理,越来越多的是入口控制器或服务网格。
API 网关"必须具备"哪些功能,业界并没有达成太多共识。 但是我们知道他通常需要以下能力(按用例分组):
弹性:
- A/B 测试、金丝雀部署和蓝绿部署
- 协议转换(例如 JSON 和 XML 之间)
- 速率限制
- 服务发现
流量管理
- 基于方法的路由和匹配
- 请求/响应标头和正文操作
- 第7层请求路由
安全管理
- API模式实现
- 客户端认证和授权
- 自定义响应
- 细粒度的访问控制
- TLS终止
几乎所有这些用例都在 Kubernetes 中常用。协议转换以及请求/响应标头和正文操作不太常见,因为它们通常与不太适合 Kubernetes 和微服务环境的旧 API 绑定。 要了解有关 API 网关用例的更多信息,请参阅我们博客上的将NGINX 部署为 API 网关,第 1 部分。
什么是Ingress Controller
Ingress Controller(也称为 Kubernetes 入口控制器 - 简称 KIC)是一种专门的第 4 层和第 7 层代理,它将流量传入 Kubernetes、服务并再次返回(称为入口-出口或南北向流量) )。除了流量管理之外,入口控制器还可用于可见性和故障排除、安全和身份等用例。
请参阅我们博客上的"选择 Ingress 控制器指南,第 1 部分:确定您的要求",了解有关如何使用 Ingress 控制器进行基本流量管理以外的更多信息。
什么是### Service Mesh
服务网格处理 Kubernetes 服务之间的流量(称为服务到服务或东西向流量),通常用于实现端到端加密 (E2EE)。服务网格的采用规模很小,但随着越来越多的组织启动高级部署或对 E2EE 有需求,其采用率也在不断增长。服务网格可以用作非常接近应用程序的分布式(轻量级)API 网关,这可以通过服务网格边车在数据平面级别上实现。
在 Kubernetes 环境中使用 Kubernetes 原生工具
正如我们从 Mark Church 在他关于 Kubernetes 和应用程序网络的未来的 NGINX Sprint 2.0 主题演讲中听到的那样,"API 网关、负载均衡器和服务网格将继续看起来越来越相似,并提供相似的功能"。我们完全同意这一说法,并进一步补充说,这一切都是为了根据您将在何处(以及如何)使用它来选择适合工作的工具。毕竟,砍刀和黄油刀都用于切割,但你可能不会在早上的吐司上使用前者。
那么您如何决定哪种工具适合您呢?我们简单来看:如果您需要 Kubernetes 内的 API 网关功能,通常最好选择可以使用本机 Kubernetes 配置工具(例如 YAML)进行配置的工具。通常是Ingress Controller或服务网格。但我们听到您说,"我的 API 网关工具比我的 Ingress 控制器(或服务网格)拥有更多的功能 - 难道我没有错过吗?"不!更多的功能并不等于更好的工具,特别是在 Kubernetes 中,工具的复杂性可能是一个杀手。
注意:Kubernetes-native(与 Knative 不同)是指为 Kubernetes 设计和构建的工具。通常,它们与 Kubernetes CLI 配合使用,可以使用 Helm 安装,并与 Kubernetes 功能集成。
大多数 Kubernetes 用户更喜欢用 Kubernetes 原生方式配置的工具,因为这样可以避免改变开发或 GitOps 体验。 YAML工具具有三大优势:
- YAML 是 Kubernetes 团队熟悉的语言,因此如果您使用现有的 Kubernetes 工具来实现 API 网关功能,则学习曲线很小,甚至根本不存在。这有助于您的团队在现有技能范围内工作,而无需学习如何配置他们可能偶尔使用的新工具。
- 您可以像其他 Kubernetes 工具一样自动化 YAML 友好的工具。任何完全适合您的工作流程的东西都会受到您的团队的欢迎 - 增加他们使用它的可能性。
- 您可以使用 Ingress Controller、服务网格或两者来缩小 Kubernetes 流量管理工具堆栈。毕竟,每一个额外的跃点都很重要,没有理由增加不必要的延迟或单点故障。当然,减少 Kubernetes 中部署的技术数量也有利于您的预算和整体安全性。
南北 API 网关用例:使用Ingress Controller
Ingress Controller可以支持许多 API 网关用例。除了定义中概述的内容之外,我们发现最看重能够实现以下功能的 Ingress 控制器:
- 卸载身份验证和授权
- 控制授权的路由
- 第 7 层级别路由和匹配(HTTP、HTTP/S、标头、cookie、方法)
- 协议兼容性(HTTP、HTTP/2、WebSocket、gRPC)
- 速率限制
示例场景:方法级路由
您想使用Ingress Controller拒绝API请求中的POST方法。 一些攻击者通过发送不符合API定义的请求类型来寻找API中的漏洞 - 例如,将POST请求发送到仅接受GET请求的API。 Web应用程序防火墙(WAF)无法检测到这类攻击 - 他们仅检查请求字符串和body以进行攻击 - 因此,最好在Ingress层使用API网关来阻止恶意请求。
例如,假设新的API/Coffee/{coffee-store
}/brand 刚刚添加到您的群集中。 第一步是使用NGINX Ingress Controller暴露API - 只需将API添加到上游字段中即可。
yaml
apiVersion: k8s.nginx.org/v1
kind: 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
启用方法级匹配,您可以在路由字段中添加 /coffee/{coffee-store}/brand 路径,并添加两个使用$ request_method变量来区分GET和POST请求的条件。 使用HTTP GET方法的任何流量将自动传递给咖啡服务。 使用POST方法的流量重定向到一个错误页面,并带有消息"您被拒绝!" 就这样,您保护了新的API不会接受到不需要的POST流量。
yaml
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文档。 有关与API网关功能使用Ingress Controller使用的安全性相关示例,请在我们的博客上使用OKTA和NGINX INGRESS COLLLANTER为KUBERNETES实现OpenID连接身份验证。
东西API网关用例:使用Server Mesh
对于大多数API网关用例,不需要服务网格,因为您可能想完成的大部分可能会在入口层上发生并且应该发生。 但是,随着复杂性的增加,您更有可能从使用服务网格中获得价值。 我们发现最有益的用例与E2EE和流量分裂有关,例如A/B测试,金丝雀部署和蓝绿色部署。
案例:金丝雀部署
您想根据HTTP/S标准在有条件的路由下设置服务之间的金丝雀部署。
优点是您可以逐渐推出API更改(例如新功能或版本),而不会影响大多数生产流量。 当前,您的NGINX Ingress Controller在由Nginx服务网络管理的两个服务之间路由流量:Coffee
.frontdoor.svcand 和Tea.frontdoor.svc。
这些服务从Nginx Ingress Controller接收流量,并将其路由到适当的应用程序功能,包括Tea.Cream1.svc。 您决定重构Tea
.cream1.svc,调用新版本tea.cream2.svc。 您希望您的Beta测试人员提供有关新功能的反馈,以便根据Beta Testers的独特会话cookie配置金丝雀流量拆分,以确保您的常规用户到tea.cream1.svc。
使用NGINX Server Mesh,您首先在所有由Tea.frontdoor.svc前面的服务之间创建流量,其中包括Tea.Cream1.svc和Tea.Cream.Cream2.SVC。 要启用条件路由,您可以创建一个httproutegroup资源(命名为tea-hrg)并将其与流量拆分相关联,其结果是只有从beta用户请求(带有session cookie设置为version = beta的请求)才能从 tea.frontdoor.svc to tee.cream2.svc。 您的常规用户继续仅在tea.frontdoor.svc。
yaml
apiVersion: split.smi-spec.io/v1alpha3
kind: 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"