使用 ansible 与多个组和服务器一起玩和执行任务
Play and task execution with multiple groups and servers with ansible
我们有这个包含数十台服务器的 Ansible 清单,每个微服务都按服务器分组。假设我们在清单中有几个应用程序组,其中包含服务器。
说:
[group1]
server1
server2
server3
server20
server27
server38
[group2]
server4
server5
[group3]
server7
server8
server9
server6
此库存已用于数十次播放,因此不能仅更改它。我需要处理这个设置。
我需要知道是否有可能以某种方式在每个组的一台服务器上并行进行游戏 运行 而无需在游戏中明确命名它们? (群组和服务器可以由其他人添加,我需要玩才能应付)
因此,当播放开始时,它可能会在服务器 1、服务器 4 和服务器 7 上并行处理。 server2 的处理可能会在 server1 完成时开始,server5 的处理可能会在 server4 完成时开始,等等。我猜你明白我的意思了。这意味着,一开始,每个组中的一个服务器都会被处理,但是随着时间的推移,较小的组将完成 运行 秒,而在较大的组中,处理仍然会发生。
有什么方法可以实现吗?
蒂亚
这里已经有关于如何 运行 多个主机上的剧本的答案Ansible: deploy on multiple hosts in the same time
也许你可以从那里开始。但是,如果 运行 只对第一台并行服务器感兴趣,那么这将更加困难,因为它需要编写自定义脚本或类似的东西
问:"运行 在每个组中的 1 个服务器上并行处理...在 server1、server4 和 server7 上并行处理。可能会在 server2 上开始处理当 server1 完成时,server5 的处理可能会在 server4 完成时开始,等等......在编写代码时迭代一些未知的组和服务器。"
答:作为不完整的提示,下面的剧本
- hosts: all
gather_facts: false
vars:
_groups: "{{ groups.keys()|difference(['all', 'ungrouped']) }}"
# _hosts: [0, 1, 2] # Range of minimal common leght perhaps?
_groups_len_min: "{{ _groups|map('extract', groups)|map('length')|min }}"
_hosts: "{{ range(_groups_len_min|int) }}"
my_hosts: "{{ query('cartesian', _hosts, _groups) }}"
tasks:
- add_host:
name: "{{ groups[item.1][item.0] }}"
groups: my_group
loop: "{{ my_hosts }}"
run_once: true
- hosts: my_group
gather_facts: false
serial: 3 # TODO: Number of the groups involved
order: inventory
tasks:
- debug:
var: inventory_hostname
给予
PLAY [my_group] ***************************************************
TASK [debug] ******************************************************
ok: [server4] =>
inventory_hostname: server4
ok: [server1] =>
inventory_hostname: server1
ok: [server7] =>
inventory_hostname: server7
PLAY [my_group] ***************************************************
TASK [debug] ******************************************************
ok: [server2] =>
inventory_hostname: server2
ok: [server5] =>
inventory_hostname: server5
ok: [server8] =>
inventory_hostname: server8
PLAY [my_group] ***************************************************
TASK [debug] ******************************************************
ok: [server6] =>
inventory_hostname: server6
ok: [server3] =>
inventory_hostname: server3
ok: [server9] =>
inventory_hostname: server9
如果您想包括所有主机,请使用 dummies 填充缺少的主机,例如给定库存
shell> cat hosts
[group1]
server1
server2
server3
[group2]
server4
server5
[group3]
server7
剧本
- hosts: all
gather_facts: false
vars:
_groups: "{{ groups.keys()|difference(['all', 'ungrouped']) }}"
_groups_len_max: "{{ _groups|map('extract', groups)|map('length')|max }}"
_hosts: "{{ range(_groups_len_max|int) }}"
my_hosts: "{{ query('cartesian', _hosts, _groups) }}"
tasks:
- add_host:
name: "{{ groups[item.1][item.0]|default('dummy-' ~ ansible_loop.index) }}"
groups: my_group
loop: "{{ my_hosts }}"
loop_control:
extended: true
run_once: true
- hosts: my_group
gather_facts: false
serial: 3 # TODO: Number of the groups involved
order: inventory
tasks:
- name: Proceed if not dummy
block:
- debug:
var: inventory_hostname
when: inventory_hostname is not match('^dummy-\d*$')
给予
PLAY [my_group] *****************************************************
TASK [debug] ********************************************************
ok: [server1] =>
inventory_hostname: server1
ok: [server4] =>
inventory_hostname: server4
ok: [server7] =>
inventory_hostname: server7
PLAY [my_group] *****************************************************
TASK [debug] ********************************************************
skipping: [dummy-6]
ok: [server2] =>
inventory_hostname: server2
ok: [server5] =>
inventory_hostname: server5
PLAY [my_group] *****************************************************
TASK [debug] ********************************************************
ok: [server3] =>
inventory_hostname: server3
skipping: [dummy-8]
skipping: [dummy-9]
注释
一个简单的选择是创建动态组,例如
- hosts: all
gather_facts: false
vars:
my_groups:
my_group1: [[group1,0], [group2,0], [group3,0]]
my_group2: [[group1,1], [group2,1], [group3,1]]
my_group3: [[group1,2], [group2,2], [group3,2]]
tasks:
- add_host:
name: "{{ groups[item.1.0][item.1.1] }}"
groups: "{{ item.0.key }}"
with_subelements:
- "{{ my_groups|dict2items }}"
- value
run_once: true
- hosts: my_group1
gather_facts: false
tasks:
- debug:
var: inventory_hostname
- hosts: my_group2
gather_facts: false
tasks:
- debug:
var: inventory_hostname
- hosts: my_group3
gather_facts: false
tasks:
- debug:
var: inventory_hostname
给出(删节)
PLAY [my_group1] *******************************************************
TASK [debug] ***********************************************************
ok: [server1] =>
inventory_hostname: server1
ok: [server7] =>
inventory_hostname: server7
ok: [server4] =>
inventory_hostname: server4
PLAY [my_group2] *******************************************************
TASK [debug] ***********************************************************
ok: [server5] =>
inventory_hostname: server5
ok: [server2] =>
inventory_hostname: server2
ok: [server8] =>
inventory_hostname: server8
PLAY [my_group3] *******************************************************
TASK [debug] ***********************************************************
ok: [server3] =>
inventory_hostname: server3
ok: [server6] =>
inventory_hostname: server6
ok: [server9] =>
inventory_hostname: server9
下一个选项是创建一个具有所需主机顺序的组并设置 serial and order,例如
- hosts: all
gather_facts: false
vars:
my_groups:
my_group1: [[group1,0], [group2,0], [group3,0]]
my_group2: [[group1,1], [group2,1], [group3,1]]
my_group3: [[group1,2], [group2,2], [group3,2]]
tasks:
- add_host:
name: "{{ groups[item.1.0][item.1.1] }}"
groups: my_group
with_subelements:
- "{{ my_groups|dict2items }}"
- value
run_once: true
- hosts: my_group
gather_facts: false
serial: 3
order: inventory
tasks:
- debug:
var: inventory_hostname
给出(删节)
PLAY [my_group] ****************************************************
TASK [debug] *******************************************************
ok: [server1] =>
inventory_hostname: server1
ok: [server7] =>
inventory_hostname: server7
ok: [server4] =>
inventory_hostname: server4
PLAY [my_group] ****************************************************
TASK [debug] *******************************************************
ok: [server2] =>
inventory_hostname: server2
ok: [server5] =>
inventory_hostname: server5
ok: [server8] =>
inventory_hostname: server8
PLAY [my_group] ****************************************************
TASK [debug] *******************************************************
ok: [server3] =>
inventory_hostname: server3
ok: [server6] =>
inventory_hostname: server6
ok: [server9] =>
inventory_hostname: server9
为了避免手动编写大型矩阵的繁琐工作,可以动态创建结构,例如下面的剧本创建了相同的动态组
- hosts: all
gather_facts: false
vars:
_groups: [group1, group2, group3]
_hosts: [0, 1, 2]
_dgroups: [my_group1, my_group2, my_group3]
_groups_hosts: "{{ query('cartesian', _hosts, _groups)|
batch(_dgroups|length) }}"
my_groups: "{{ dict(_dgroups|zip(_groups_hosts)) }}"
tasks:
- add_host:
name: "{{ groups[item.1.1][item.1.0] }}"
groups: my_group
with_subelements:
- "{{ my_groups|dict2items }}"
- value
run_once: true
我们有这个包含数十台服务器的 Ansible 清单,每个微服务都按服务器分组。假设我们在清单中有几个应用程序组,其中包含服务器。
说:
[group1]
server1
server2
server3
server20
server27
server38
[group2]
server4
server5
[group3]
server7
server8
server9
server6
此库存已用于数十次播放,因此不能仅更改它。我需要处理这个设置。
我需要知道是否有可能以某种方式在每个组的一台服务器上并行进行游戏 运行 而无需在游戏中明确命名它们? (群组和服务器可以由其他人添加,我需要玩才能应付)
因此,当播放开始时,它可能会在服务器 1、服务器 4 和服务器 7 上并行处理。 server2 的处理可能会在 server1 完成时开始,server5 的处理可能会在 server4 完成时开始,等等。我猜你明白我的意思了。这意味着,一开始,每个组中的一个服务器都会被处理,但是随着时间的推移,较小的组将完成 运行 秒,而在较大的组中,处理仍然会发生。
有什么方法可以实现吗?
蒂亚
这里已经有关于如何 运行 多个主机上的剧本的答案Ansible: deploy on multiple hosts in the same time
也许你可以从那里开始。但是,如果 运行 只对第一台并行服务器感兴趣,那么这将更加困难,因为它需要编写自定义脚本或类似的东西
问:"运行 在每个组中的 1 个服务器上并行处理...在 server1、server4 和 server7 上并行处理。可能会在 server2 上开始处理当 server1 完成时,server5 的处理可能会在 server4 完成时开始,等等......在编写代码时迭代一些未知的组和服务器。"
答:作为不完整的提示,下面的剧本
- hosts: all
gather_facts: false
vars:
_groups: "{{ groups.keys()|difference(['all', 'ungrouped']) }}"
# _hosts: [0, 1, 2] # Range of minimal common leght perhaps?
_groups_len_min: "{{ _groups|map('extract', groups)|map('length')|min }}"
_hosts: "{{ range(_groups_len_min|int) }}"
my_hosts: "{{ query('cartesian', _hosts, _groups) }}"
tasks:
- add_host:
name: "{{ groups[item.1][item.0] }}"
groups: my_group
loop: "{{ my_hosts }}"
run_once: true
- hosts: my_group
gather_facts: false
serial: 3 # TODO: Number of the groups involved
order: inventory
tasks:
- debug:
var: inventory_hostname
给予
PLAY [my_group] ***************************************************
TASK [debug] ******************************************************
ok: [server4] =>
inventory_hostname: server4
ok: [server1] =>
inventory_hostname: server1
ok: [server7] =>
inventory_hostname: server7
PLAY [my_group] ***************************************************
TASK [debug] ******************************************************
ok: [server2] =>
inventory_hostname: server2
ok: [server5] =>
inventory_hostname: server5
ok: [server8] =>
inventory_hostname: server8
PLAY [my_group] ***************************************************
TASK [debug] ******************************************************
ok: [server6] =>
inventory_hostname: server6
ok: [server3] =>
inventory_hostname: server3
ok: [server9] =>
inventory_hostname: server9
如果您想包括所有主机,请使用 dummies 填充缺少的主机,例如给定库存
shell> cat hosts
[group1]
server1
server2
server3
[group2]
server4
server5
[group3]
server7
剧本
- hosts: all
gather_facts: false
vars:
_groups: "{{ groups.keys()|difference(['all', 'ungrouped']) }}"
_groups_len_max: "{{ _groups|map('extract', groups)|map('length')|max }}"
_hosts: "{{ range(_groups_len_max|int) }}"
my_hosts: "{{ query('cartesian', _hosts, _groups) }}"
tasks:
- add_host:
name: "{{ groups[item.1][item.0]|default('dummy-' ~ ansible_loop.index) }}"
groups: my_group
loop: "{{ my_hosts }}"
loop_control:
extended: true
run_once: true
- hosts: my_group
gather_facts: false
serial: 3 # TODO: Number of the groups involved
order: inventory
tasks:
- name: Proceed if not dummy
block:
- debug:
var: inventory_hostname
when: inventory_hostname is not match('^dummy-\d*$')
给予
PLAY [my_group] *****************************************************
TASK [debug] ********************************************************
ok: [server1] =>
inventory_hostname: server1
ok: [server4] =>
inventory_hostname: server4
ok: [server7] =>
inventory_hostname: server7
PLAY [my_group] *****************************************************
TASK [debug] ********************************************************
skipping: [dummy-6]
ok: [server2] =>
inventory_hostname: server2
ok: [server5] =>
inventory_hostname: server5
PLAY [my_group] *****************************************************
TASK [debug] ********************************************************
ok: [server3] =>
inventory_hostname: server3
skipping: [dummy-8]
skipping: [dummy-9]
注释
一个简单的选择是创建动态组,例如
- hosts: all
gather_facts: false
vars:
my_groups:
my_group1: [[group1,0], [group2,0], [group3,0]]
my_group2: [[group1,1], [group2,1], [group3,1]]
my_group3: [[group1,2], [group2,2], [group3,2]]
tasks:
- add_host:
name: "{{ groups[item.1.0][item.1.1] }}"
groups: "{{ item.0.key }}"
with_subelements:
- "{{ my_groups|dict2items }}"
- value
run_once: true
- hosts: my_group1
gather_facts: false
tasks:
- debug:
var: inventory_hostname
- hosts: my_group2
gather_facts: false
tasks:
- debug:
var: inventory_hostname
- hosts: my_group3
gather_facts: false
tasks:
- debug:
var: inventory_hostname
给出(删节)
PLAY [my_group1] *******************************************************
TASK [debug] ***********************************************************
ok: [server1] =>
inventory_hostname: server1
ok: [server7] =>
inventory_hostname: server7
ok: [server4] =>
inventory_hostname: server4
PLAY [my_group2] *******************************************************
TASK [debug] ***********************************************************
ok: [server5] =>
inventory_hostname: server5
ok: [server2] =>
inventory_hostname: server2
ok: [server8] =>
inventory_hostname: server8
PLAY [my_group3] *******************************************************
TASK [debug] ***********************************************************
ok: [server3] =>
inventory_hostname: server3
ok: [server6] =>
inventory_hostname: server6
ok: [server9] =>
inventory_hostname: server9
下一个选项是创建一个具有所需主机顺序的组并设置 serial and order,例如
- hosts: all
gather_facts: false
vars:
my_groups:
my_group1: [[group1,0], [group2,0], [group3,0]]
my_group2: [[group1,1], [group2,1], [group3,1]]
my_group3: [[group1,2], [group2,2], [group3,2]]
tasks:
- add_host:
name: "{{ groups[item.1.0][item.1.1] }}"
groups: my_group
with_subelements:
- "{{ my_groups|dict2items }}"
- value
run_once: true
- hosts: my_group
gather_facts: false
serial: 3
order: inventory
tasks:
- debug:
var: inventory_hostname
给出(删节)
PLAY [my_group] ****************************************************
TASK [debug] *******************************************************
ok: [server1] =>
inventory_hostname: server1
ok: [server7] =>
inventory_hostname: server7
ok: [server4] =>
inventory_hostname: server4
PLAY [my_group] ****************************************************
TASK [debug] *******************************************************
ok: [server2] =>
inventory_hostname: server2
ok: [server5] =>
inventory_hostname: server5
ok: [server8] =>
inventory_hostname: server8
PLAY [my_group] ****************************************************
TASK [debug] *******************************************************
ok: [server3] =>
inventory_hostname: server3
ok: [server6] =>
inventory_hostname: server6
ok: [server9] =>
inventory_hostname: server9
为了避免手动编写大型矩阵的繁琐工作,可以动态创建结构,例如下面的剧本创建了相同的动态组
- hosts: all
gather_facts: false
vars:
_groups: [group1, group2, group3]
_hosts: [0, 1, 2]
_dgroups: [my_group1, my_group2, my_group3]
_groups_hosts: "{{ query('cartesian', _hosts, _groups)|
batch(_dgroups|length) }}"
my_groups: "{{ dict(_dgroups|zip(_groups_hosts)) }}"
tasks:
- add_host:
name: "{{ groups[item.1.1][item.1.0] }}"
groups: my_group
with_subelements:
- "{{ my_groups|dict2items }}"
- value
run_once: true