在 Vitrage 模板中支持外部动作

launchpad 蓝图: https://blueprints.launchpad.net/vitrage/+spec/support-external-actions

目前,Vitrage 模板支持以下动作:触发告警、设置状态、标记因果关系和降级。降级功能的实现比较零散(更新顶点上的属性并调用通知器)。

我们需要一种在模板中定义应该采取的外部动作的方式。一个例子是降级。另一个例子是执行 Mistral 工作流或 Congress 策略。

问题描述

应支持以下用例

  1. 降级。这是一个现有的用例。如果存在降级动作,Vitrage 将调用 Nova 降级 API。更改后行为应保持不变。

  2. 执行 Mistral 工作流。用户应该能够基于 Vitrage insights 执行 Mistral 工作流。

  3. 执行其他外部动作,例如 Congress 策略。

提议的变更

为每个我们想要支持的外部引擎添加一个新的动作。该动作将具有要发送到引擎的参数的元数据。

示例

action:
  action_type: execute_nova
  metadata:
    api_call: mark-down
    host: host1
action:
  action_type: execute_mistral
  metadata:
    workflow: evacuate_host
    failed_host: host1

为每个引擎添加一个新的 external_* 动作背后的想法是强调 Vitrage 支持预定义的外部动作集合,并且明确不支持运行脚本。

内部实现对于 Nova、Mistral、Congress 等将是相同的。在模板加载阶段,execute_* 动作将被转换为通用的 Execute 动作,并带有 notifier 参数。模板验证器将验证所需的 notifier 是否在 vitrage.conf 中启用,否则模板加载将失败。

当执行 Execute 动作时,评估器将向所需 notifier 的消息总线发送一个事件。这样,只有 Mistral notifier 会处理 execute_mistral 动作。

请注意,目前只有 Vitrage 图发送通知到 notifier。这种行为将被改变,因此通知将同时从图(用于推导出的告警和设置状态)和从评估器发送。

备选方案

有两种替代方案

发送消息总线通知

Vitrage 可以有一个消息总线 notifier,它将发送关于触发/删除告警、设置状态和标记因果关系的通知。Mistral 将被配置为基于从 Vitrage 接收到的通知执行某些工作流。

优点

  • 无需在 Vitrage 中进行额外的配置

  • 可以与当前的 notifiers 机制一起工作

缺点

  • 消息总线通知可能会丢失

  • 功能较弱。在 Vitrage 模板中,用户可以决定基于告警的组合或特定的拓扑来执行工作流。一旦 Mistral 收到通知,拓扑上下文就不再存在。

  • 此解决方案不支持降级用例

在特定 notifier 上完成配置

将编写一个 Mistral notifier 并接收来自图的通知。它将通过一个 yaml 文件进行配置,该文件将确定针对特定告警执行哪个工作流。

优点

  • 无需在 Vitrage 中进行额外的配置

  • 可以与当前的 notifiers 机制一起工作

  • 不会丢失消息

缺点

  • 功能较弱。在 Vitrage 模板中,用户可以决定基于告警的组合或特定的拓扑来执行工作流。在 Mistral notifier 中,我们不再拥有这种上下文。

  • 此解决方案不支持降级用例

计算 action_target

每个“常规”动作(raise_alarm、set_state、add_causal_relationship)都有一个 action_target 块。对于外部动作,action_target 没有意义,因为它们由一个没有“目标”术语的外部引擎管理。

问题是 action_target 对于子图匹配计算至关重要,以便计算连通分量。

提出的解决方案

对于外部动作,我们将自动计算一个 action target。目标将从可能的目标的集合中任意选择。在涉及 {and, or, not} 的复杂条件下,找到目标可能并不容易。由于这个原因,对于外部动作,一些更复杂的条件将不受支持。

计算方法

  • And 条件 - 条件的任何顶点都可以是目标

  • Not 条件 - 条件的任何顶点都不能是目标

  • Or 条件 - 目标应该是出现在 Or 条件的任何“正向”部分(即,前面没有 ‘not’)中的顶点

示例:

注意: 在某些情况下,找到有效的目标是不可能的。它们用 ‘/’ 标记。

在这些情况下,模板验证应该失败,对于所有类型的动作。

条件

可能的 targets

a_in_error_status

a

a_contains_b

a, b

a_contains_b or a_contains_c

a

a_contains_b or a_contains_c or a_contains_d

a

a_in_error_status or a_contains_c or a_contains_d

a

a_contains_b or a_contains_c or b_contains_d

不支持

a_contains_b and a_contains_c

a, b, c

a_contains_b and a_contains_c and a_contains_d

a, b, c, d

a_contains_b or (a_contains_c and a_contains_d)

a

a_contains_b or (a_contains_c and b_contains_d)

a,b

not a_contains_b

不支持

not a_in_error_status

不支持

a_contains_b or not a_contains_c

不支持

a_contains_b or (a_contains_c and not a_contains_d)

a

a_contains_b or (not a_contains_c and not a_contains_d)

不支持

计算 action_target 的替代方案

我们可以决定外部动作需要像所有其他动作一样的 action_target。这将简化实现,但在逻辑上是错误的。action_target 将作为子图匹配的“辅助实体”,不应该由最终用户来帮助修复实现问题。就外部引擎而言,action_target 没有意义。

数据模型影响

将向评估器添加一个新的 Execute 动作。

REST API 影响

版本影响

我们应该为模板引入一个版本控制机制。这将在一修改降级功能的实现时完成。

其他最终用户影响

部署者影响

开发者影响

Horizon 影响

实现

负责人

主要负责人

ifat-afek

工作项

  • 增强模板语言(模板加载和验证)

  • 更新文档

  • 从评估器执行外部动作

依赖项

测试

实现将由单元测试和 tempest 测试覆盖。

文档影响

应该记录新的动作

参考资料