Ansible - 处理角色、任务和依赖关系的正确方法?

Ansible - 处理角色、任务和依赖关系的正确方法?

Ansible - 处理角色、任务、依赖关系的正确方法?

相关当列为依赖项时,如何防止 ansible 角色多次运行?

这是一篇很长的帖子/问题。TL;DR - 设置角色和任务标记的正确方法是什么,以便依赖关系能够正常工作而无需多次运行角色。

Ansible-测试-deps用于剧本设置来说明问题。

我一直无法让剧本与标签和依赖项配合良好。一般来说,我希望剧本包含一堆角色(每个角色都有一些依赖项),以便“干净利落地工作”。仅这一点就相当容易设置,并且在整个剧本中使用所有角色时效果很好。具有依赖项的角色可以在剧本中以任何顺序定义,并且这些依赖项确保它们以正确的顺序运行。当然,没有依赖项的角色将按照它们在剧本角色:部分中出现的顺序运行。

但有时人们只想运行一部分角色,然后它就崩溃了,一些角色被运行多次,而且顺序很奇怪。

因此我建立了一个测试设置,其中包含 4 个角色(A B C D),以及一个使用多种标记方法的剧本。实际上,它有 4 个角色,每个角色都有未标记的任务,还有 4 个角色有标记的任务……再加上一个名为“z”的角色,它没有任何任务,只是所有其他角色的依赖关系。它们看起来像这样:

Role name    Dependencies
----------   ------------
a_tagged     none
b_tagged     a_tagged
c_tagged     b_tagged
d_tagged     c_tagged b_tagged a_tagged
z_tagged     a_tagged b_tagged c_tagged d_tagged
a_untagged   none
b_untagged   a_untagged
c_untagged   b_untagged
d_untagged   c_untagged b_untagged a_untagged
z_untagged   a_untagged b_untagged c_untagged d_untagged

我知道这看起来很麻烦,但我们试图测试基本上 4 种组合:

Role config         Tasks config
-----------         ------------
Role IS tagged      Tasks are NOT tagged
Role IS tagged      Tasks ARE tagged
Role is NOT tagged  Tasks are NOT tagged
Role is NOT tagged  Tasks ARE tagged

每个角色任务/main.yml看起来像这样 - 在这个示例角色中“b_tagged“只有一个任务,并且该任务标记为”标签: b

./角色/b_tagged/任务/main.yml

---
- debug: msg="Role B tagged"
  tags: b

以及相关meta/main.yml像这样,所以角色b_tagged取决于角色标记

./角色/b_tagged/meta/main.yml

---
dependencies:
  - { role: a_tagged }

相应的b_untagged风格任务相同,但没有“标签:" 任务中的行。

期望的结果是角色按顺序执行A B C D每个只运行一次,如下所示:

    "msg": "Role A ..."
    "msg": "Role B ..."
    "msg": "Role C ..."
    "msg": "Role D ..."

为了提供仅显示调试消息的最小输出:输出,脚本“测试文件“只需运行 ansible-playbook 如下。无论你在哪里看到测试文件它只是运行这个命令。

ANSIBLE_STDOUT_CALLBACK=minimal ansible-playbook -i hosts test.yml $@ -- | egrep -v "{|}"

演出主要有 4 种场景……

  • 运行每个剧中的每个角色,默认典型用途 ./test.sh

  • 运行每个剧集中的每个角色,使用“z”标签选择每个角色/任务。请记住,“z”角色只是将所有其他角色作为依赖项 ./test.sh --tags 'z'

  • 仅为带有“c”标签的角色/任务运行每个剧本,这应该只运行角色ABC ./test.sh --tags 'c'

  • 仅为“b”和“c”标记的角色/任务运行每个剧本,这应该只运行角色ABC ./test.sh --tags 'b,c'

剧本文件中的每个剧本测试文件采用以下形式:(这是第一个)

./测试.yml

###########################################################################################
# roles with NO tags and tasks WITH tags, roles defined in reverse order from dependencies.
- hosts: localhost
  gather_facts: false
  become: no

  pre_tasks:
    - debug:
        msg: "=============== untagged roles z d c b a tagged tasks reverse ========"
      tags: always

  roles:
    - role: z_tagged
    - role: d_tagged
    - role: c_tagged
    - role: b_tagged
    - role: a_tagged
###########################################################################################

由于每个剧本只有角色定义会发生变化(并且信息:字符串)这就是这里列出的其他剧目测试文件剧本文件

* roles with NO tags and tasks with NO tags, roles defined in reverse order from dependencies
    - role: z_untagged
    - role: d_untagged
    - role: c_untagged
    - role: b_untagged
    - role: a_untagged

* roles WITH tags and tasks WITH tags, roles defined in correct order from dependencies
    - { role: a_tagged, tags: a }
    - { role: b_tagged, tags: b }
    - { role: c_tagged, tags: c }
    - { role: d_tagged, tags: d }
    - { role: z_tagged, tags: z }

* roles WITH tags and tasks WITH tags, roles defined in reverse order from dependencies
    - { role: z_tagged, tags: z }
    - { role: d_tagged, tags: d }
    - { role: c_tagged, tags: c }
    - { role: b_tagged, tags: b }
    - { role: a_tagged, tags: a }

* roles WITH tags and tasks with NO tags, roles defined in correct order from dependencies
    - { role: a_untagged, tags: a }
    - { role: b_untagged, tags: b }
    - { role: c_untagged, tags: c }
    - { role: d_untagged, tags: d }
    - { role: z_untagged, tags: z }

* roles WITH tags and tasks with NO tags, roles defined in reverse order from dependencies
    - { role: z_untagged, tags: z }
    - { role: d_untagged, tags: d }
    - { role: c_untagged, tags: c }
    - { role: b_untagged, tags: b }
    - { role: a_untagged, tags: a }

运行上述 4 种场景会产生以下输出。

./test.sh 无论各个任务是否被标记,(只要角色没有标记)都会产生正确的输出(前两个场景)。如果角色有标签,则角色会多次出现(如接下来的 4 个剧本中所示),顺序取决于它们在剧本中定义的顺序。

正确的示例- role: a_tagged- role: a_untagged角色顺序并不重要

"msg": "=============== untagged roles z d c b a tagged tasks reverse ========"
"msg": "Role A tagged"
"msg": "Role B tagged"
"msg": "Role C tagged"
"msg": "Role D tagged"
"msg": "=============== untagged roles z d c b a untagged tasks reverse ======"
"msg": "Role A untagged"
"msg": "Role B untagged"
"msg": "Role C untagged"
"msg": "Role D untagged"
"msg": "=============== tagged roles a b c d z tagged tasks =================="
"msg": "Role A tagged"
"msg": "Role A tagged"
"msg": "Role B tagged"
"msg": "Role B tagged"
"msg": "Role C tagged"
"msg": "Role C tagged"
"msg": "Role D tagged"
"msg": "Role D tagged"
"msg": "=============== tagged roles z d c b a tagged tasks reverse =========="
"msg": "Role A tagged"
"msg": "Role B tagged"
"msg": "Role C tagged"
"msg": "Role D tagged"
"msg": "Role D tagged"
"msg": "Role C tagged"
"msg": "Role B tagged"
"msg": "Role A tagged"
"msg": "=============== tagged roles a b c d z untagged tasks ================"
"msg": "Role A untagged"
"msg": "Role A untagged"
"msg": "Role B untagged"
"msg": "Role B untagged"
"msg": "Role C untagged"
"msg": "Role C untagged"
"msg": "Role D untagged"
"msg": "Role D untagged"
"msg": "=============== tagged roles z d c b a untagged tasks reverse ========"
"msg": "Role A untagged"
"msg": "Role B untagged"
"msg": "Role C untagged"
"msg": "Role D untagged"
"msg": "Role D untagged"
"msg": "Role C untagged"
"msg": "Role B untagged"
"msg": "Role A untagged"

./test.sh --tags 'z' 使用时‘z’标签选择所有角色/任务,仅有的角色扮演的戏剧标签:在他们的定义中产生了正确的输出。如果角色没有被标记,那么该角色中的任务永远不会执行,不管它们是否被标记。

正确的示例- { role: a_tagged, tags: a }- { role: a_untagged, tags: a }角色顺序并不重要

"msg": "=============== untagged roles z d c b a tagged tasks reverse ========"
"msg": "=============== untagged roles z d c b a untagged tasks reverse ======"
"msg": "=============== tagged roles a b c d z tagged tasks =================="
"msg": "Role A tagged"
"msg": "Role B tagged"
"msg": "Role C tagged"
"msg": "Role D tagged"
"msg": "=============== tagged roles z d c b a tagged tasks reverse =========="
"msg": "Role A tagged"
"msg": "Role B tagged"
"msg": "Role C tagged"
"msg": "Role D tagged"
"msg": "=============== tagged roles a b c d z untagged tasks ================"
"msg": "Role A untagged"
"msg": "Role B untagged"
"msg": "Role C untagged"
"msg": "Role D untagged"
"msg": "=============== tagged roles z d c b a untagged tasks reverse ========"
"msg": "Role A untagged"
"msg": "Role B untagged"
"msg": "Role C untagged"
"msg": "Role D untagged"

./test.sh --tags 'c' 仅运行选定的角色(及其依赖项),唯一正确的输出是标记角色和任务不是标记(最后两次播放)。

正确示例- { role: a_untagged, tags: a }角色顺序并不重要

"msg": "=============== untagged roles z d c b a tagged tasks reverse ========"
"msg": "Role C tagged"
"msg": "=============== untagged roles z d c b a untagged tasks reverse ======"
"msg": "=============== tagged roles a b c d z tagged tasks =================="
"msg": "Role A tagged"
"msg": "Role B tagged"
"msg": "Role C tagged"
"msg": "Role C tagged"
"msg": "=============== tagged roles z d c b a tagged tasks reverse =========="
"msg": "Role C tagged"
"msg": "Role A tagged"
"msg": "Role B tagged"
"msg": "Role C tagged"
"msg": "=============== tagged roles a b c d z untagged tasks ================"
"msg": "Role A untagged"
"msg": "Role B untagged"
"msg": "Role C untagged"
"msg": "=============== tagged roles z d c b a untagged tasks reverse ========"
"msg": "Role A untagged"
"msg": "Role B untagged"
"msg": "Role C untagged"

./test.sh --tags 'b,c' 仅运行两个选定的角色(及其依赖项)正确的输出。

笔记: 没有任何配置产生运行公正角色所需的结果“AB C”

    "msg": "=============== untagged roles z d c b a tagged tasks reverse ========"
    "msg": "Role B tagged"
    "msg": "Role C tagged"
    "msg": "=============== untagged roles z d c b a untagged tasks reverse ======"
    "msg": "=============== tagged roles a b c d z tagged tasks =================="
    "msg": "Role A tagged"
    "msg": "Role B tagged"
    "msg": "Role B tagged"
    "msg": "Role C tagged"
    "msg": "Role C tagged"
    "msg": "=============== tagged roles z d c b a tagged tasks reverse =========="
    "msg": "Role B tagged"
    "msg": "Role C tagged"
    "msg": "Role A tagged"
    "msg": "Role C tagged"
    "msg": "Role B tagged"
    "msg": "=============== tagged roles a b c d z untagged tasks ================"
    "msg": "Role A untagged"
    "msg": "Role B untagged"
    "msg": "Role B untagged"
    "msg": "Role C untagged"
    "msg": "=============== tagged roles z d c b a untagged tasks reverse ========"
    "msg": "Role A untagged"
    "msg": "Role B untagged"
    "msg": "Role C untagged"
    "msg": "Role B untagged"

结论...仅有的处理具有依赖关系的两种场景(运行整个剧本(所有角色)或仅运行部分角色)的方法是确保用于选择的标签是仅有的在角色定义中,不是任务本身。例如:

    - { role: a_untagged, tags: a }

任务上的任何标签都应该只针对任务,不是对于任何角色选择。即便如此,这只适用于通过以下方式选择单个角色/标签的情况--标签‘c’运行,并失败多次通过--标签‘b,c’ 正如最后一个例子所示。

在里面测试文件playbook 文件中,这是最后两个剧本(角色顺序无关紧要)。所有其他变体都不会产生正确的结果。似乎没有理由标签:在任务本身上,至少如果您希望角色/任务选择具有依赖性并且不需要多次执行。

答案1

我没有一个确切的答案给你,但是“不要再把 Ansible 像木偶一样握在手里” ;-)

我可以想象这种依赖关系的必要性,但您可能还想考虑一下:我可以自己管理依赖关系吗?

我经历过几乎相同的情况:一个加载角色logstash和的剧本tomcat。两者都需要角色java。我们的 Java 角色也有一个元依赖关系。因此,角色java将在主机推出时执行两次(也是我们的 java 角色的依赖关系)。

---
- hosts: myhost
  roles:
    - role: logstash
    - role: tomcat8

我们通过如下方式解决了这个问题:

---
- hosts: myhost
  roles:
    - role: java
    - role: logstash
    - role: tomcat8

java从角色logstash和中删除角色的依赖关系tomcat。这样,java get 在 playbook 运行中只会推出一次。

当您了解并自行控制工具并希望保持其简单而不是复杂时,此解决方案可能会有所帮助。

相关内容