关于在 Kubernetes 中扩展 OCI 队列使用者

此手册介绍了如何使用 Oracle Cloud Infrastructure (OCI) 队列的功能,并提供了配方,可根据客户端需求量来满足大多数需要动态扩展的用例,而不会产生后退压力或性能瓶颈问题。

您可以将微服务部署到 Oracle Kubernetes 引擎 (OKE),该引擎处理来自 OCI 队列的消息,然后利用队列深度横向扩展在 OKE 集群上运行的微服务实例。此示例包括可以从任何位置运行的消息生成器;例如,从本地计算机或作为其他容器或 VM 的一部分运行。

本手册还提供了代码和详细的设置说明,可在 Oracle-DevRel GitHub 资料档案库 oci-arch-queue-oke-demo(可以从本手册的“浏览更多”部分中访问)。此解决方案提供所有 Java 代码、脚本和配置文件,以及构建、部署和运行构建块的详细步骤。本文档将提供架构视图,并检查实施的关键要素,包括确定需要修改的代码的各个部分,以便根据自己的需求调整解决方案。

了解 OCI 队列 API

解决方案很少处理单个进程;应用程序之间的通信通常必须是异步的,以避免通过解决方案的最有限部分(例如需要 CPU、延迟等)限制解决方案。您可以通过建立通信来克服这些问题,在这些通信中,生产者和消费者并不相互依赖。这是 OCI 队列以极高的性能支持的内容。

虽然队列可以缓解需求波动中的应用,但当涉及用户时,您不希望在消息创建和消息处理之间花费大量时间。因此,后端需要能够根据需要动态扩展。该需求由队列中的消息数确定;更多的消息意味着需求更多,因此需要更多的计算工作。相反,空队列表示无需求,因此只需要最少的后端资源。动态缩放可解决这些常量变化。

体系结构

此体系结构要求队列包含位于可见容错域外部的消息,因为它是完全托管的服务。

在 OCI 中,您可以使用客户端管理的节点或 Oracle 管理的节点运行 Kubernetes。此方案使用客户端节点的旧方法,因此您需要连接到集群的计算节点。这些节点最好分布在可用性区域内的容错域中。

注:

在本手册中,需求生成来自本地计算机,因此来自 OCI 环境外部。

最后两个关键要素控制缩放。首先,定期调用 OCI 函数并检索队列深度的详细信息。要抽象确定队列深度的方式,将使用 API 网关,这有助于调用 OCI 函数。

最后,我们需要辅助服务(如 Vault)来存储用于访问队列的身份证明、监视一般健康状况观察等。


后面是队列缩放 -oke-arch.png 的说明
插图队列缩放 -oke-arch.png 的说明

队列缩放 -oke-arch-oracle.zip

上图中的数字表示以下事件顺序:
  1. 本地托管的生产者将消息放入 OCI 队列。
  2. OCI 使用者实例从队列中检索消息。在代码内,使用延迟会限制使用费率。这可确保提供者生成的消息数大于单个使用者可以从队列中删除的消息数。因此,扩展机制将发挥作用。
  3. 定期,Kubernetes 计划作业将支持 KEDA 调用发布的 API 以获取队列中的消息数。
  4. API 网关会将请求定向到 OCI 函数的实例。
  5. OCI 函数会查询 OCI 队列。
  6. 将返回响应,这将导致 KEDA 触发微服务的实例增加或减少。
此外,(a) 此实现还允许用户随时查询队列深度的状态。
此体系结构包含以下组件:
  • 区域

    OCI 区域是一个局部地理区域,包含一个或多个数据中心(称为可用性域)。区域独立于其他区域,广阔的距离可以将其分开(跨国家甚至大陆)。

  • 可用性域

    可用性域是区域中的独立独立数据中心。每个可用性域中的物理资源与提供容错能力的其他可用性域中的资源隔离。可用性域不共享基础设施服务,例如电源、冷却或内部可用性域网络。因此,一个可用性域出现故障不会影响区域中的其他可用性域。

  • 容错域

    容错域是可用性域内的一组硬件和基础设施。每个可用性域都具有三个具有独立电源和硬件的容错域。在多个容错域中分配资源时,您的应用可以承受容错域中的物理服务器故障、系统维护和电源故障。

  • 区间

    区间是 OCI 租户中的跨区域逻辑分区。使用区间在 Oracle Cloud 中组织资源、控制对资源的访问以及设置使用限额。要控制对每个区间中资源的访问,您可以定义策略来指定哪些人可以访问资源以及他们可以执行的操作。

  • 虚拟云网络 (VCN) 和子网

    VCN 是您在 OCI 区域中设置的可定制软件定义网络。与传统数据中心网络一样,VCN 允许您完全控制您的网络环境。一个 VCN 可以具有多个不重叠的 CIDR 块,您可以在创建 VCN 后对其进行更改。您可以将 VCN 细分为多个子网,这些子网可以限定到区域或可用性域。每个子网包含一系列不与 VCN 中的其他子网重叠的连续地址。创建后可以更改子网的大小。子网可以是公共子网,也可以是专用子网。

  • 计算实例

    通过 OCI 计算,您可以预配和管理计算主机。您可以为计算实例启动符合您的资源需求的配置(CPU、内存、网络带宽和存储)。创建计算实例后,您可以安全地访问它、重新启动它、连接和分离卷,并在不需要时终止它。

  • 函数

    Oracle Functions 是一个完全托管的多租户、高度可扩展的按需函数即服务 (FaaS) 平台。它由 Fn 项目开源引擎提供支持。使用函数可以部署代码,直接调用代码或触发代码以响应事件。Oracle Functions 使用在 OCI 注册表中托管的 Docker 容器。

  • 容器注册表

    OCI 注册表是一种由 Oracle 管理的注册表,可用于简化开发到生产工作流。通过注册表,您可以轻松存储、共享和管理开发构件,例如 Docker 映像。OCI 的高可用性和可扩展架构可确保您可以可靠地部署和管理应用。

  • 适用于 Kubernetes 的容器引擎

    OCI Container Engine for Kubernetes 是一项完全托管、可扩展的高可用性服务,可用于将容器化应用部署到云中。您可以指定应用所需的计算资源,而容器引擎 for Kubernetes 在现有租户中的 OCI 上预配这些资源。适用于 Kubernetes 的容器引擎使用 Kubernetes 在主机集群中自动部署、扩展和管理容器化应用。

  • API 网关

    使用 Oracle API Gateway,您可以发布具有端点的 API,以管理函数、微服务和其他应用接口等功能的可见性。这些端点为后端解决方案提供了细粒度的安全控制,并抽象了 API 的实施方式。

  • 队列

    队列是一种无服务器高度可扩展的异步通信机制。它非常适合分离服务和消息传送。

考虑事项

将微服务部署到 Kubernetes 以处理来自 OCI 队列的消息时,应考虑以下事项:

  • 队列策略的注意事项

    控制和配置 OCI 队列以及用于创建和使用消息的策略是分开的。这样,您可以对通过 API 提供的操作实施细粒度控制。这意味着您需要考虑应用程序的要求和安全需求。对于生产环境,建议使用严格控制;本实施使用放宽的配置设置,这样可以最大限度地减少配置错误的可能性,从而阻止演示工作。

  • Kubernetes 扩展限制注意事项

    您需要考虑后端扩展的速率和限制。您需要解决一些因素,例如在启动微服务的其他实例之前队列可以获得多大深度。微服务的最大附加实例数应该正在运行。虽然在现实生活中,如果有人(故意或意外)开始将队列淹没时出错的消息,您不希望吸收耗尽额外的计算能力的成本,而这在实际环境中是很有诱惑力的。您还需要考虑如何快速地细分微服务的其他实例。速度太快,你会发现你的环境不断启动和停止服务。无论微服务的效率如何,启动和停止服务实例总是会产生开销,这最终会产生成本。

  • 缩放控制的注意事项

    控制缩放的最后一个方面是是否要应用缩放以及如何控制缩放。此方案利用名为 KEDA 的 CNCF 项目 (Kubernetes Event Driven Autoscaler)。除了后端缩放的执行方式,您还需要考虑如何调用 API。在这种情况下,您可以配置 Kubernetes 计划作业(因为作业由图表反映此流的 worker 节点执行)来调用 API。

先决条件

开始之前,您需要通过满足此处所述的先决条件来准备环境。

  • 要生成消息,您需要安装 Java 8 或更高版本(Java 8 与 Apache Maven 一起安装)。
  • 与 OCI 队列的交互需要用户和关联的身份证明才能允许访问。设置以下策略:
    • 设置此策略以标识要使用的区间 (compartment-name):
      allow any-user to manage queues in compartment compartment-name 
    • 要限制用户仅读取或写入 OCI 队列,请创建名为 MessageConsumersMessageProducers 的 OCI 组,并将相应的用户分配给这些组。使用以下策略:
      allow group MessageConsumers to use queues in compartment compartment-name 
      allow group MessageProducers to use queues in compartment compartment-name
    • 为生成器客户端提供标准 OCI 配置属性,以便他们可以通过 OCI 进行验证并使用 API。
    • 您需要设置策略来支持动态行为,因为新资源会来回并需要访问队列。通过创建具有所需资源的动态组来设置这些策略。由于此控制发生在 OCI 中,因此请使用实例主体。将此组命名为 queue_dg。使用以下策略语句:
      ALL {instance.compartment.id='instance Compartment id (OCID)'} 
      allow dynamic-group queue_dg to use queues in compartment queue_parent_compartment 
      其中,instance Compartment id (OCID) 是包含 worker 节点的区间。

了解 Java SDK

这三段代码(生成器、使用者和功能)都使用 OCI API。与 API 交互的最简单方法是通过 Java SDK。OCI 提供的 SDK 提供了一系列信服功能,这些功能可检索验证和授权调用 OCI 服务所需的信息。SDK 采用了 Joshua Bloch 的构建器模式。您可以在 Java SDK 上找到有关 SDK 的更多信息。Oracle DevRel GitHub 系统信息库提供了此处使用的 SDK 的更多示例,例如 https://github.com/oracle-devrel/oci-arch-queue-demo