我有一本类似这样的剧本:
---
- hosts: group1
roles:
- role1
- role2
- hosts: group2
roles:
- role2
- role3
现在假设我有一个 hosts 文件,其中有如下条目:
[group1]
host1.example.com
[group2]
host1.example.com
Ansible 将为 host1.example.com 运行两次 role2 中的任务,因为它出现在 2 个组中,并且每个组都分配了 role2。
我怎样才能让 Ansible 意识到它包含了两次相同的角色,因此它应该只运行一次?
答案1
如上所述,这是设计使然。Ansible 一次只执行一个剧本。您的剧本由两个剧本组成(剧本文件定义的根级 YAML 列表中的两个项目)。第一个剧本将 role1 和 role2 应用于 group1。该剧本首先执行,并且只有在完成后,第二个剧本才会开始。但 Ansible 不会尝试在逻辑上将这些剧本合并在一起。毕竟,您可能实际上希望 role2 中的任务运行两次。
至于解决这个问题,有几种方法可以解决这个问题,而选择哪种方法将取决于群组和角色的详细信息。
如果角色 2 中的所有任务都是幂等的,即如果它们可以多次运行并且每次都得到相同的结果,那么您真正浪费的只是时间,让角色重复是可以的。如果角色需要很长时间才能应用,或者您无法使其幂等,请考虑以下想法:
你可以将剧本分成三个部分,并分别应用角色:
---
- hosts: group1
roles:
- role1
- hosts: group1:group2
roles:
- role2
- hosts: group2
roles:
- role3
或者,如果您的角色需要分组在一起,您可以为需要所有三个角色的服务器创建第三个组。您不需要将它们从其他两个组中取出。您可以在清单文件中像这样创建组:
[group1and2:children]
group1
group2
然后,您可以在剧本中再次分成三个剧本,但使用第三组来避免重复角色:
---
- hosts: group1:!group1and2
roles:
- role1
- role2
- hosts: group1and2
roles:
- role1
- role2
- role3
- hosts: group2:!group1and2
roles:
- role2
- role3
这很丑陋,但在某些情况下可能会有用。
答案2
这是设计使然。唯一的办法是仅在一个剧本中将 role2 应用于一个特定组,而不是在可能有共同成员的组的任何其他剧本中使用 role2,就像这里一样。