使用“import_role”
上一次
引言
搜索ansible的实际示例时,经常会看到”将所需任务直接记录在playbook中的方法”。
我认为在熟悉ansible之前,这种方法更简单,易于理解。但是在实际工作中使用ansible时,可能不太常用,因为这样做会降低管理的便利性和减少错误的可能性。
(实际上,我也是这样认为的。。)
不想直接在playbook.yml文件中编写需要执行的任务,而是创建一个由想要执行的任务组成的角色,并在角色中编写这些任务。因此,我想简单地写下这种方法。
验证环境
关于验证环境的建立
我使用Docker构建了验证环境。关于构建ansible环境,请参考下方页面(有关操作系统等,请查看下方页面):
https://qiita.com/Shoma0210/items/7d7d24d7c3f95f19b427
环境概述
▼节点
<コントロールノード>
ansible_main
<ターゲットノード>
ansible_test01
ansible_test02
ansible_test03
当在控制节点(ansible_main)上执行playbook.yml时,其中所包含的任务将在目标节点(ansible_test01、02、03)上执行。
▼目录结构
$ tree
.
|-- ansible_playbook_apache.yml
|-- ansible_playbook_debug.yml
|-- hosts
|-- roles
|-- role_apache
| `-- tasks
| `-- main.yml
|-- role_debug
| `-- tasks
| `-- main.yml
|-- role_debug_2
`-- tasks
`-- main.yml
7 directories, 6 files
⇒ 这次,我们主要使用以下文件:
ansible_playbook_debug.yml
roles/role_debug/tasks/main.yml
roles/role_debug_2/tasks/main.yml
hosts
解释内容(import_role)
这次作为一个简单的例子,
在ansible_test01和ansible_test02中,输出”你好,世界!”的消息。
在ansible_test03中,输出”不必要”的消息。
为了执行这个处理操作。(对于这种程度的任务,我认为不必特意分成角色,但这只是一个例子,敬请谅解。)
处理流程
处理的流程如下(除了①之外的所有步骤都将自动进行)
①在控制节点(ansible_main)上执行playbook(ansible_playbook_debug.yml)。
②通过上述步骤,按顺序执行ansible_playbook_debug.yml中的任务。
③由于ansible_playbook_debug.yml中使用了”import_role”模块,因此需要读取位于”roles”目录下的角色。
→本次使用的角色是”role_debug”和”role_debug_2″。
④执行位于所使用角色目录下的”tasks/main.yml”中的任务。
⑤自动输出执行结果。
关于playbook的问题
我们将使用的播放书是ansible_playbook_debug.yml,其内容如下:
---
- hosts: all
become: yes
tasks:
- name: Play Debug role
import_role:
name: role_debug
tags:
- debug
when: "'debug' in group_names"
- name: Play Debug2 role
import_role:
name: role_debug_2
tags:
- debug_2
when: "'debug_2' in group_names"
由上至下依次执行,因此首先执行名为「Play Debug role」的任务。
当查看其中内容时,使用了”import_role”模块,并且设置为读取”role_debug”角色。
通过这个设置,将执行在role_debug目录下设置(定义)的任务等。
另外,底下标有两个说明:「tags: – debug」和「when: “‘debug’ in group_names”」。
标签
通过设置「tags」,可以在执行playbook时只执行「特定的任务」。
在本例中,通过在playbook执行时指定如下内容,将只执行包含在「Play Debug role」中的任务。(→跳转到role_debug去解析。)
$ ansible-playbook --tags debug ansible_playbook_debug.yml
PLAY [all] *************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************
ok: [ansible_test03]
ok: [ansible_test02]
ok: [ansible_test01]
TASK [role_debug : TEST Message] ***************************************************************************************************************************
ok: [ansible_test01] => {
"msg": " Hello,World! "
}
ok: [ansible_test02] => {
"msg": " Hello,World! "
}
skipping: [ansible_test03]
PLAY RECAP *************************************************************************************************************************************************
ansible_test01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ansible_test02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ansible_test03 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
当
只需要一种中国的方法来释义以下内容:
「当」一词,字面意义上表示「执行的条件」。
这次的情况是
当:”group_names”中有”debug”时
由于其所述,这意味着只运行属于“debug”组的服务器。
这个群组的定义在名为“hosts”的文件中定义。
就是被称为清单文件的那个。
这次,清单文件被配置如下:
[node]
ansible_test01
ansible_test02
ansible_test03
[debug]
ansible_test01
ansible_test02
[debug_2]
ansible_test03
「[debug]」文件夹下面有两个文件,分别是「ansible_test01」和「ansible_test02」。
在这个例子中,”Play Debug role”这个任务有一个条件,即”when: “‘debug’ in group_names”,所以只有ansible_test01和ansible_test02这两台服务器(节点)会执行”Play Debug role”。
此外,ansible_test03是属于[debug_2]组,而不属于[debug]组的服务器,因此针对[debug]组执行的任务将被跳过。
在上述的执行结果中(指定使用标签debug进行执行),ansible_test03也被标记为“跳过”。
当把when句和清单文件结合使用时,可以将执行目标限定在特定范围内。
(当然,我们也可以以其他方式使用when句和清单文件。)
关于角色的③和④议题
①在控制节点(ansible_main)上执行playbook(ansible_playbook_debug.yml)。
②上述步骤将按照ansible_playbook_debug.yml中列出的任务顺序依次执行。
③由于ansible_playbook_debug.yml中使用了”import_role”模块,因此将读取位于”roles”目录下的角色。
→本次使用了”role_debug”和”role_debug_2″两个角色。
④执行位于使用的角色目录下的”tasks/main.yml”中列出的任务。
⑤执行结果将自动输出。
角色
在「roles」目录中,可以创建多个角色。
(本次共有以下3个角色)
|-- roles
|-- role_apache
| `-- tasks
| `-- main.yml
|-- role_debug
| `-- tasks
| `-- main.yml
|-- role_debug_2
`-- tasks
`-- main.yml
我认为能够创建多个角色有几个好处。
例如,通过为每个MW创建角色,可以获得以下好处。
・按照MW的每个实施任务进行管理,变得更加轻松。
・由于每个MW的任务被归类分离,可以预防意外操作。
「关于Apache,我们使用role_apache;关于Tomcat,我们使用role_tomcat。」这样分开更明确和易于理解。
如果在playbook中没有使用role,并且对每个中间件的任务进行完全记录的话,将会产生大量的描述,并且在进行修正和补充时也会耗费很多精力。
如果没有使用角色,而是在playbook中完整记录每个中间件的任务,那么在进行修正和添加时,也存在修改其他中间件描述的风险。
在操作和管理工作中,我认为“一目了然”非常重要,而且比任何事情都不能允许“人为错误”的发生。
当物量增多或多个要素复杂交织在一起时,由于人为的疏忽,人类往往会忽略一些细节。因此,我认为将操作步骤分成角色进行管理,而不是直接在playbook上进行记录可能是更好的选择。
任务/main.yml
每个角色中都有几个目录。就像上一篇「Ansible备忘录1」中介绍的那样,「handler」也可以在每个角色的目录中进行设置。(还有其他一些目录,如「default」、「template」、「files」等等…)
由于本次是关于任务说明的讨论,所以只需要在”tasks/main.yml”文件中进行记录。
如果使用role,在执行playbook时,会执行在tasks/main.yml中定义的任务。
执行playbook
↓
执行被定义在import_role中的角色
↓
执行该角色下的tasks/main.yml中所定义的任务
大致上是这样吧。
此次
请在ansible_test01和ansible_test02上输出消息“Hello, World!”。
在ansible_test03上输出消息“Unnecessary”。
为了执行这个任务,tasks/main.yml应该如下所示。
---
- name: "TEST Message"
debug:
msg: ' Hello,World! '
---
- name: "Debug_Message_2"
debug:
msg: ' Unnecessary '
不管怎样,不仅仅是debug,各种模块都可以使用。
⑤执行结果
执行以上内容的结果将如下所示。
$ ansible-playbook ansible_playbook_debug.yml
PLAY [all] *************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************
ok: [ansible_test02]
ok: [ansible_test03]
ok: [ansible_test01]
TASK [role_debug : TEST Message] ***************************************************************************************************************************
ok: [ansible_test01] => {
"msg": " Hello,World! "
}
ok: [ansible_test02] => {
"msg": " Hello,World! "
}
skipping: [ansible_test03]
TASK [role_debug_2 : Debug_Message_2] **********************************************************************************************************************
skipping: [ansible_test01]
skipping: [ansible_test02]
ok: [ansible_test03] => {
"msg": " Unnecessary "
}
PLAY RECAP *************************************************************************************************************************************************
ansible_test01 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
ansible_test02 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
ansible_test03 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
在页面底部,我们提供了各种设置的示例和执行结果(按标签分类)。供您参考。
例子的记录
---
- hosts: all
become: yes
tasks:
- name: Play Debug role
import_role:
name: role_debug
tags:
- debug
when: "'debug' in group_names"
- name: Play Debug2 role
import_role:
name: role_debug_2
tags:
- debug_2
when: "'debug_2' in group_names"
---
- name: "TEST Message"
debug:
msg: ' Hello,World! '
---
- name: "Debug_Message_2"
debug:
msg: ' Unnecessary '
[node]
ansible_test01
ansible_test02
ansible_test03
[debug]
ansible_test01
ansible_test02
[debug_2]
ansible_test03
执行结果
$ ansible-playbook ansible_playbook_debug.yml
PLAY [all] *************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************
ok: [ansible_test02]
ok: [ansible_test03]
ok: [ansible_test01]
TASK [role_debug : TEST Message] ***************************************************************************************************************************
ok: [ansible_test01] => {
"msg": " Hello,World! "
}
ok: [ansible_test02] => {
"msg": " Hello,World! "
}
skipping: [ansible_test03]
TASK [role_debug_2 : Debug_Message_2] **********************************************************************************************************************
skipping: [ansible_test01]
skipping: [ansible_test02]
ok: [ansible_test03] => {
"msg": " Unnecessary "
}
PLAY RECAP *************************************************************************************************************************************************
ansible_test01 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
ansible_test02 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
ansible_test03 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
$ ansible-playbook --tags debug ansible_playbook_debug.yml
PLAY [all] *************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************
ok: [ansible_test03]
ok: [ansible_test02]
ok: [ansible_test01]
TASK [role_debug : TEST Message] ***************************************************************************************************************************
ok: [ansible_test01] => {
"msg": " Hello,World! "
}
ok: [ansible_test02] => {
"msg": " Hello,World! "
}
skipping: [ansible_test03]
PLAY RECAP *************************************************************************************************************************************************
ansible_test01 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ansible_test02 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ansible_test03 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
$ ansible-playbook --tags debug_2 ansible_playbook_debug.yml
PLAY [all] *************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************
ok: [ansible_test02]
ok: [ansible_test03]
ok: [ansible_test01]
TASK [role_debug_2 : Debug_Message_2] **********************************************************************************************************************
skipping: [ansible_test01]
skipping: [ansible_test02]
ok: [ansible_test03] => {
"msg": " Unnecessary "
}
PLAY RECAP *************************************************************************************************************************************************
ansible_test01 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
ansible_test02 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
ansible_test03 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
结束
根据实践经验,我尽量以简明易懂的方式进行了输出。
在撰写过程中,我对import_role进行了一些调查研究,似乎”roles”这个表述也可以实现与”import_role”相似的功能…
考虑到时间有限,我只将关于”import_role”的内容作为备忘录记录下来了。
自动化虽然非常方便,但最终还是由人来进行管理,所以我认为使用类似本次角色结构的机制来进行整理是很重要的。