Convergence

https://blueprints.launchpad.net/heat/+spec/convergence

云环境充满不确定性——服务器可能无法启动,或者在底层虚拟机监控程序崩溃或发生断电时停止工作。Heat 应该具有弹性,并允许对任何规模的堆栈进行并发操作。

问题描述

当前模型给 Heat 用户带来了一些问题。

  • 堆栈在创建/更新过程中失败

  • 物理资源可能(无声无息地)停止工作——要么消失,要么出现某种错误(例如,负载均衡器未转发流量,或者 nova 实例处于 ERROR 状态)。当发生这种情况时,后续依赖于假定为“活动”资源的更新很可能会意外失败。

  • Heat 引擎本身也存在不确定性

    • 当服务器需要更新时,它们会被重启

    • 由于硬件或网络故障,它们可能会失败(参见虚拟机监控程序故障部分)

    • Heat 引擎故障表现为 _FAILED 堆栈,这对用户来说是一个问题,但实际上这只是操作员的临时问题,用户无法解决。

  • 大型堆栈超过了单个 heat-engine 进程有效更新/管理的容量。

  • 大型集群——例如 10K 个虚拟机应该可以直接使用

  • 堆栈更新会锁定状态,直到整个堆栈再次收敛,这会阻止管理员在完成之前进行更改

    • 这使得执行自动伸缩变得困难/不可能,因为自动伸缩决策可能比每个事件的完成时间更频繁

      • 问题:为什么会创建一个控制器,以如此频繁地做出决策,以至于在做出下一个决策之前没有时间观察一个决策的影响?

    • 大型管理团队被迫使用外部协调服务,以确保他们不在计划的时间之外执行昂贵的更新

    • 应对紧急情况存在问题

用户故事

  • 用户只需要在 Heat 无法采取任何正确措施来交付当前模板+环境+参数时才干预堆栈。例如,如果附加到非伸缩组资源的 cinder 卷离线,则需要管理员干预 -> STACK_FAILED

    • 无需干预即可处理的示例

      • nova 实例永远无法达到 ACTIVE 状态

      • neutron 端口无法访问

      • 伸缩组中的服务器消失/在 nova api 中进入 ERROR 状态

    • 可能需要干预的示例

      • 未在伸缩组中的服务器在运行一段时间后进入 ERROR 状态或直接消失

      • 由于服务器出现错误/消失,伸缩组降至指定的最小值以下。

  • Heat 用户期望 Heat 能够使堆栈与模板+参数保持一致,即使在其周围的世界在 STACK_READY 之后发生变化——例如,由于用户删除了服务器。

    • 也就是说,有时用户会希望禁用此功能。

  • 操作员不需要手动等待或准备 heat 引擎进行维护:假设崩溃/关机/故障会发生,并且对用户来说是无缝的。

    • 正在更新的堆栈不应因 heat 引擎重启/重新启动/重新部署而以用户可见的方式中断/打断。

  • 用户应该能够部署扩展到后端存储引擎大小的堆栈——例如,我们应该能够在单个 heat 堆栈中执行一百万个资源(一个相对任意的数字作为目标)。这并不意味着单个模板包含一百万个资源,而是单个堆栈包含一百万个资源,也许通过资源组和/或嵌套堆栈来实现。

  • 用户需要在任何时候告诉 heat 他们的期望模板+参数,而不仅仅是在 heat 认为堆栈“READY”时。

    • 自动伸缩是这里的“用户”的一个特例,它调整组的大小,但除此之外与用户相同。

    • 管理员对有问题的情况做出反应时,可能需要在短时间内进行“重叠”的更改。

  • 部署超过 10K 个实例(因此可能包含 50K 个资源)的用户应该期望 Heat 能够快速且优雅地部署和更新这些堆栈,前提是云具有足够的容量。

  • 现有的堆栈应继续正常工作。“我们不破坏用户空间”。

  • 在堆栈创建期间,创建过程卡在等待永远不会到来的信号,由于带外用户操作。发出更新以删除信号等待。

  • 在堆栈创建期间,由于卷中分配的空间不足,软件初始化失败。发出更新以分配更大的卷。

  • 在堆栈删除期间,删除过程无限期地等待删除无法删除的资源。发出更新以更改删除策略,而不尝试删除物理资源。

提议的变更

本规范主要用于驱动整体设计。大部分工作将在一组子蓝图下完成

  • 从使用进程内轮询来观察资源状态,转变为观察和通知方法。这将是规范 convergence-observer

  • 从调用堆栈实现转变为持续收敛实现,由更改通知触发。这将是规范 convergence-engine

  • 使用来自 taskflow 库的分布式工作者集,以支持运行每个单独的收敛步骤。

在进行上述工作之前,以及支持上述工作,将进行数据库模式更改。主要更改是分离期望状态和观察状态,以及支持修改后的处理技术。为了分离期望状态和观察状态,我们将:(1)克隆名为 resource 的表,创建一个名为 resource_observed 的表(名为 resource_data 的表似乎更像是某些类型资源的实现的一部分,因此不需要克隆),以及(2)引入一个名为 resource_properties_observed 的表。对于 resource_observed 表,将删除名为 status、status_reason、action 和 rsrc_metadata 的列。原始模板将是期望状态的一部分。资源在期望状态中的属性是从模板和有效的环境(包括堆栈参数)计算得出的。在观察状态下,资源的属性存储在 resource_properties_observed 表中;它将具有以下字段。

  1. id VARCHAR(36)

  2. stack_id VARCHAR(36)

  3. resource_name VARCHAR(255)

  4. prop_name VARCHAR

  5. prop_value VARCHAR

在升级模式和引擎后,现有的堆栈将自动开始使用收敛模型。

不会对现有的 API 进行任何必需的更改,包括资源插件 API。

收敛引擎

将创建一组新的内部 RPC 调用,以允许观察者触发每个资源的收敛操作。还需要一组新的公共 API 调用来手动触发堆栈或资源的收敛。

之前曾计划仅使用现有的堆栈更新来启用手动收敛。这将导致一个有些笨拙的用户体验,需要用户付出比必要的更多努力。

观察引擎

将创建一组新的内部 RPC 调用,以触发观察者立即观察现实。还需要一组新的公共 API 调用来手动触发堆栈或资源的观察。

请注意,这将建立在 `stack-check` 蓝图引入的调用之上,允许资源检查。

数据模型

Heat 需要为每个资源创建一个新的“期望状态”和“观察状态”的概念。存储需要序列化对单个资源状态的并发修改,以便在资源级别我们可以期望一致性。

调度

Heat 堆栈包含用户期望在操作期间得到尊重的依赖关系图。目标状态的修改必须以与现在相同的方式进行调度,但将从中央任务调度器移动到分布式任务调度器。

例如,在创建堆栈时,当前引擎将解析整个堆栈。图中任何没有未完成父项的项目将向收敛引擎队列发送直接消息,该队列由所有收敛引擎处理。该消息将指示工作者该资源应该存在,并且工作者将进行必要的状态更改以记录该信息。记录后,将创建一个收敛资源的作业。

收敛作业将创建一个观察作业。一旦现实被观察到与期望状态匹配,就会检查图中的子项,这些子项现在已经满足了所有父项,如果找到任何子项,则启动它们的收敛过程。如果我们发现没有更多的子项,则堆栈标记为 COMPLETE。

这可能会导致拥有较大堆栈的用户与拥有较小堆栈的用户相比,获得不公平的资源份额,因为较大的堆栈将在较小的堆栈之前填满队列,从而导致较长的队列长度。目前,配额和常规资源限制足以防止这种情况。

更新将以相同的方式工作。删除的项目仍然通过搜索新图中所有现有资源来枚举,并适当地将期望状态记录为“不应该存在”对于新图中不存在的任何内容。

回滚将以与当前方式相同的方式启用,保留旧的堆栈定义并在回滚操作中重新应用。如果同时进行更新,回滚始终是到先前达到 COMPLETE 状态的堆栈定义。[1]

堆栈删除以相反的顺序进行。堆栈将被记录为“不应该存在”,这将告知收敛作业调度方向相反。图中没有子节点的节点将被记录为“不应该存在”,然后没有更多处于活动状态的子节点的父节点将被记录为“不应该存在”。

这实际上会将收敛引擎渲染为垃圾收集器,因为物理资源将未在图中引用,处于可以随时删除的状态。考虑到对用户的潜在成本,必须使这些资源对用户可见,垃圾收集必须具有很高的优先级。

请注意,“不应该存在”的状态不会改变模板中表达的删除策略的含义。如果存在阻止实际删除的策略,仍然会导致重命名和基本的去引用。

备选方案

  • 使用更好的错误处理和重试支持改进当前模型。

    • 不能解决锁定/并发问题

    • 不能解决大型堆栈的可扩展性问题

实现

负责人

这项工作将被大量分解,并在许多开发人员之间传播。

里程碑

大部分工作应在“K”周期内完成,子蓝图将在 Juno 期间发布大量的更改。

特别是,分离期望状态和观察状态的数据库模式更改将首先进行。完成此操作后,我们可以在代码结构中进行重大改进,而无需进行太多更改;只需在每次更改发生后立即更新观察状态,即可修复最严重的问题(部分成功的堆栈更新不会准确记录结果状态)。稍后进行主要的重组。

工作项

待定

依赖项

  • 蓝图

    • convergence-observer

    • convergence-engine

  • Taskflow

    • 应在此处添加 taskflow 的任何特定需求。