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 运行中只会推出一次。
当您了解并自行控制工具并希望保持其简单而不是复杂时,此解决方案可能会有所帮助。