改进 ActionPlan 的存储

https://blueprints.launchpad.net/watcher/+spec/planner-storage-action-plan

问题描述

行动计划决策引擎服务中的默认 规划器构建。每个 动作都链接到下一个动作,因此默认规划器的结果是动作的链接列表。应用器服务执行行动计划。顺序启动动作会对性能产生负面影响,尤其是在动作很多的情况下。每个动作都必须在下一个动作运行之前完成,因此顺序启动迁移动作将花费大量时间。

用例

作为管理员,我希望能够运行一个行动计划,该计划将为每个节点(计算、网络、存储)并行启动动作。

提议的变更

我们可以并行启动具有相同动作权重的多个并发动作。

本规范定义了两个具有相同输入/输出数据流的不同规划器:权重规划器和工作负载稳定规划器。每个规划器都应使用新的 parents 属性,该属性将存储动作链接到的动作列表,但填充此属性的方式不同。

权重规划器旨在获得并行执行动作的统一方式。它不了解指定动作的结构以及它们之间的关系。主要目标是构建按权重排序的动作集合。高权重动作将在低权重动作之前进行规划。并行化是指能够并行执行具有相同动作类型的多个动作。并行化因子受另一个任务流参数 max_worker 限制。管理员可以在 watcher 配置文件中指定每个动作类型的权重及其并行化能力。让我们展示此规划器的非循环有向图示例

  ---sleep2    ---migration1     ---resize1
 /         \  /             \   /          \
I----sleep1-------migration2------resize2----resize3----E
              \             /
               ---migration3

此图是使用以下设置构建的

权重

并行化

睡眠

70

2

迁移

60

3

调整大小

50

2

由于有三个调整大小的动作,但仅允许同时执行两个,因此第三个调整大小的动作仅在之前的动作完成后才会执行。

权重规划器易于配置,应被视为新的默认规划器。

工作负载稳定规划器通过允许影响 parents 的构建来尊重动作类型的特征。某些动作类型,例如调整实例大小,应仅在迁移同一实例之前/之后运行,而不是并行运行。需要指定一些约束

  • 不链接的动作应并行执行。

  • 同一时间每个实例只能执行一个动作

  • 如果某个实例有多个动作,则链接的动作必须按照动作权重顺序执行。

因此,我们可以添加新的属性 parents,该属性将存储当前动作链接到的动作列表。可以使用非循环有向图来显示它

    ----------------a1(t=dis)-----------
   /                                    \
  |                                      \
  | ----------------a2(t=mig)-------------\
  |/                                       \
I-----a3(t=mig) -- a31(t=res)---------------E
  |\                                       /
  | ----------a4(t=resize)----------------/
  |                                      /
   \                                    /
    a5(resource=123, -- a51(resource=123,
       t=mig)               t=resize)

在这里我们可以看到以下链接

  • a1 动作禁用计算节点,并且不链接到另一个动作。它可以与其他动作并行运行(没有约束)。

  • a2 动作迁移实例,并且不链接到另一个动作。它可以与其他动作并行运行(没有约束)。

  • a3 动作迁移实例,并且是 a31 动作的父动作。它可以与其他动作并行运行。

  • a31 动作在上次由动作 a3 迁移后调整实例大小。

  • a4 动作调整实例大小,并且不链接到另一个动作。它可以与其他动作并行运行(没有约束)。

  • a5 动作迁移实例,并且是 a51 动作的父动作。它可以与其他动作并行运行。

  • a51 动作在上次由动作 a5 迁移后调整同一实例的大小。

正如我们所见,所有彼此独立的动作都可以并行执行。同时,如果某些动作链接到同一资源,则必须按照动作权重顺序执行它们。目前,我们可以定义以下权重

  • 图的结束 - 0

  • 禁用计算节点 - 1

  • 调整实例大小 - 2

  • 迁移实例 - 3

  • 初始点 - 4

这里有一个估计的伪代码,用于显示工作负载稳定规划器工作流程的一部分

action = [uuid, type, resource_id, metadata]

init = Flow()

action_weights = {
    'turn_host_to_acpi_s3_state': 0,
    'resize': 1,
    'migrate': 2,
    'sleep': 3,
    'change_nova_service_state': 4,
    'nop': 5,
}

actions = sorted_by_weights(descended)

for action in actions:
    a_type = action['action_type']
    if a_type != 'turn_host_to_acpi_s3_state':
        db_action = self._create_action(context, action)
        plugin_action = self.load_child_class(
            db_action.action_type)
        parents = plugin_action.validate_parents(
            resource_action_map, action)
        if parents:
            db_action.parents = parents
            db_action.save()
    else:
        # if we have an action that will make host unreachable, we need to
          complete all actions (resize and migration type) related to the
          host.
        parent_actions = get_actions(metadata=action[metadata][host])
        resize_actions = [x for x in parent_actions if x[type] == resize]
        migration_actions = [x for x in parent_actions if x[type] == mig]
        resize_migration_parents = [x[parents] for x in resize_actions]
        # Since resize actions have less weight than migration, they may
          have migration actions as parents and must be connected to the
          turn_host_to_acpi_s3_state action firstly.
        action_parents = []
        action_parents.extend([x[uuid] for x in resize_actions])
        # Add migrations that aren't linked to resize type actions
        action_parents.extend([x[uuid] for x in migration_actions
                              if [x[uuid]] not in resize_migration_parents)
        db_action = create_action(action, parents=action_parents)

本规范仅限于简单的动作链表作为行动计划。修改行动计划执行的第二部分将包含用于并行执行行动计划的图。

备选方案

数据模型影响

  • next 列应从 Action 表中删除。

  • parents 列应添加到 Action 表中。类型:JSON。

  • first_action_id 列应从 Action Plan 表中删除。

  • ActionPlan 对象的版本号可能需要更新到 2.0

REST API 影响

安全影响

通知影响

其他最终用户影响

watcher.conf 中的新配置参数

[watcher_planner] planner = weight #planner = workload_stabilization

[watcher_planners.weight] #weights = turn_host_to_acpi_s3_state:10,resize:20,migrate:30,sleep:40, change_nova_service_state:50,nop:60 #parallelization = turn_host_to_acpi_s3_state:2,resize:2,migrate:2,sleep:1, change_nova_service_state:1,nop:1

[watcher_planners.workload_stabilization] #weights = turn_host_to_acpi_s3_state:10,resize:20,migrate:30,sleep:40, change_nova_service_state:50,nop:60

性能影响

其他部署者影响

我们将拥有 2 个新的规划器扩展。我们应该通过运行 pip install [-e] 正确地重新安装 watcher。

开发人员影响

实现

负责人

主要负责人:Alexander Chadin <a.chadin@servionica.ru>

其他贡献者:Vincent Francoise <Vincent.FRANCOISE@b-com.com

工作项

  • 根据提议的更改更新数据模型(实际上是 API 和对象)。

  • 删除默认规划器。

  • 添加 watcher/decision_engine/planner/weight.py 和 watcher/decision_engine/planner/workload_stabilization.py

  • 将权重规划器设置为默认值。

  • 更新文档。

  • 添加适当的单元测试。

依赖项

https://blueprints.launchpad.net/watcher/+spec/plugins-parameters

测试

  • 将添加单元测试以验证这些修改。

文档影响

根据新的更改更新 defaultplanner 文档。

参考资料

历史