使用“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”的内容作为备忘录记录下来了。

自动化虽然非常方便,但最终还是由人来进行管理,所以我认为使用类似本次角色结构的机制来进行整理是很重要的。

bannerAds