提供一个更动态的动作管理解决方案

包含您的 Launchpad 蓝图的 URL

https://blueprints.launchpad.net/watcher/+spec/watcher-add-actions-via-conf

Watcher 旨在提供一个开放的解决方案,用于审计任何资源池并优化它,通过推荐的 动作

此蓝图旨在提供一个通用且动态的系统,用于添加新的优化动作,这些动作可以在一个或多个策略中使用,以达到 审计的目标。

问题描述

目前,给定版本的 Watcher 中可能的 动作集合是固定的,并使优化算法能够包含诸如实例迁移、更改 hypervisor 状态、更改电源状态(ACPI 级别等)之类的动作。

应该能够在 watcher.conf 中部署和配置新的潜在动作,并将每个动作与 Python 类关联,而无需重新部署新版本的 Watcher。

请注意,即使到目前为止 Watcher 决策引擎Watcher Applier打包在同一个 Python 包中,这些服务可能部署在单独的机器上。除此之外,可能还会有一个蓝图,旨在将 Watcher Planner作为一个单独的组件(目前它包含在 Watcher 决策引擎中)。

这就是为什么,应该在以下方面进行严格的关注点分离

  • 动作类型定义(输入参数等)

  • 给定动作类型的动作实例化

  • 动作调度(通过动作类型调度策略等)

  • 动作模拟和执行(通过某些动作处理程序类)

这些关注点中的每一个都与特定的 有界上下文相关,此蓝图的目标是更好地独立地解决每个有界上下文,以便我们可以在不影响其他上下文的情况下更新给定上下文的模型和源代码(微服务架构)。

下面是一个图表,显示了 Watcher 中动作管理的功能需求

../../../_images/Watcher_Actions_Management_Functional_Need.png

您可以看到,Watcher 需要三个主要阶段

  • 第一个阶段名为“定义和实例化用于优化的动作”发生在 Watcher 决策引擎的策略中:每个 策略需要能够使用和实例化一组预定义的优化动作类型,以实现 审计的目标。此时,这些动作不会在时间范围内进行调度。

    在此阶段,开发人员需要在他们的策略中执行四件事

    • 使用专用的领域特定语言 (DSL) 描述和注册新的动作类型。每种动作类型都应具有自己的输入参数、名称、描述、版本和目标 受管理资源类型

    • 创建这些动作类型的一个或多个实例(即,Watcher 需要某种动作工厂);

    • 将这些动作添加到推荐的 解决方案中,作为一个简单的无序动作列表;

    • 将此推荐动作列表持久化到 Watcher 数据库中。

  • 第二个阶段名为“按时间调度动作”发生在 Watcher Planner 中:在策略中实例化的动作需要被调度,以便它们不会干扰 SLA,并且因为在执行动作时存在一些逻辑顺序。例如,您将在从其撤离所有实例之前禁用 hypervisor(以确保 hypervisor 不会从 Nova 接收新的初始放置请求)。因此,Watcher Planner 必须能够考虑一些调度策略/规则,例如

    • 为了避免网络拥塞,不要同时迁移太多虚拟机;

    • 在关闭计算节点之前,确保节点上没有更多的虚拟机(为了节能);

    • 优先使用实时迁移而不是非活动迁移;

    因此,在此阶段的 Watcher 处理过程中,应该有一种高效且可扩展的方式来定义这些调度策略/规则,并且应该有一些实现可以考虑它们来生成描述每个动作之间依赖关系链的流程设计(在动作 A 触发动作 B 之后,……)。

    理想情况下,开发人员应该能够集成一个新的“规则求解器”,它可以根据 Watcher 配置文件中的设置动态加载到 Watcher Planner 中。

    请注意,此计划的推荐动作流程称为 Watcher 词汇中的 动作计划

    还应该能够定义错误恢复规则,这些规则定义了发生工作流中的错误时应该执行什么操作(应该尝试多少次,多久一次,……)。应该能够为特定的动作或更广泛的范围(整个流程或嵌入式流程)定义错误恢复策略。

    调度策略/规则和动作流程设计都可以依赖于专用的领域特定语言 (DSL) 和特定的“求解器”,该求解器能够考虑这些规则。

    再次,开发人员需要一种简单的方法将调度策略/规则和动作流程设计持久化到 Watcher 数据库中。

  • 第三个阶段名为“模拟和执行动作”发生在 Watcher Applier 中:它包括执行在第二阶段构建的动作流程。这意味着应该有一些工作流引擎系统,能够读取流程描述(用 DSL 描述并存储在 Watcher 数据库中),模拟流程的执行,如果模拟成功,则真正执行其中包含的所有动作,并尊重调度(即动作之间的依赖关系链)。

    此工作流引擎应该能够加载每个动作类型的实现(名为“ActionHandler”),并执行以下操作

    • 首先启动一些模拟方法,以确保在执行实际命令之前满足所有先决条件,并避免对实际 OpenStack 服务进行无用的回滚。模拟阶段还可以确保所有 ActionHandler 实现都存在,并且所有 目标资源都存在。

    • 如果满足先决条件,则触发技术组件上的某些具体命令(大多数情况下,这将是 OpenStack 组件,例如 Nova、Neutron,…)。

    • 处理错误恢复规则

    为了将第一阶段和第二阶段中使用的动作类型与 ActionHandler 类映射,必须能够为开发人员实现一个映射系统,该系统可以动态加载和配置。

    工作流引擎应该能够创建一个工作流执行的当前上下文,从而能够从先前执行的动作中获取一些输出结果,并将其作为下一个即将到来的动作的输入参数注入。此上下文必须持久化到某个数据库中,并且工作流引擎应该能够从停止的位置恢复中断的工作流(例如,如果 Watcher Applier 服务停止),而不是从零开始重新启动它。

    理想情况下,具有管理员角色的操作员应该能够浏览工作流引擎的活动历史记录(尤其是有关已执行动作的事件和警报)。

    工作流引擎应该能够在动作的当前状态发生变化时发送一些通知(在 Watcher AMQP 消息总线上)。

用例

作为开发人员,我希望能够在优化 策略(加载到 Watcher 决策引擎中)中创建和使用新的优化 动作。以便我可以轻松开发新的策略(用于给定的优化 目标),这些策略依赖于这些动作来更改受管理资源的状态,而无需升级 Watcher。

作为开发人员,我希望能够在 Watcher Planner中创建包含原子动作和嵌入式工作流(由多个动作组成)的工作流。工作流可以按顺序或并行调度这些动作。以便我可以根据一些调度策略/规则调度优化动作。

作为开发人员,我希望能够开发调度策略/规则并动态添加这些规则,而无需升级 Watcher。以便我可以控制在给定时间范围内如何调度动作。

作为开发人员,我希望能够将新的动作处理程序作为 Python 类提供,这些类可以加载到 Watcher Applier中。以便 Watcher Applier 能够启动到负责管理资源的服务的具体命令(大多数情况下,这将是 OpenStack 服务,例如 Nova、Cinder、Neutron,……但它也可以是任何资源管理服务)。

作为具有管理员角色的操作员,我希望能够轻松安装和配置新的优化动作,而无需部署新版本的 Watcher 软件。以便它们可以用于我需要安装的新优化策略

项目优先级

不相关,因为 Watcher 目前不在大型帐篷内。

提议的变更

预计的更改将在以下位置进行

问题描述中所述,Watcher 应该集成一个新的任务/流程管理系统,该系统提供三个主要阶段之间的清晰分离

  • 定义新的优化 动作类型并在策略中实例化它们

  • 按时间调度动作

  • 模拟和执行动作

备选方案

每次我们需要添加新的动作类型时,我们都可以部署新版本的 Watcher,但这会影响 Watcher 的可用性,并导致系统更不易演进。

数据模型影响

以下数据对象可能会受到影响

  • 操作:

    • 我们可能需要更改存储 动作的输入参数(可能作为键值对的数组)和 目标资源的唯一 ID 的方式。

    • 我们可能还需要存储数据库中执行动作后返回的输出值列表。

可能还需要添加一些新的数据对象,例如

  • ActionType,它将包含与某种类型的动作相关的所有信息

    • action_type:动作类型的唯一 ID。

    • action_type_version:动作类型的版本。它将以 SemVer 格式提供。

    • parameters:作为具有以下字段的元组提供的输入参数数组:(parameter_name, parameter_type)parameter_type 可以是任何简单类型,例如字符串、整数、布尔值、浮点数……

    • target_resource_type:此动作类型可以更改的唯一 资源类型。它可以是任何 HEAT 资源类型

    • display_name:动作类型的简短易于理解的名称。

    • display_description:动作类型的长易于理解的描述。

REST API 影响

将影响所有以 /v1/actions/ 开头并使用类型 Action 的 REST 资源 URL

  • GET /v1/actions/(action_uuid)

  • POST /v1/actions

  • PATCH /v1/actions

  • GET /v1/actions/detail

类型 Action 将具有前面段落中提到的新属性。

请参阅 Watcher API 中的动作处理

如果 Watcher 存储新的数据对象,例如 ActionType,则需要提供新的 REST 资源 URL 来使用 CRUD 操作管理这些对象。

请注意,为了使用 API 创建新的 ActionType,用户可以提供符合其使用的 DSL(即,可能是 JSON 或 YAML 文件)的 ActionType 的描述。

安全影响

如果新的动作需要访问 OpenStack 服务(例如,Neutron),则在 Watcher Applier 运行的 watcher 用户需要被声明为具有该服务上足够的权限,以触发具体的动作。

通知影响

其他最终用户影响

除了 API 之外,以下是用户与此功能交互的其他方式

  • python-watcherclient 的影响

    • 需要找到一种新的方式来显示动作列表和有关动作的详细信息。

    • 还需要能够处理新的数据对象,例如 ActionType

性能影响

其他部署者影响

在交付新的 策略时,操作员将部署以下软件

  • 实现 策略的主要 Python 类;

  • 包含所需 动作类型描述的文件(以适当的 DSL 编写);

  • 包含调度规则描述的文件(以适当的 DSL 编写);

  • Python Planner 类(规则求解器),它能够读取调度规则并生成动作的调度。请注意,这里交付新的类是可选的,因为新的策略可能依赖于先前部署的规则求解器;

  • Python 动作处理程序类,这些类需要在动作流程中模拟/执行在 Watcher Applier 中。

操作员还需要更改 Watcher 配置,以指示

  • 将使用哪个 Watcher Planner 实现来调度动作

  • 将使用哪个 动作映射器 实现来完成动作类型和动作处理程序之间的映射(即,由 观察者应用器 加载的 Python 类)。

  • 必须使用哪个工作流引擎来模拟和执行动作流程。

  • 观察者应用器中使用的工作流引擎将使用哪个存储后端来持久化动作流程的当前状态。

开发人员影响

实现

负责人

主要负责人

jed56

工作项

观察者团队应首先研究像 TaskFlowMistral 这样的解决方案是否适合需求。这肯定可以避免长时间重写源代码,甚至可以帮助我们预见未来关于管理/调度 动作 在观察者中的需求。

以下是预见的工作项目列表

  • 为描述观察者中的新动作类型找到合适的领域特定语言 (DSL)。

  • 实现能够根据动作类型描述在 策略 中实例化动作的工厂。

  • 观察者规划器 类放入一个专门的 Python 包中(不在 观察者决策引擎 中)。

  • 添加观察者规划器实现的动态加载(通过 stevedore)。

  • 找到一种通用的格式来持久化由 观察者规划器 生成并由 观察者应用器 加载的动作流程的描述。

  • 提供 观察者规划器 的默认实现。此默认实现应非常简单,并基于与每个动作关联的优先级。 稍后,可以提供更复杂的实现,这些实现能够读取调度规则 DSL。 我们可能需要基准测试几个现有的规则求解器实现。

  • 在观察者应用器中添加动作处理程序的动态加载(通过 stevedore)。

  • 集成一个现有的工作流引擎,该引擎能够根据观察者规划器生成的动作流程的设计(即所谓的 动作计划)加载和执行动作处理程序。

  • 在观察者应用器中添加一个模拟阶段,以验证动作流程是否可以无错误地执行。

  • 确保在模拟阶段或在观察者应用器中实际执行动作流程期间,如果动作失败,则正确处理错误。

依赖项

存在与以下蓝图的依赖关系

我们还应该查看其他现有的工作流管理框架

  • Mistral:这个 OpenStack 项目提出了一个即服务的工作流系统

  • PyUtilib:它是一个独立的 workflow 引擎,旨在嵌入和开发以自动化科学 workflow 的处理。

  • Spiff Workflow:用纯 Python 实现的 workflow 引擎

  • hurry.workflow:一个简单的 workflow 系统。它可以用于实现 Zope Toolkit 应用程序的状态化多版本 workflow。

测试

需要以下内容的单元测试

  • 包含所需 动作 类型描述的文件加载(以适合此目的的任何 DSL 编写);

  • 包含调度规则描述的文件加载(以适合此目的的任何 DSL 编写);

  • Python 规划器类(规则求解器),该类能够读取调度规则并生成动作的计划;

  • 观察者应用器 内部动态加载动作处理程序类;

  • Python 类,每个动作处理程序都需要在观察者应用器中模拟/执行动作流程;

  • 动态加载 观察者规划器 实现;

  • 动态加载 动作映射器 实现;

  • 执行提供的默认观察者规划器实现

  • 执行提供的默认 动作映射器 实现;

  • 配置不同的存储后端,用于观察者应用器中使用的工作流引擎,以持久化动作流程的当前状态。

  • 执行模拟阶段以及在此模拟阶段期间的错误管理

还需要在现有的集成测试中验证整个动作管理系统。

文档影响

需要更新文档,尤其是词汇表,以解释有关 动作 定义、调度和执行的新概念。

架构描述也需要更新,因为

  • 观察者规划器 将从 观察者决策引擎 中独立出来

  • 将引入一个新的组件:动作映射器

  • 许多组件实现将作为插件提供(动作类型、观察者规划器、动作映射器动作处理程序

有关观察者安装和配置的文档也需要更新,以便解释

  • 如何使用建议的 DSL 描述新的动作类型;

  • 如何将新的动作类型部署到观察者中;

  • 如何在优化策略中使用新的动作类型(即如何从给定的动作类型实例化一个动作);

  • 如何在 观察者规划器 中添加新的调度策略/规则;

  • 如何使用建议的 DSL 构建动作流程;

  • 如何添加新的观察者规划器实现;

  • 如何添加新的 动作映射器 实现;

  • 如何配置 观察者应用器:引擎实现、持久化后端等

参考资料

IRC 讨论

历史