Is it possible to control batch execution in percentage, but applying it individually to groups of hosts in the Ansible playbook?
my hosts file:
group_1 - has 5 hosts
group_2 - has 18 hosts
group_3 - has 4 hosts
And my playbook like this:
- name: "Apply percent per group"
hosts: all
serial: "30%"
Currently, when I run like this, Ansible concatenate all groups and applies the 30% serial, so it runs 8 hosts per round and linearly, so it ends up getting all the hosts in group_1 at once.
Is there a way to apply this 30% per group individually?
So per batch it would run 1 host from group_1, 5 hosts from group_2 and 1 host from group_3.
It would even give me the possibility to increase the percentage that would still not cause unavailability and decrease execution time.
Create the batch on your own. For example, given the inventory
shell> cat hosts
[group_1]
host_1_[01:05]
[group_2]
host_2_[01:18]
[group_3]
host_3_[01:04]
and the variable my_serial_pc
my_serial_pc: 30
count_1: "{{ groups.group_1|length * my_serial_pc|int // 100 }}"
count_2: "{{ groups.group_2|length * my_serial_pc|int // 100 }}"
count_3: "{{ groups.group_3|length * my_serial_pc|int // 100 }}"
batch_1: "{{ groups.group_1|batch(count_1|int) }}"
batch_2: "{{ groups.group_2|batch(count_2|int) }}"
batch_3: "{{ groups.group_3|batch(count_3|int) }}"
my_serial: "{{ count_1|int + count_2|int + count_3|int }}"
give
count_1: 1
count_2: 5
count_3: 1
batch_1:
- [host_1_01]
- [host_1_02]
- [host_1_03]
- [host_1_04]
- [host_1_05]
batch_2:
- [host_2_01, host_2_02, host_2_03, host_2_04, host_2_05]
- [host_2_06, host_2_07, host_2_08, host_2_09, host_2_10]
- [host_2_11, host_2_12, host_2_13, host_2_14, host_2_15]
- [host_2_16, host_2_17, host_2_18]
batch_3:
- [host_3_01]
- [host_3_02]
- [host_3_03]
- [host_3_04]
my_serial: 7
my_hosts: "{{ batch_1|
zip_longest(batch_2)|map('flatten')|
zip_longest(batch_3)|map('flatten')|flatten }}"
- add_host:
name: "{{ item }}"
groups: my_group
my_serial: "{{ my_serial }}"
loop: "{{ my_hosts }}"
- hosts: my_group
serial: "{{ hostvars[groups.my_group.0].my_serial }}"
tasks:
- debug:
var: ansible_play_batch|to_yaml
run_once: true
gives
PLAY [my_group] *******************************************************************************************
TASK [debug] **********************************************************************************************
ok: [host_1_01] =>
ansible_play_batch|to_yaml: |-
[host_1_01, host_2_01, host_2_02, host_2_03, host_2_04, host_2_05, host_3_01]
PLAY [my_group] *******************************************************************************************
TASK [debug] **********************************************************************************************
ok: [host_1_02] =>
ansible_play_batch|to_yaml: |-
[host_1_02, host_2_06, host_2_07, host_2_08, host_2_09, host_2_10, host_3_02]
PLAY [my_group] *******************************************************************************************
TASK [debug] **********************************************************************************************
ok: [host_1_03] =>
ansible_play_batch|to_yaml: |-
[host_1_03, host_2_11, host_2_12, host_2_13, host_2_14, host_2_15, host_3_03]
PLAY [my_group] *******************************************************************************************
TASK [debug] **********************************************************************************************
ok: [host_1_04] =>
ansible_play_batch|to_yaml: |-
[host_1_04, host_2_16, host_2_17, host_2_18, host_3_04, host_1_05]
Example of a complete playbook for testing
shell> cat pb.yml
- hosts: all
vars:
my_serial_pc: 30
count_1: "{{ groups.group_1|length * my_serial_pc|int // 100 }}"
count_2: "{{ groups.group_2|length * my_serial_pc|int // 100 }}"
count_3: "{{ groups.group_3|length * my_serial_pc|int // 100 }}"
batch_1: "{{ groups.group_1|batch(count_1|int) }}"
batch_2: "{{ groups.group_2|batch(count_2|int) }}"
batch_3: "{{ groups.group_3|batch(count_3|int) }}"
my_hosts: "{{ batch_1|
zip_longest(batch_2)|map('flatten')|
zip_longest(batch_3)|map('flatten')|flatten }}"
my_serial: "{{ count_1|int + count_2|int + count_3|int }}"
tasks:
- block:
- debug:
msg: |
count_1: {{ count_1 }}
count_2: {{ count_2 }}
count_3: {{ count_3 }}
batch_1:
{{ batch_1|to_yaml|indent(2) }}
batch_2:
{{ batch_2|to_yaml|indent(2) }}
batch_3:
{{ batch_3|to_yaml|indent(2) }}
my_serial: {{ my_serial }}
when: debug|d(false)|bool
- add_host:
name: "{{ item }}"
groups: my_group
my_serial: "{{ my_serial }}"
loop: "{{ my_hosts }}"
run_once: true
- hosts: my_group
serial: "{{ hostvars[groups.my_group.0].my_serial }}"
tasks:
- debug:
var: ansible_play_batch|to_yaml
run_once: true
gives
shell> ansible-playbook pb.yml -e debug=true
PLAY [all] ************************************************************************************************
TASK [debug] **********************************************************************************************
ok: [host_1_01] =>
msg: |-
count_1: 1
count_2: 5
count_3: 1
batch_1:
- [host_1_01]
- [host_1_02]
- [host_1_03]
- [host_1_04]
- [host_1_05]
batch_2:
- [host_2_01, host_2_02, host_2_03, host_2_04, host_2_05]
- [host_2_06, host_2_07, host_2_08, host_2_09, host_2_10]
- [host_2_11, host_2_12, host_2_13, host_2_14, host_2_15]
- [host_2_16, host_2_17, host_2_18]
batch_3:
- [host_3_01]
- [host_3_02]
- [host_3_03]
- [host_3_04]
my_serial: 7
TASK [add_host] *******************************************************************************************
changed: [host_1_01] => (item=host_1_01)
changed: [host_1_01] => (item=host_2_01)
changed: [host_1_01] => (item=host_2_02)
changed: [host_1_01] => (item=host_2_03)
changed: [host_1_01] => (item=host_2_04)
changed: [host_1_01] => (item=host_2_05)
changed: [host_1_01] => (item=host_3_01)
changed: [host_1_01] => (item=host_1_02)
changed: [host_1_01] => (item=host_2_06)
changed: [host_1_01] => (item=host_2_07)
changed: [host_1_01] => (item=host_2_08)
changed: [host_1_01] => (item=host_2_09)
changed: [host_1_01] => (item=host_2_10)
changed: [host_1_01] => (item=host_3_02)
changed: [host_1_01] => (item=host_1_03)
changed: [host_1_01] => (item=host_2_11)
changed: [host_1_01] => (item=host_2_12)
changed: [host_1_01] => (item=host_2_13)
changed: [host_1_01] => (item=host_2_14)
changed: [host_1_01] => (item=host_2_15)
changed: [host_1_01] => (item=host_3_03)
changed: [host_1_01] => (item=host_1_04)
changed: [host_1_01] => (item=host_2_16)
changed: [host_1_01] => (item=host_2_17)
changed: [host_1_01] => (item=host_2_18)
changed: [host_1_01] => (item=host_3_04)
changed: [host_1_01] => (item=host_1_05)
PLAY [my_group] *******************************************************************************************
TASK [debug] **********************************************************************************************
ok: [host_1_01] =>
ansible_play_batch|to_yaml: |-
[host_1_01, host_2_01, host_2_02, host_2_03, host_2_04, host_2_05, host_3_01]
PLAY [my_group] *******************************************************************************************
TASK [debug] **********************************************************************************************
ok: [host_1_02] =>
ansible_play_batch|to_yaml: |-
[host_1_02, host_2_06, host_2_07, host_2_08, host_2_09, host_2_10, host_3_02]
PLAY [my_group] *******************************************************************************************
TASK [debug] **********************************************************************************************
ok: [host_1_03] =>
ansible_play_batch|to_yaml: |-
[host_1_03, host_2_11, host_2_12, host_2_13, host_2_14, host_2_15, host_3_03]
PLAY [my_group] *******************************************************************************************
TASK [debug] **********************************************************************************************
ok: [host_1_04] =>
ansible_play_batch|to_yaml: |-
[host_1_04, host_2_16, host_2_17, host_2_18, host_3_04, host_1_05]
PLAY RECAP ************************************************************************************************
host_1_01: ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host_1_02: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host_1_03: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host_1_04: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0