Mistral 主要特性¶
任务结果 / 数据流¶
Mistral 支持将数据从一个任务传递到另一个任务。换句话说,如果taskA产生一个值,那么紧随taskA之后的taskB可以使用它。为了使用这些数据,Mistral 依赖于一种名为 YAQL 的查询语言。YAQL 是一种功能强大但简单的工具,允许用户过滤信息、转换数据和调用函数。有关更多信息,请参阅 YAQL 官方文档。这种数据传递机制在工作流概念中起着核心作用,被称为数据流。
以下是 Mistral 工作流语言视角下 Mistral 数据流的简单示例
version: '2.0'
my_workflow:
input:
- host
- username
- password
tasks:
task1:
action: std.ssh host=<% $.host %> username=<% $.username %> \
password=<% $.password %>
input:
cmd: "cd ~ && ls"
on-complete: task2
task2:
action: do_something data=<% task(task1).result %>
名为“task1”的任务产生一个结果,其中包含用户主文件夹中的文件列表(主机名和用户名都作为工作流输入提供),而任务“task2”使用 YAQL 表达式“task(task1).result”来使用此数据。“task()”是 Mistral 在 YAQL 中注册的一个函数,用于通过名称获取有关任务的信息。
任务亲和性¶
任务亲和性是一项功能,可用于在特定的 Mistral 执行器上执行特定任务。实际上,有两种情况
您需要在单个执行器上执行任务。
您需要在命名组内的任何执行器上执行任务。
要启用任务亲和性功能,请编辑配置文件中的“executor”部分中的“host”属性
[executor]
host = my_favorite_executor
然后启动(重新启动)执行器。使用 Mistral 工作流语言中的“target”任务属性来指定此执行器
... Workflow YAML ...
task1:
...
target: my_favorite_executor
... Workflow YAML ...
任务策略¶
任何 Mistral 任务,无论其工作流类型如何,都可以选择性地配置策略。策略控制任务的流程——例如,策略可以在任务开始之前或任务完成后延迟任务执行。
YAML 示例¶
my_task:
action: my_action
pause-before: true
wait-before: 2
wait-after: 4
fail-on: <% $.some_value < 4 %>
timeout: 30
retry:
count: 10
delay: 20
break-on: <% $.my_var = true %>
Mistral 中有不同类型的策略。
pause-before
指定 Mistral Engine 是否应该在启动任务之前暂停工作流。
wait-before
指定 Mistral Engine 在启动任务之前应等待的秒数延迟。
wait-after
指定 Mistral Engine 在任务完成后应等待的秒数延迟,然后再启动‘on-success’、‘on-error’ 或 ‘on-complete’ 中指定的任务。
fail-on
指定任务将失败的条件,即使操作已成功完成。
timeout
指定一个以秒为单位的时间段,如果任务未完成,引擎将自动使任务失败。
retry
指定任务应如何重复的模式。
count - 指定任务可以重复的最大次数。
delay - 指定后续任务迭代之间的秒数延迟。
break-on - 指定一个 YAQL 表达式,如果评估结果为‘true’,则将中断迭代循环。如果触发,则认为任务遇到错误。
continue-on - 指定一个 YAQL 表达式,如果评估结果为‘true’,则将继续迭代循环。如果触发,则认为任务成功。
也可以在一行中配置单个行的重试策略,如下所示
task1: action: my_action retry: count=10 delay=5 break-on=<% $.foo = 'bar' %>
任何策略的所有参数值都可以定义为 YAQL 表达式。
注意:在同一个重试块中使用 break-on 和 continue-on 很少见。break-on 应该在预期操作在一段时间内处于 ERROR 状态时使用,但最终可能会进入 SUCCESS 状态,从而停止循环。但是,如果 break-on 为 ‘true’,则重试将停止,任务将处于 ERROR 状态。continue-on 应该在操作通常返回 SUCCESS 时使用,但操作有其他结果可用于指示是否继续循环。
Join¶
Join 流控制允许同步多个并行工作流分支并聚合它们的数据。
完全 Join (join: all).
YAML 示例¶
register_vm_in_load_balancer:
...
on-success:
- wait_for_all_registrations
register_vm_in_dns:
...
on-success:
- wait_for_all_registrations
try_to_do_something_without_registration:
...
on-error:
- wait_for_all_registrations
wait_for_all_registrations:
join: all
action: send_email
当任务具有分配了值 “all” 的属性 “join” 时,只有当所有上游任务(导致此任务的任务)都已完成并且相应的条件已触发时,该任务才会运行。如果任务 A 在任何 “on-success”、“on-error” 和 “on-complete” 子句中提到了任务 B,则任务 A 被认为是任务 B 的上游任务,无论 YAQL 保护表达式如何。
部分 Join (join: 2)
YAML 示例¶
register_vm_in_load_balancer:
...
on-success:
- wait_for_all_registrations
register_vm_in_dns:
...
on-success:
- wait_for_all_registrations
register_vm_in_zabbix:
...
on-success:
- wait_for_all_registrations
wait_for_two_registrations:
join: 2
action: send_email
当任务具有分配了数字值的属性 “join” 时,该任务将在至少完成这么多上游任务并且相应的条件已触发后运行。在上面的示例中,如果两个“register_vm_xxx”任务中的任何两个任务完成,则任务“wait_for_two_registrations”将运行。
Discriminator (join: one)
Discriminator 是 Partial Join 的特殊情况,其中 “join” 属性的值为 1。在这种情况下,可以使用特殊字符串值 “one”,它是为了与 “all” 对称而引入的。但是,用户是否使用 “1” 或 “one” 由用户决定。
处理集合 (with-items)¶
YAML 示例¶
---
version: '2.0'
create_vms:
description: Creating multiple virtual servers using "with-items".
input:
- vm_names
- image_ref
- flavor_ref
output:
vm_ids: <% $.vm_ids %>
tasks:
create_servers:
with-items: vm_name in <% $.vm_names %>
action: nova.servers_create name=<% $.vm_name %> \
image=<% $.image_ref %> flavor=<% $.flavor_ref %>
publish:
vm_ids: <% task().result.id %>
on-success:
- wait_for_servers
wait_for_servers:
with-items: vm_id in <% $.vm_ids %>
action: nova.servers_find id=<% $.vm_id %> status='ACTIVE'
retry:
delay: 5
count: <% $.vm_names.len() * 10 %>
在此示例中,工作流 “create_vms” 根据我们在 “vm_names” 输入参数中提供的数量创建多个虚拟机。例如,如果指定 vm_names=[“vm1”, “vm2”],则它将基于相同的镜像和 flavor 创建具有这些名称的服务器。这是可能的,因为我们正在使用 “with-items” 关键字,该关键字将操作或工作流与多次运行的任务相关联。“with-items” 任务属性的值包含以下形式的表达式:<variable_name> in <% YAQL_expression %>。
最常见的形式是
with-items:
- var1 in <% YAQL_expression_1 %>
- var2 in <% YAQL_expression_2 %>
...
- varN in <% YAQL_expression_N %>
其中以 YAQL_expression_1、YAQL_expression_2、YAQL_expression_N 表示的集合必须大小相等。当任务启动时,Mistral 将并行迭代所有集合,即迭代次数将等于任何集合的长度。
请注意,在 “with-items” 的情况下,任务结果(在工作流上下文中可访问为 <% $.task_name %>)将是一个列表,其中包含相应操作/工作流调用的结果。如果至少一个操作/工作流调用失败,则整个任务将进入 ERROR 状态。也可以为具有 “with-items” 属性的任务应用重试策略。在这种情况下,重试策略将根据 “with-items” 配置重新启动所有操作/工作流调用。其他策略也可以以与常规非 “with-items” 任务相同的方式使用。
执行过期策略¶
当 Mistral 在生产中使用时,控制已完成的工作流执行的数量可能很困难。默认情况下,Mistral 将无限期地存储所有执行,并且随着时间的推移,存储的数量将不断累积。可以通过设置过期策略来解决此问题。
默认情况下,此功能已禁用。
此策略定义了自上次更新时间以来执行的最大年龄(分钟),以及已完成执行的最大数量。每次评估都将满足这些条件,因此过期的执行(超过指定时间)将被删除,并且完成状态下的执行数量(无论是否过期)将限制为 max_finished_executions。
要启用该策略,请编辑 Mistral 配置文件并指定 evaluation_interval 和 older_than 或 evaluation_interval 选项中的至少一个。
[execution_expiration_policy]
evaluation_interval = 120 # 2 hours
older_than = 10080 # 1 week
max_finished_executions = 500
evaluation_interval
评估间隔定义了 Mistral 将检查并确保上述约束的频率。在上面的示例中,它设置为两个小时,因此每两个小时 Mistral 将删除超过 1 周的执行,并保留最新的 500 个已完成的执行。
older_than
定义自上次更新以来执行的最大年龄(分钟)。它必须大于或等于
1。
max_finished_executions
定义已完成执行的最大数量。它必须大于或等于
1。
工作流命名空间¶
Mistral 允许在命名空间中创建工作流。因此,只要它们位于不同的命名空间中,就可以创建许多具有相同名称的工作流。
有关更多信息,请参阅 工作流命名空间
任务跳过¶
Mistral 具有跳过 ERROR 状态任务的能力。任务从 ERROR 状态移动到 SKIPPED 状态,发布 publish-on-skip 部分中的变量,并且工作流从 on-skip 部分中指定的任务继续。要配置任务的跳过行为,请在任务定义中填写以下属性
on-skip - 可选。此参数指定在跳过此任务后应启动哪些任务。
publish-on-skip - 可选。此参数指定在跳过此任务后应发布哪些变量。
也可以跳过没有预定义上述参数的任务,在这种情况下,任务不会发布任何内容,并会通过 on-success 分支继续。这对于下一个任务来说可能不安全,因为它们可能缺少一些输入,因此在跳过此类任务之前请三思。
可以通过以下请求执行任务跳过
PUT /v2/tasks
{
"id": "<task-id>",
"state": "SKIPPED"
}