(Note: The phrase "及其" appears redundant after "介绍了API网关的概念及其". This might be a typo or an incomplete suggestion in the expert advice. For the sake of fluency and naturalness, I'll leave it as "介绍了API网关的概念" without adding "及其". If "及其" is meant to add more explanation, the exact phrase would need to be specified in the expert suggestions.)
Final refined translation:
在这篇文章中,我介绍了API网关的概念,并解释了为什么你需要在Kubernetes集群中使用API网关。在我的下一篇文章中,我将展示如何使用Kong设置一个API网关。来连接你的微服务
与我的大多数文章不同,这篇文章更多是理论而非实践。如果你想安装 API 网关,可以看看我写的关于 Kong 安装的文章。
如果你正在为你的产品构建一个可扩展的后端系统,你很可能会实现微服务架构。在这种情况下,你希望客户端能够轻松连接到不同的微服务,不论是浏览器、移动设备,还是物联网(IoT)组件。
在这篇文章中,假定你对 Kubernetes 有所了解。
在上面这张图片中,你可以看到在Kubernetes集群内的微服务。虚线表示客户端连接到这些微服务,正是这些虚线表示的连接,我们对于这些虚线表示的连接需要一个解决方案。
除了 Kubernetes,我还假定你熟悉如何创建和使用 Services 来为运行你微服务的 Pods 提供一个一致且持久的访问入口。如果你还不熟悉 Services,可以在我其他文章中了解更多关于实现 Services 的内容。在我其他文章中了解更多关于实现 Services 的内容。
好的,由于我们的服务提供了微服务的统一接入点,我们可以访问它们而不必担心实例(或副本)的数量,甚至不用管它们部署在哪。事实上,如果你读过我的文章,你会发现这就是我尝试新东西时的做法。我把服务设置成 NodePort 类型,然后从集群外部访问它。
虽然你确实可以在实际环境中这样做,不过我们不建议这样做,原因在你看到API网关的强大功能后就会明白了。
假设我们有一些微服务,每个微服务都有自己的一组副本,并且每个微服务都设置了服务。我们现在可以退一步看看,我们的客户端是如何连接到这些微服务的。
我们需要一种方法,使得客户有一个单一、持续且稳定的联系点。也就是说,我们需要一个服务于我们服务的平台!
我们把它叫做 API 网关,这是一种...
让我们来了解一下API网关
你可能已经注意到我把这张图片转过来了。这样我就可以来谈谈南北和东西方向的车流概念。
这些术语在讨论 Kubernetes 数据流时经常被提到。
在这篇文章里,我并不打算深入探讨复杂的Kubernetes网络世界。不过,在谈到API网关时,理解这些术语是有用的。
从图片中可以看到,客户端通过我们的API网关来连接服务。它提供了一个入口,并为我们的南向数据流提供了一个一致且稳定的连接点。
我们的客户不再需要了解我们如何构建微服务及其服务,它们的数量和位置。客户只需连接到我们的API网关并通过例如RESTful API请求我们的服务。其实,我也假设你知道什么是RESTful API了!
API网关根据域名、路径或其他多种因素负责将请求路由到适当的服务。在某些情况下,服务可能不是REST API,而是其他应用程序级的协议。API网关也应该为这些协议进行相应的路由。
从技术角度看,东西向的流量路由并不通过 API 网关进行,但有些供应商的方案中包含这个功能。还有其他解决方案,例如的 Istio 服务网格能处理东西向流量。
API网关的其他特性
(注:此处用空行代替#号,以符合中文翻译的习惯)
好的,所以我们刚刚看到了API网关如何将来自下方的流量路由到我们集群中的所需服务及微服务,但这只是API网关众多功能中的一个。其他功能包括:
尽管我们已经讨论了路由REST请求,你也应该知道除了HTTP流量之外,还可能存在其他类型的请求,例如流媒体、WebSocket、多播等等。API网关也可以都应付这些请求。
为了保证高可用性,API Gateway 可以在不同服务之间进行负载均衡。这意味着如果某个服务失败或被终止,你的客户端甚至不会察觉到,其请求会被其他服务接管。
存在多种负载均衡技术,例如随机分配、粘滞、哈希散列、轮转等,API网关应提供这些选项。
我们还没有提到过需要一个外部负载均衡器,不过我们会稍后再讨论这个需求。
API网关可以充当你的TLS端点。你可以给它提供客户端信任的TLS证书,这样客户端就可以安全且自信地连接到你的API网关。
在 TLS 终点处,流量会变得未加密,从而变得容易受到网络监听。为了防止这种情况发生,建议您配置 API 网关,使其通过安全连接与您的服务和微服务进行交互。
在某些架构里,API网关不终止TLS连接,而是将连接一路路由至微服务。
当一个客户端连接到您的微服务时,您想知道他们是谁。这就是认证的步骤。认证应该在网络的入口点始终进行,以确保没有人能在被识别之前进入。
记住,认证是确认你的身份,授权则是让你能够做什么,通常由网络的其他部分或服务自身来处理。
虽然 API 网关自身不执行身份验证,但它可以确保身份验证过程。您可以保护特定的请求路径,如果用户未经过身份验证,可以要求其登录,或者直接拒绝其请求,并返回 401 HTTP 状态。
在某些情况下,可以通过在API网关中使用API密钥来进行认证和授权。
当请求向南传输到您的服务时,API 网关很快就能发现某个服务不再可用。因此,它需要将请求转发。
因此,API网关成了监控您服务的好信息源。
我们刚才提到,API网关对于监控服务很有帮助。在处理请求的过程中,它还可以提供这些请求的监控信息,包括请求的数量和类型、可能的网络攻击事件以及服务性能情况。
如果你曾经接触过微服务或微服务链,尤其是通过异步队列连接的微服务链条,你就会明白跟踪请求在整个过程中是非常困难的。
API网关通过在其向下传递请求时注入头部来解决这一特定问题。这些标识符可以包含在每个请求的头部中,以便监控。你可以使用工具来追踪和报告你微服务中的请求。
进行A/B测试时,你会运行服务的两个版本。这通常是一个前端界面,或者也可能是后端服务。通过运行两个版本并将用户导向其中一个,你可以比较这两个版本的性能。
A或B版本的选择可能是盲选(用户不知道自己在使用哪个版本)、固定选择(随机选择一个版本并固定给用户)或用户自行选择(用户决定他们想要使用哪个版本),每个选项之间用逗号分隔。
API网关可以通过根据请求中的信息(如cookie、头和路径)将请求定向到相应的A或B版本来帮助进行此类测试。
与 A/B 测试密切相关的是 API 版本管理。您的 API 网关可以帮助管理 API 版本,将请求定向到支持该 API 版本的服务。
这种请求路由方法使得支持API演进变得更加简单。
您可以选择限制特定客户访问您服务的频率。这可能是实现变现的一种方式(提供更高的访问频率限制给付费用户),也可能是防止拒绝服务(DoS)攻击的一种安全手段,限制请求次数。
因为所有请求都通过单一入口点进来,因此你的API网关最适合来实施这些限制。
在高负载情况下,或者当服务出现问题时,你可能希望 API 网关停止将请求传递给微服务,以避免故障连锁反应。这种机制被称为断路器,并且最好是在 API 网关中实现。在这种情况下,断路器的作用是防止一个故障引发另一个故障。
你的微服务里的 REST API 路径可能和客户端使用的路径不一样。这样的话,你可能需要对请求进行转换(也就是我们所说的路径重写),这样你就可以让客户端顺利连接到你的微服务了。
这个请求转换通常是由API网关来做的。这些转换不仅限于路径,还可以包括其他内容,例如:
· 通过增强请求来添加额外信息(例如:在句末添加追踪或认证信息)
· 将一个请求拆分为两个微服务处理(解封装)
· 将来自多个微服务的信息整合起来以形成一个响应(组装)
· 通过设置代理规则来隐藏API网关,使微服务认为它们直接与客户端通信
希望到现在为止,你已经被说服需要在你的集群里有一个API网关。我也认为理解API网关的高层次架构设计是很重要的。
API网关服务架构
通常来说,Kubernetes集群中的API网关架构包括三个部分,
此组件负责在您的节点之间进行负载均衡。它允许您运行多个网关代理服务,并且负载均衡器会确保如果任何实例失败,请求将被重新定向到其他实例,从而确保服务的连续性。
在云计算的世界里,云提供商(例如:AWS、Azure、Google Cloud)通常会提供负载均衡器即服务。Kubernetes 集群环境可以自动请求一个负载均衡器,因此得名外部负载均衡器。
在非云端环境中,需要手动配置负载均衡器
负载均衡器可以提供保护,以抵御诸如分布式拒绝服务(DDoS)攻击之类的网络攻击。
需要注意的是,负载均衡器是多宿主的,它在公共域(即互联网)有一个接口,并且在虚拟私有云(VPC)中也有一个接口。通常,这是从互联网进入VPC的唯一入口。因为它位于互联网上,它会有一个公共IP地址,并且很可能在公共DNS网络中有一个与其相关的域名,以便客户端可以通过该域名访问它。
请求由负载均衡器发送至网关。这个组件负责根据提供的规则将请求以及任何转换路由到适当的服务。
通常,网关代理通常是无状态的,但如果需要任何持久的会话信息,则需要一个跨代理实例的分布式会话管理数据库,因为请求可能会被任一实例接收到。会话持久性可通过使用类似 Redis 的技术来实现。
需要留意的是,虽然我将 Gateway Proxy 称为代理,但它其实可能是路由器或其他技术方案。
网关代理程序需要设置路由和转换规则。
在整個 Kubernetes 集群中,這些規則由集群狀態和集群內創建的資源決定。入口控制器的職責是將集群狀態和資源解析成網關代理能夠理解的規則。
创建规则之后,Ingress Controller 将这些规则传递给 Gateway Proxy 进行实施。这通常是一个实时更新过程,无需停机。
一起,这三个组件(Ingress Controller、Gateway Proxy 和 External Load Balancer)实现了 API网关的功能。
虽然我已在总体和Kubernetes集群的具体上下文中描述了API网关,但了解Kubernetes是如何管理和维护API网关资源的这一点很重要。
在这里有一个困惑点。Kubernetes CRD 或清单文件的结构被称为 API 结构,因为它指的是 Kubernetes 控制平面中的 API 结构,所以称为 API 结构。为什么这点很重要?因为现在为 API 网关定义了一个新的 CRD,称为网关 CRD。经过深思熟虑,决定将 Gateway CRD 称为 Gateway API,而不是简单的 API 网关。不要把 Gateway API 与通过 Gateway API 实现的 API 网关混淆。希望这能澄清这点!
在 Kubernetes 中,API 网关由两个资源组成,分别是 GatewayClass
和 Gateway
(这两个术语在 Kubernetes 中具有特定的含义)。我将尝试描述它们之间的区别。
GatewayClass
的目的是定义一个可以在集群中实例化和配置的 Gateway
类型,实际上就是告诉你有哪些可用的网关技术。
一旦创建,这个集群级别的资源可以从任何命名空间中引用。您可以在这里找到相关文档资料。
GatewayClass
定义了以下内容:
Gateway
需要的参数类型每个 API Gateway 技术供应商将具有这些字段的特定值。如果您决定使用 Hashicorp 的网关,他们会在这里定义这些值 这里。如果您想使用 Kong,请阅读我在这里的文章 这里。下面我会以 Kong 为例。资源定义在 YAML 文件中。
apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: kong-class annotations: konghq.com/gatewayclass-unmanaged: 'true' spec: controllerName: konghq.com/kic-gateway-controller
关于这个文件,需要注意以下几点:
konghq
开头contollerName
字段中要创建 GatewayClass
资源,可以这样做:
kubectl apply -f kong-gw-class.yml # 使用 kubectl 命令应用名为 "kong-gw-class.yml" 的 YAML 文件
在创建了 GatewayClass
之后,可以创建一个使用该类的 Gateway
。请注意,您可以创建许多引用相同 GatewayClass
的 Gateway
实例。您还可以基于不同技术创建多个 GatewayClass
资源。
Gateway
资源表示实际部署的 API 网关。
就像 Gateway
一样,特定技术的供应商通常会告知,他们的技术期望关联的 Gateway
资源满足什么条件。
当你手动安装了 Kong 网关(比如上面的例子),你可以这样定义一个 Gateway
:
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: kong-gateway namespace: kong spec: gatewayClassName: kong-class listeners: - name: world-selector hostname: worlds.com port: 80 protocol: HTTP allowedRoutes: namespaces: from: All
需要注意的是,文件中请注意以下几点:
name
(kong-gateway
),这将使它能够在后续的路由资源(如HTTPRoute
)中被引用。GatewayClassName
来匹配定义Gateway
类型的GatewayClass
。Gateway
定义一个或多个侦听器,这些侦听器是进入集群的入口,就像任何监听连接的应用程序一样。name
,应是一个符合URL格式的字符串。hostname
被用作匹配字段,是可选的。allowedRoutes
)来自定义其命名空间,默认情况下这与Gateway
的命名空间相同,但还有其他配置选项(如示例中所示的All
)。该Gateway
规范要求网关在端口80上监听HTTP请求。它还告诉Kubernetes,它的类或类型定义为之前我们定义的网关类名为kong-class
。
注意,port
已设置为 80,这是集群内部使用的端口(即内部集群端口),并不是 任何端口转发的端口或外部端口(例如,如果使用 NodePort 时)。
注意,Gateway
资源特定于命名空间,在创建该资源之前需要先创建对应的命名空间。如果 Gateway
在某个命名空间里,这不会阻止它访问其他命名空间里的服务,如之前关于 AllowedRoutes
的说明。
一旦你的 API Gateway 开始运行,你就需要对其进行设置。每个供应商都会有自己的客户资源定义来配置特定于其技术的功能。但通过定义一个 Kubernetes Gateway API,有一些配置是标准的。这些标准配置的描述可以在这里查看:here。
需要注意的是,某些路由配置(例如:TCPRoute
、TLSRoute
和 UDPRoute
)并没有正式的规则定义,实际上它们充当了它们的后端服务的直接代理。可以将其视为从客户端到服务的端口转发。
这是最常见的转发形式,它在 TLS 终止后,根据请求的主机名、路径、头信息和查询参数的任意组合进行匹配,并将 HTTP 和 HTTPS 请求转发到你的后端服务。
这是一个 HTTPRoute 示例(HTTP 路由):
apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute # HTTPRoute: HTTP 路由 metadata: name: example-1 namespace: default annotations: konghq.com/strip-path: 'true' spec: parentRefs: - name: kong-gateway namespace: kong hostnames: - worlds.com rules: - matches: - path: type: PathPrefix # 类型: 路径前缀 value: /world1 backendRefs: - name: hello-world-1-svc port: 80 kind: Service # 类型: 服务
在此文件中,我们添加了一个特定于 Kong 的注解 konghq.com/strip-path: "true"
,它会从请求中去掉传送到上游服务的匹配路径。其他行的内容如下:
ParentRefs
中),引用以名称和命名空间backendRefs
定义了要将匹配的请求路由到的服务和端口(注意使用 Kubernetes 自动添加到集群 DNS 的名称和未映射的服务 clusterIP
端口)在这个路由中,匹配的是路径的 /world1
前缀,去掉前缀后传递给这个服务。
很可能你会用这种类型的 HTTPRoute
配置所有路由。
在这篇文章里,我解释了什么是API网关,并说明了其必要性以及它们能带来的好处。
我们已经研究了它们在Kubernetes集群中的构建方式,以及它们是如何被拆分为三个不同的部分的。
最后我们看到了Kubernetes是如何扩展以支持GatewayClass
和Gateway
资源的概念,从而支持安装Kubernetes兼容的API网关的。通过几个例子,我们看到这些资源是如何创建和使用的。
虽然这篇文章主要是理论性的,你可以在我写的文章里找到在Kubernetes集群中使用API网关的实际示例。
希望你喜欢这篇文章,学到一点点新的东西,哪怕是很小的一点,也能提升你的技能。
如果你喜欢这篇文章,请给我点个赞或留言,这能帮助我了解大家喜欢的内容,以及我接下来应该写些什么。如果你有任何建议,请在评论或回复里添加。