StackStorm介绍
StackStorm是一个强大的自动化平台,结合DevOps和ChatOps,提供可扩展、灵活和健壮的工具链用于应用、服务和工作流的自动化能力。
Mistral
Mistral是Mirantis公司为Openstack开发的工作流组件,提供Workflow as aService。Stackstorm集成了Mistral,提供更加灵活和强大的Workflow支持。
Mistral的一些概念,需要和StackStrom的概念区分开来:
- Workbook:工作簿。可以理解为工作流任务的文档,纪录了工作流,任务以及任务的执行顺序,依赖关系,以及每个任务的输入输出等。从开发者的角度看,可以认为它是一种工作流任务的文档组织形式,或者命名空间。
- Workflow:工作流。比Workbook小的单元。描述了任务,动作的执行顺序,依赖关系。一个Workbook可以有多条Workflow,也可以只有一条Workflow。
- Task:描述Workflow中包含的工作步骤。
- Action:Mistral中最小的单位,描述了某一个具体的动作,比如执行一个http请求,或者发一个e-mail等等。
YAQL & Jinja
Mistral中支持的模板解析语法有YAQL和Jinja,这提供了强大的流程控制和语法支持。下面对比下YAQL和Jinja:
YAQL:
version: '2.0'
examples.mistral-branching: description: > A sample workflow that demonstrates how to use conditions to determine which path in the workflow to take. type: direct input: - which tasks: t1: action: core.local input: cmd: "printf <% $.which %>" publish: path: <% task(t1).result.stdout %> on-success: - a: <% $.path = 'a' %> - b: <% $.path = 'b' %> - c: <% not $.path in list(a, b) %> a: action: core.local input: cmd: "echo 'Took path A.'" publish: stdout: <% task(a).result.stdout %> b: action: core.local input: cmd: "echo 'Took path B.'" publish: stdout: <% task(b).result.stdout %> c: action: core.local input: cmd: "echo 'Took path C.'" publish: stdout: <% task(c).result.stdout %> |
Jinja
version: '2.0'
examples.mistral-jinja-branching: description: > A sample workflow that demonstrates how to use conditions to determine which path in the workflow to take. type: direct input: - which tasks: t1: action: core.local input: cmd: "echo {{ _.which }}" publish: path: "{{ task('t1').result.stdout }}" on-success: - a: "{{ _.path == 'a' }}" - b: "{{ _.path == 'b' }}" - c: "{{ not _.path in ['a', 'b'] }}" a: action: core.local input: cmd: "echo 'Took path A.'" b: action: core.local input: cmd: "echo 'Took path B.'" c: action: core.local input: cmd: "echo 'Took path C.'" |
Mistral示例
StackStorm的examples下面提供了关于Mistral的示例,我们接下来通过一系列的示例来说明Mistral。
examples.mistral-basic
同样的MistralWorkflow跟ActionChainWorkflow一样都需要提供元数据文件和规格文件,
Pack examples的元数据文件是在/opt/stackstorm/packs/examples/actions目录下,规格文件是在/opt/stackstorm/packs/examples/actions/workflows目录下.
/opt/stackstorm/packs/examples/actions/mistral-basic.yaml
--- description: Run a local linux command enabled: true runner_type: mistral-v2 entry_point: workflows/mistral-basic.yaml name: mistral-basic pack: examples parameters: cmd: required: true type: string timeout: type: integer default: 60 |
规格文件/opt/stackstorm/packs/examples/actions/workflows/mistral-basic.yaml
version: '2.0'
examples.mistral-basic: description: A basic workflow that runs an arbitrary linux command. type: direct input: - cmd - timeout output: stdout: <% $.stdout %> tasks: task1: action: core.local cmd=<% $.cmd %> timeout=<% $.timeout %> publish: stdout: <% task(task1).result.stdout %> stderr: <% task(task1).result.stderr %> |
根据定义examples.mistral-basic需要提供参数cmd(必选)和timeout(可选),然后在task1中调用core.local执行,并且打印执行结果。执行如下:
$ st2 run examples.mistral-basic cmd="date" . id: 5afba6ed2b2556015687cdda action.ref: examples.mistral-basic parameters: cmd: date status: succeeded result_task: task1 result: failed: false return_code: 0 stderr: '' stdout: Wed May 16 03:35:10 UTC 2018 succeeded: true start_timestamp: Wed, 16 May 2018 03:35:09 UTC end_timestamp: Wed, 16 May 2018 03:35:11 UTC +--------------------------+------------------------+-------+------------+-------------------------------+ | id | status | task | action | start_timestamp | +--------------------------+------------------------+-------+------------+-------------------------------+ | 5afba6ee2b2556015687cddd | succeeded (0s elapsed) | task1 | core.local | Wed, 16 May 2018 03:35:10 UTC | +--------------------------+------------------------+-------+------------+-------------------------------+ |
examples. mistral-workbook-basic
Mistral中有个WorkBook的概念,是Workflow的组合,也就是说可以同时定义多个Workflow
/opt/stackstorm/packs/examples/actions/workflows/mistral-workbook-multiple-subflows.yaml
version: "2.0" name: "examples.mistral-workbook-multiple-subflows"
workflows:
main: type: direct output: report: <% $.report %> state: <% $.state %> tasks: call_internal_workflow: workflow: wf1 input: v1: ok publish: report: <% task(call_internal_workflow).result.report %> on-success: - call_internal_workflow_multiple_tasks call_internal_workflow_multiple_tasks: workflow: wf2 input: v1: good v2: excellent on-success: - call_external_workflow call_external_workflow: action: examples.mistral-basic input: cmd: "echo 'external workflow ok'" publish: state: <% task(call_external_workflow).result.stdout %> on-success: - call_action_chain call_action_chain: action: examples.echochain
wf1: type: direct input: - v1 output: report: <% $.report %> tasks: t1: action: core.local input: cmd: "echo 'task1 <% $.v1 %>'; sleep 1" publish: report: <% task(t1).result.stdout %>
wf2: type: direct input: - v1 - v2 tasks: t1: action: core.local input: cmd: "echo 'task2 <% $.v1 %>'; sleep 1" t2: action: core.local input: cmd: "echo 'task3 <% $.v2 %>'; sleep 2" |
examples.mistral-handle-error
Mistral Workflow通过可以设置子任务成功失败后的执行顺序,
/opt/stackstorm/packs/examples/actions/workflows/mistral-handle-error.yaml:
version: '2.0'
examples.mistral-handle-error: description: > A workflow example that illustrates error handling. By default when any task fails, the notify_on_error task will be executed and the workflow will transition to the failed state. type: direct input: - cmd vars: error_handled: False tasks: task1: action: core.local cmd="echo 1 && exit 0" publish: stdout: <% task(task1).result.stdout %> on-success: - task2 on-error: - handle_error task2: action: core.local cmd="echo 2 && exit 1" publish: stdout: <% task(task1).result.stdout %> on-error: - handle_error handle_error: action: core.local input: cmd: "printf '<% task(task1).result.stderr %>'" publish: error_handled: True on-complete: - fail |
examples.mistral-handle-error定义了task1和task2,task1成功后执行task2,task2失败后执行handle_error。
$ st2 run examples.mistral-handle-error .. id: 5afbca362b2556015687cddf action.ref: examples.mistral-handle-error parameters: None status: failed start_timestamp: Wed, 16 May 2018 06:05:42 UTC end_timestamp: Wed, 16 May 2018 06:05:45 UTC +--------------------------+------------------------+--------------+------------+-------------------------------+ | id | status | task | action | start_timestamp | +--------------------------+------------------------+--------------+------------+-------------------------------+ | 5afbca372b2556015687cde2 | succeeded (0s elapsed) | task1 | core.local | Wed, 16 May 2018 06:05:43 UTC | | 5afbca372b2556015687cde4 | failed (1s elapsed) | task2 | core.local | Wed, 16 May 2018 06:05:43 UTC | | 5afbca382b2556015687cde6 | succeeded (0s elapsed) | handle_error | core.local | Wed, 16 May 2018 06:05:44 UTC | |
Mistral Workflow可以针对失败的子任务进行重跑(StackStorm2.7版本的ActionChain不支持从失败的子任务继续重跑):
$ st2 execution re-run 5afbca362b2556015687cddf --tasks task2 . id: 5afbcadc2b2556015687cde8 action.ref: examples.mistral-handle-error parameters: None status: failed result_task: task2 result: failed: true return_code: 1 stderr: '' stdout: 2 succeeded: false start_timestamp: Wed, 16 May 2018 06:08:28 UTC end_timestamp: Wed, 16 May 2018 06:08:30 UTC +--------------------------+------------------------+--------------+------------+-------------------------------+ | id | status | task | action | start_timestamp | +--------------------------+------------------------+--------------+------------+-------------------------------+ | 5afbcadc2b2556015687cdea | failed (1s elapsed) | task2 | core.local | Wed, 16 May 2018 06:08:28 UTC | | 5afbcadd2b2556015687cdec | succeeded (0s elapsed) | handle_error | core.local | Wed, 16 May 2018 06:08:29 UTC | +--------------------------+------------------------+--------------+------------+-------------------------------+ |
examples.mistral-repeat
Mistral Workflow支持循环语法:
/opt/stackstorm/packs/examples/actions/workflows/mistral-repeat.yaml
version: '2.0'
examples.mistral-repeat: description: > A sample workflow that demonstrates how to repeat a task x number of times with the same inputs. type: direct input: - cmd - count tasks: repeat: with-items: i in <% list(range(0, $.count)) %> action: core.local cmd=<% $.cmd %> publish: result: <% task(repeat).result.select($.stdout) %> |
循环5次执行命令:
st2 run examples.mistral-repeat cmd=date count=5 .. id: 5afbdab82b2556015687ce19 action.ref: examples.mistral-repeat parameters: cmd: date count: 5 status: succeeded result_task: repeat result: - failed: false return_code: 0 stderr: '' stdout: Wed May 16 07:16:09 UTC 2018 succeeded: true - failed: false return_code: 0 stderr: '' stdout: Wed May 16 07:16:09 UTC 2018 succeeded: true - failed: false return_code: 0 stderr: '' stdout: Wed May 16 07:16:09 UTC 2018 succeeded: true - failed: false return_code: 0 stderr: '' stdout: Wed May 16 07:16:09 UTC 2018 succeeded: true - failed: false return_code: 0 stderr: '' stdout: Wed May 16 07:16:09 UTC 2018 succeeded: true start_timestamp: Wed, 16 May 2018 07:16:08 UTC end_timestamp: Wed, 16 May 2018 07:16:11 UTC +--------------------------+------------------------+--------+------------+-------------------------------+ | id | status | task | action | start_timestamp | +--------------------------+------------------------+--------+------------+-------------------------------+ | 5afbdab82b2556015687ce20 | succeeded (1s elapsed) | repeat | core.local | Wed, 16 May 2018 07:16:08 UTC | | 5afbdab82b2556015687ce22 | succeeded (1s elapsed) | repeat | core.local | Wed, 16 May 2018 07:16:08 UTC | | 5afbdab82b2556015687ce23 | succeeded (1s elapsed) | repeat | core.local | Wed, 16 May 2018 07:16:08 UTC | | 5afbdab82b2556015687ce21 | succeeded (1s elapsed) | repeat | core.local | Wed, 16 May 2018 07:16:08 UTC | | 5afbdab82b2556015687ce24 | succeeded (1s elapsed) | repeat | core.local | Wed, 16 May 2018 07:16:08 UTC | +--------------------------+------------------------+--------+------------+-------------------------------+ |
参考
- https://yaql.readthedocs.io/en/latest/
- http://jinja.pocoo.org/
- http://jinja.pocoo.org/
作者简介
吴龙辉,现任网宿科技云计算架构师,致力于云计算PaaS的研究和实践,《Kubernetes实战》作者,活跃于CloudFoundry,Docker,Kubernetes等开源社区,贡献代码和撰写技术文档。邮箱:[email protected]