与当作为依赖项列出时,如何防止ansible角色多次运行?相关
这是一个很长的问题。TL;DR -设置角色和任务标记的正确方法是什么,这样依赖关系就可以正常工作,而无需多次运行角色。
我在让剧本很好地处理标签和依赖关系方面遇到了一些困难。一般来说,我想要一本有很多角色的剧本(每个角色都有一些依赖项)来“干净地工作”。这本身就相当容易设置,并且在使用整个剧本中的所有角色时工作得很好。具有依赖关系的角色可以按剧本中的任意顺序定义,这些依赖关系确保它们按照正确的顺序运行。当然,没有依赖项的角色将按照它们在剧本角色:部分中出现的顺序运行。
但有时人们只想运行角色的一个子集,然后就会分崩离析,有些角色会多次运行,顺序也会很奇怪。
因此,我构建了一个测试设置,包含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“
---
- debug: msg="Role B tagged"
tags: b并且相关的meta/main.yml如下所示,因此角色b_tagged依赖于角色a_tagged:
---
dependencies:
- { role: a_tagged }相应的b_untagged样式任务是相同的,但没有任务中的“标记:”行。
期望的结果是角色按照A、B、C、D的顺序执行,每个角色只运行一次,如下所示:
"msg": "Role A ..."
"msg": "Role B ..."
"msg": "Role C ..."
"msg": "Role D ..."为了提供仅显示调试msg:输出的最小输出,脚本"test.sh“只运行,如下所示。无论您在哪里看到test.sh,它都只是运行这个命令。
ANSIBLE_STDOUT_CALLBACK=minimal ansible-playbook -i hosts test.yml $@ -- | egrep -v "{|}"
有四种主要的方案来运行这些剧本..。
./test.sh./test.sh --tags 'z'./test.sh --tags 'c'./test.sh --tags 'b,c'剧本文件test.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
###########################################################################################因为只有角色定义改变了每个剧本(和msg: string),这就是这里列出的test.yml剧本文件中其他剧本的全部内容
* 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'只运行两个选定的角色(以及它们的依赖项),没有正确的输出。
所需的结果
"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’的情况下失败。
在test.yml剧本文件中,这是最后两个剧本(角色顺序不重要)。所有其他变体都不会产生正确的结果。似乎没有理由使用标记:在任务本身上,至少如果您希望角色/任务选择能够处理依赖关系,而不需要多次执行的话。
发布于 2019-11-19 15:09:14
我没有确切的答案给你,但是“不要像木偶一样抱着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只在运行剧本时推出一次。
当您知道和控制您自己的工具并且希望保持它简单,而不是复杂时,这个解决方案可能会有所帮助。
https://serverfault.com/questions/991605
复制相似问题