为什么我需要在Kubernetes集群上使用API网关?

引言

Kubernetes

与我撰写的多数文章有所不同,本文将重点聚焦于理论层面,而非实践操作。倘若你计划安装API网关,可点击阅读我关于Kong安装的文章

当你致力于为产品搭建一个具备高扩展性的后端时,很可能会采用微服务架构。在这样的架构体系下,无论客户端是浏览器、移动设备,还是物联网(IoT)组件,你都期望它们能够与你的微服务顺利建立连接。

在阅读本文之前,我假定你已经对Kubernetes有了一定的了解。

从上图中,你可以看到我们的微服务部署在Kubernetes集群内部。图中的虚线代表客户端与这些微服务之间的连接,而如何处理这些连接,正是我们需要寻找解决方案的关键所在。

除了Kubernetes,我还假定你熟悉如何创建和使用服务(Services),通过服务为运行微服务的Pods提供一个稳定且持久的连接入口。要是你对服务的相关内容不太熟悉,可以点击阅读我其他文章中关于服务实现的部分

既然我们已经知道服务为微服务提供了稳定的连接入口,那么我们在访问这些微服务时,就无需担忧正在运行的实例(或副本)数量,甚至也无需在意它们具体运行在何处。实际上,如果你一直关注我的文章,就会发现我在实践过程中就是这样操作的。我将服务以NodePort服务的形式暴露出来,然后从集群外部对其进行访问。

尽管在生产环境中你也可以采用这种方式,但并不推荐,等你深入了解API网关的功能后,就会明白其中的缘由。

API网关简介

设想我们构建了一个复杂的微服务架构,其中包含多个微服务,每个微服务都有各自独立的副本数量,并且都设置了对应的服务。此刻,让我们暂时跳脱具体的服务构建细节,从宏观视角审视客户端与这些服务之间的连接方式。

我们迫切需要一种机制,能够为客户端提供一个单一、稳定且持久的连接入口。从本质上讲,这就如同为我们现有的众多服务,再打造一个“总服务”,而这个“总服务”,就是我们所说的API网关。

Kubernetes流量流向

或许你已经留意到,我特意将这幅图调转了方向。这么做是为了引出南北向和东西向流量这两个重要概念,在探讨Kubernetes流量流向时,它们频繁出现。

  • 北向(Northbound):指的是借助出口点,流向互联网的流量。
  • 南向(Southbound):是通过入口点,从互联网流入的流量。
  • 东西向(East/West):表示在Pods和服务之间流动的流量。

在本文中,我们不会深入钻研Kubernetes网络那庞大而复杂的体系,但在探讨API网关相关内容时,理解这些术语的含义是非常必要的。

从图中清晰可见,客户端是通过API网关来连接我们的服务。API网关不仅提供了一个统一的入口,更为南向流量搭建起了稳定、持久的连接桥梁。这意味着,客户端无需再关心我们微服务及服务的构建细节,包括它们的数量、具体位置等信息。客户端只需连接到API网关,通过REST接口之类的方式,就能轻松请求所需服务。当然,在此我假定你对REST接口已有一定的了解。

API网关肩负着根据域名、路径或其他多种因素,将客户端请求精准路由到相应服务的重任。值得注意的是,在某些情形下,服务所采用的并非REST API,而是其他应用层协议,即便如此,API网关也应当具备对这些请求进行路由的能力。

从技术层面来讲,东西向流量的路由工作并非由API网关负责执行。不过,部分供应商在其提供的解决方案中,将这一功能纳入其中。除了API网关,还有诸如Istio服务网格这类解决方案,能够对东西向流量进行有效管理。

API网关的其他功能

我们刚刚了解了API网关如何将南向流量精准路由至集群内目标服务和微服务,可这仅仅是其众多功能中的冰山一角。实际上,API网关还具备以下丰富多样的功能:

  • 基于多维度的路由:依据主机、路径、头信息等条件进行智能路由。
  • 负载均衡:合理分配服务请求,保障系统稳定运行。
  • 安全性保障:全方位守护系统安全,抵御各类风险。
  • 强制身份验证:严格确认访问者身份,防止非法访问。
  • 服务监控:实时掌握服务运行状态,及时发现潜在问题。
  • 请求监控和追踪:详细记录请求轨迹,便于故障排查与性能优化。
  • A/B测试:助力产品迭代,通过对比不同方案效果做出科学决策。
  • API版本管理:有序管理API版本,确保系统兼容性与稳定性。
  • 速率限制/断路:有效控制请求速率,避免系统过载,在必要时及时切断异常连接。
  • 请求转换:灵活调整请求格式,适配不同服务需求。

路由

我们之前着重讨论了对REST请求的路由,但需要特别留意的是,实际场景中存在的请求类型丰富多样,远不止HTTP流量这一种。像流媒体传输、WebSockets实时通信、多播数据分发等特殊请求也十分常见。而强大的API网关完全有能力妥善处理上述各类请求,保障数据传输的顺畅与高效。

负载均衡

为实现系统的高可用性,API网关能够在多个服务之间巧妙地进行负载均衡。这意味着,当某个服务不幸出现故障或者意外终止时,客户端几乎不会察觉到任何异样。因为API网关会迅速将客户端的请求无缝切换至其他正常运行的服务进行处理,从而确保业务的连续性与稳定性不受影响。

在负载均衡技术领域,存在着诸如随机分配、粘性会话、哈希算法、轮询调度等多种成熟方案。优秀的API网关应当为用户提供丰富的选择,以便根据实际业务需求灵活配置,实现最佳的负载均衡效果。

目前,我们尚未深入探讨外部负载均衡器的相关需求,不过后续我们会专门针对这一重要议题展开详细的分析与讨论 。

安全性

API网关能够充当您的TLS端点。您可以为其配置客户端信任的TLS证书,如此一来,客户端便能凭借这些证书,放心且安全地连接到API网关。

当API网关作为TLS端点时,流量会被解密,这就可能使数据面临网络窃听的风险。为防范此类情况,建议对API网关进行配置,使其与您的服务和微服务之间也通过安全连接进行通信。

值得注意的是,在某些架构中,API网关并不终结TLS连接,而是将其直接路由至微服务。

身份验证

当客户端尝试连接您的微服务时,确认其身份至关重要,这便是身份验证的意义所在。身份验证应当始终在网络的入口点执行,以确保任何未经识别的访问者都无法进入系统。

需要牢记的是,身份验证解决的是“你是谁”的问题,而授权则是决定“允许你做什么”,授权通常由网络的其他部分或服务自身负责。

尽管API网关本身并不直接执行身份验证操作,但它能够确保身份验证流程的正常运行。您可以对特定的请求路由进行保护,若用户尚未进行身份验证,API网关可以要求用户进行身份验证(比如将用户重定向到登录页面),或者直接拒绝其请求(返回401 HTTP状态码)。

在某些情形下,借助API密钥,API网关可以在内部完成身份验证和授权工作。

服务监控

随着请求不断被传递到各个服务,API网关能够迅速察觉某个服务是否已不可用。它必须掌握这一情况,因为一旦服务不可用,它需要及时重定向请求。

正因如此,API网关成为了监控服务状态的关键信息来源。

请求监控和追踪

我们刚才提到,API网关在监控服务方面表现出色。由于它负责处理请求,所以也能够对这些请求进行监控,提供诸如请求数量、请求类型、潜在网络攻击迹象以及服务性能等关键信息。

倘若您使用过微服务,尤其是通过异步队列连接的微服务链,便会深知端到端追踪请求是一项极具挑战性的任务。

API网关巧妙地解决了这一难题,它在请求向南传递时注入标头。这些标头中可以包含每个请求的唯一标识符,方便记录到日志中用于监控。随后,您可以借助相关工具对微服务中的请求进行报告分析。

A/B测试

在A/B测试中,您会同时运行同一服务的两个不同版本。通常情况下,这更多指的是前端用户界面,但也可能涉及后端服务。通过同时运行这两个版本,并将用户分流到其中一个版本,您就能够对比两种不同解决方案和/或版本的性能表现。

A或B版本的选择方式多样,既可以是盲选(用户并不知晓自己使用的是哪个版本),也可以是粘性选择(随机为用户选定一个版本,并固定该用户后续的使用版本),还可以是自选(由用户自主决定使用哪个版本)。

API网关能够基于请求中的信息,包括cookie、标头和路径等,将请求精准引导至相应的A或B版本,从而为这类测试提供有力支持。

API版本管理

API版本管理与A/B测试紧密相关。API网关可以协助管理API版本,将请求准确无误地引导至支持对应API版本的服务。

这种请求路由机制使得API的升级和演进过程变得更加轻松顺畅。

速率限制和断路

您可能会根据业务需求,决定限制特定客户端访问您服务的速率。这既可以作为一种商业化策略(例如付费账户享有更高的限速),也可以作为一种安全手段,用于限制拒绝服务(DoS)攻击中的请求数量。

鉴于所有请求都通过单一入口点进入系统,API网关无疑是实施这类限制的最佳选择。

在面临极端负载(或服务出现严重问题)时,为避免级联故障(一个故障引发另一个故障,进而导致系统全面崩溃),您可能需要API网关停止向微服务传递请求,这就是所谓的断路器机制,而在API网关中实现这一机制是最为理想的选择。

请求转换

在您的微服务体系中,REST API所采用的路径,很可能与客户端发起请求时使用的路径存在差异。一旦出现这种情况,就必须对请求进行转换(也称作路径重写),只有这样,才能实现客户端与微服务之间的顺畅连接。

这种请求转换工作,通常由API网关来完成。而且,转换的范畴并不局限于路径,还涵盖了诸多其他方面,例如:

  • 增强请求信息:在请求中添加额外信息,像是追踪数据或身份验证信息,以此丰富请求内容,满足后续处理需求。
  • 拆分单个请求:将来自客户端的单个请求,依据特定逻辑在两个微服务之间进行拆分(即解组操作),使不同的微服务能够各司其职,协同完成对请求的处理。
  • 汇集响应信息:从多个微服务收集相关信息,将其整合汇聚,进而形成对客户端请求的完整响应(也就是组装过程),确保客户端能获得全面且准确的反馈。
  • 隐藏网关存在:通过巧妙设置代理规则,让API网关“隐身”,使得微服务误以为自己是在直接与客户端通信,而非与API网关交互,从而在保障系统通信逻辑的同时,提升了架构的安全性和灵活性。

网关架构

至此,相信您已经充分认识到在集群中引入API网关的必要性。同时,深入了解API网关的高级架构,对于构建高效、稳定的系统同样至关重要。

Kubernetes集群网关架构

通常而言,Kubernetes集群中的API网关架构主要由以下三个核心部分构成:

  1. 外部负载均衡器
  2. 网关代理
  3. Ingress控制器

外部负载均衡器

外部负载均衡器肩负着在集群节点之间实现负载均衡的重任。它允许您部署多个网关代理实例,当某个实例不幸出现故障时,负载均衡器能够迅速做出反应,将后续请求智能引导至其他正常运行的实例,从而确保服务的持续性和稳定性,避免因单点故障导致服务中断。

在云计算环境下,诸如AWS、Azure、Google Cloud等云服务提供商,往往会将负载均衡作为一项基础服务提供给用户。Kubernetes集群具备自动请求在集群外部配置一个负载均衡器的能力,这也正是其被称为“外部负载均衡器”的缘由。

与之相对,在非云环境中,负载均衡器的配置则需要手动完成,这对运维人员的技术能力和经验提出了更高要求。

此外,外部负载均衡器还具备抵御网络攻击的能力,尤其是在防范分布式拒绝服务攻击(DDoS)方面发挥着关键作用,能够有效保护集群免受恶意流量的冲击,维护网络的安全稳定运行。

值得注意的是,外部负载均衡器具备多宿主特性,它拥有一个面向公共域(即互联网)的接口,以及一个位于虚拟私有云(VPC)内的接口。通常情况下,这是从互联网进入VPC的唯一入口点。由于其暴露在互联网上,所以会被分配一个公共IP地址,并且可能在公共DNS网络中关联一个域名,这样一来,客户端就能通过该域名轻松找到它,实现与集群内部服务的通信。

网关代理

请求从外部负载均衡器进入网关代理。作为整个架构中的关键一环,网关代理负责依据预先设定的规则,为接收到的请求提供精准的路由服务(同时完成可能需要的转换操作)。

一般来说,网关代理是无状态的,这意味着它在处理每个请求时,不会依赖于之前的请求状态,能够独立、高效地完成任务。然而,倘若涉及到需要持久化的会话信息,就必须借助分布式会话管理数据库,在代理的各个实例之间进行协调和管理。这是因为请求可能随机进入任何一个实例,为了确保用户体验的一致性和数据的完整性,就需要通过这种方式来维持会话的持续性。例如,Redis等技术就常被用于提供会话持久性支持。

需要强调的是,尽管我们习惯将其称为“网关代理”,但实际上它可能采用路由器或其他替代技术来实现,其核心功能在于实现请求的高效转发和处理。

Ingress控制器

网关代理的正常运行离不开合理配置的路由和转换规则。在Kubernetes集群中,这些规则是依据集群状态以及在集群内创建的资源来进行管理的。而Ingress控制器的核心任务,就是将复杂的集群状态和资源信息,转化为网关代理能够理解并执行的规则。

一旦规则创建完成,Ingress控制器会立即将其传递给网关代理,以便后者迅速执行。这种规则传递和更新过程通常是实时进行的,无需停机维护,极大地保障了系统的稳定性和可用性,确保API网关能够持续、高效地为客户端提供服务。

综上所述,Ingress控制器、网关代理和外部负载均衡器相互协作、紧密配合,共同构建起强大的API网关功能体系,为Kubernetes集群的稳定运行和高效服务提供了坚实支撑。

GatewayClass和Gateway

尽管我已经从宏观角度以及Kubernetes集群的背景下,对API网关进行了阐述,但深入了解Kubernetes如何管理API网关资源,同样不可或缺。

在此处,很容易产生混淆。Kubernetes自定义资源定义(CRD)或清单文件的结构被称作API。这是由于它指代的是Kubernetes控制平面中的API结构。为什么这一点至关重要呢?因为针对API网关,定义了一种全新的CRD。经过广泛讨论,最终决定将网关CRD命名为网关API。请务必注意,不要将其与API网关相混淆(API网关是通过网关API来实现的)。希望这样的解释能够消除疑惑!

在Kubernetes中,API网关由两个资源进行定义:GatewayClass和Gateway。接下来,我将尝试阐述它们之间的差异。

GatewayClass

GatewayClass的作用在于定义一种可在集群中实例化和配置的网关类型。它实际上是在告知您,能够运用哪些网关技术。

这是一个集群级别的资源,这就意味着,一旦创建完成,便可从任何命名空间进行引用。相关文档可在此处查阅。

GatewayClass资源定义包含以下内容:

  • 类名引用:作为被引用的类名。
  • 可选描述:对该类的简要说明,方便用户了解其用途。
  • 技术引用:指向该类所支持的技术,明确技术范畴。
  • 可选参数对象:定义网关所需参数类型,为后续配置提供依据。

每个API网关技术供应商都会为这些字段赋予特定的值。举例来说,如果您决定采用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

针对这个文件,有几点需要特别留意:

  • 由于它是集群级别的资源,所以没有命名空间。
  • 注释部分定义了针对该解决方案的特定选项,对于Kong而言,这些注释均以konghq开头。
  • unmanaged注释是一个示例,表明Kong是通过手动设置,而非借助操作器自动设置。
  • Ingress控制器为Kong Ingress Controller(KIC),并在contollerName字段中进行配置。

可通过以下方式创建GatewayClass资源:

kubectl apply -f kong-gw-class.yml

一旦创建好GatewayClass,便可以创建使用该类的Gateway。需注意的是,您能够创建多个引用相同GatewayClass的Gateway实例。同时,也可以基于不同技术,创建多个GatewayClass资源。

网关(Gateway)

Gateway资源代表着实际的API网关安装。

与GatewayClass类似,特定技术的供应商通常会告知您,其技术对关联的Gateway资源有哪些具体要求。

对于像上述示例中手动安装的Kong Gateway,可按如下方式定义一个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

在这个文件中,有诸多要点值得关注:

  • 它拥有一个名称(kong-gateway),便于后续路由资源(如HTTPRoute)对其进行引用。
  • 通过GatewayClassName来匹配定义网关类型的GatewayClass。
  • 每个Gateway会定义一个或多个监听器,这些监听器就如同监听连接的应用程序一般,是进入集群的入口点。
  • 每个监听器都需要一个唯一的名称,且该名称必须是符合URL规范的字符串。
  • 主机名用作匹配字段,但并非必填项。
  • 通过命名空间(allowedRoutes),您能够控制哪些服务可以连接到此监听器。默认情况下,与Gateway处于相同命名空间,不过也存在其他配置选项,例如本示例中展示的All。
  • 在这个示例中,我们可以看到Gateway规范期望网关在单个端口(80)上通过HTTP进行监听。它还向Kubernetes表明,其类或类型是由我们之前定义的kong-class的gatewayClassName所确定的。

需注意,端口设置为80,这是服务的内部集群端口,而非任何端口转发的端口或外部端口(例如:若使用NodePort)。

另外,Gateway资源特定于一个命名空间,我们需要在创建资源之前,先创建该命名空间。即便网关处于某一个命名空间中,也不会阻碍其访问其他命名空间的服务,正如之前关于AllowedRoutes的说明中所提及的。

配置您的网关

一旦您的API网关成功启动并运行,就需要对其进行配置。每个供应商都会拥有他们各自的自定义资源定义,用于配置其技术特定的功能。不过,通过定义Kubernetes Gateway API,部分配置已实现标准化。以下将对这些配置进行详细描述。

需要留意的是,一些路由配置(例如:TCPRoute、TLSRoute和UDPRoute)没有正式的规则定义,实际上是直接作为其后端服务的代理。它们可被视作从客户端到服务的端口转发。

HTTPRoute

HTTPRoute是最为常见的路由形式。它能够依据主机名、路径、头部值以及查询参数的任意组合来匹配请求,进而将HTTP和HTTPS请求(在TLS终止之后)精准路由至后端服务。

以下为一个HTTPRoute的示例:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
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' ,其作用是在将请求发送到上游服务之前,从传入的请求中去除匹配的路径。其他关键内容包括:

  • HTTPRoute的命名空间:明确资源所处的命名空间,便于管理和识别。
  • 关联的Gateway定义:在ParentRefs中,通过名称和命名空间引用,指定使用的Gateway,确保路由与网关的正确关联。
  • 可选的主机名引用:用于匹配Gateway中对应的监听器,实现请求的精准对接。
  • 请求匹配规则:用于判断传入请求是否符合该路由条件。
  • 后端服务引用backendRefs定义了将匹配请求路由到的服务和端口。需要注意,此处使用的是由Kubernetes定义并自动添加到集群DNS的名称,并且端口是服务未映射的clusterIP端口。

在这个路由配置中,匹配的路径前缀为/world1,并且在将请求传递给服务之前,该前缀会被剥离。

在实际应用中,您的绝大多数路由配置很可能都会采用这种类型的HTTPRoute。

总结

在本文中,我深入介绍了API网关的核心概念,详细阐述了其必要性以及所能带来的显著优势。

我们深入剖析了API网关在Kubernetes集群中的架构组成,清晰地了解到它是如何划分为三个不同组件协同工作的。

最后,我们探究了Kubernetes如何通过扩展,以理解GatewayClass和Gateway资源的概念,从而让您能够顺利安装与Kubernetes兼容的API网关。借助几个具体示例,我们直观地看到了这些资源是如何被创建和使用的。

尽管本文侧重于理论知识的讲解,但您可以在我的另一篇文章中找到在Kubernetes集群中实现API网关的实际操作示例。

我衷心希望您能喜欢这篇文章,并且通过学习新内容,哪怕只是微小的知识,也能实现自身技能的拓展与提升。

倘若您觉得这篇文章饶有趣味,请给我点个赞,您的认可对我至关重要,它能帮助我了解大家觉得哪些内容实用,进而明确未来文章的创作方向。要是您有任何宝贵建议,欢迎以备注或反馈的形式告知我 。

文章来源: https://study.disign.me/article/202509/12.kubernetes-cluster-api-gateway.md

发布时间: 2025-02-26

作者: 技术书栈编辑