运行 每个唯一的事实值仅执行一次 ansible 任务
Run ansible task only once per each unique fact value
我有一个动态清单,它为每个主机分配一个 "fact",称为 'cluster_number'。
事先不知道集群编号,但有一台或多台主机分配了相同的编号。清单有数百台主机和 2-3 打唯一的集群编号。
我想 运行 为清单中的所有主机执行任务,但是我只想对共享相同 'cluster_number' 值的每组主机执行一次。每个组选择哪个具体主机并不重要。
我觉得应该有一个相对直接的方法来使用 ansible 来做到这一点,但不知道如何做。我看过 group_by、when、loop、delegate_to 等。但还没有成功。
一个选项是
例如给定 hosts
[test]
test01 cluster_number='1'
test02 cluster_number='1'
test03 cluster_number='1'
test04 cluster_number='1'
test05 cluster_number='1'
test06 cluster_number='2'
test07 cluster_number='2'
test08 cluster_number='2'
test09 cluster_number='3'
test10 cluster_number='3'
[test:vars]
cluster_numbers=['1','2','3']
以下剧本
- hosts: all
gather_facts: no
tasks:
- group_by: key=cluster_{{ cluster_number }}
- debug: var=groups['cluster_{{ item }}'][0]
loop: "{{ cluster_numbers }}"
run_once: true
给予
> ansible-playbook test.yml | grep groups
"groups['cluster_1'][0]": "test01",
"groups['cluster_2'][0]": "test06",
"groups['cluster_3'][0]": "test09",
在目标执行任务include_tasks (instead of debug in the loop above) and delegate_to目标
- set_fact:
my_group: "cluster_{{ item }}"
- command: hostname
delegate_to: "{{ groups[my_group][0] }}"
注意:从库存中收集列表cluster_numbers
cluster_numbers: "{{ hostvars|json_query('*.cluster_number')|unique }}"
如果你不介意播放日志混乱,这里有一个方法:
- hosts: all
gather_facts: no
serial: 1
tasks:
- group_by:
key: "single_{{ cluster_number }}"
when: groups['single_'+cluster_number] | default([]) | count == 0
- hosts: single_*
gather_facts: no
tasks:
- debug:
msg: "{{ inventory_hostname }}"
serial: 1
在第一场比赛中对每个主机重新评估 when
声明至关重要。
第一次玩后,每个集群都有 N 个组,其中只有一个主机。
我有一个动态清单,它为每个主机分配一个 "fact",称为 'cluster_number'。
事先不知道集群编号,但有一台或多台主机分配了相同的编号。清单有数百台主机和 2-3 打唯一的集群编号。
我想 运行 为清单中的所有主机执行任务,但是我只想对共享相同 'cluster_number' 值的每组主机执行一次。每个组选择哪个具体主机并不重要。
我觉得应该有一个相对直接的方法来使用 ansible 来做到这一点,但不知道如何做。我看过 group_by、when、loop、delegate_to 等。但还没有成功。
一个选项是
例如给定 hosts
[test]
test01 cluster_number='1'
test02 cluster_number='1'
test03 cluster_number='1'
test04 cluster_number='1'
test05 cluster_number='1'
test06 cluster_number='2'
test07 cluster_number='2'
test08 cluster_number='2'
test09 cluster_number='3'
test10 cluster_number='3'
[test:vars]
cluster_numbers=['1','2','3']
以下剧本
- hosts: all
gather_facts: no
tasks:
- group_by: key=cluster_{{ cluster_number }}
- debug: var=groups['cluster_{{ item }}'][0]
loop: "{{ cluster_numbers }}"
run_once: true
给予
> ansible-playbook test.yml | grep groups
"groups['cluster_1'][0]": "test01",
"groups['cluster_2'][0]": "test06",
"groups['cluster_3'][0]": "test09",
在目标执行任务include_tasks (instead of debug in the loop above) and delegate_to目标
- set_fact:
my_group: "cluster_{{ item }}"
- command: hostname
delegate_to: "{{ groups[my_group][0] }}"
注意:从库存中收集列表cluster_numbers
cluster_numbers: "{{ hostvars|json_query('*.cluster_number')|unique }}"
如果你不介意播放日志混乱,这里有一个方法:
- hosts: all
gather_facts: no
serial: 1
tasks:
- group_by:
key: "single_{{ cluster_number }}"
when: groups['single_'+cluster_number] | default([]) | count == 0
- hosts: single_*
gather_facts: no
tasks:
- debug:
msg: "{{ inventory_hostname }}"
serial: 1
在第一场比赛中对每个主机重新评估 when
声明至关重要。
第一次玩后,每个集群都有 N 个组,其中只有一个主机。