ansiblebatchsize

Controlling Ansible playbook execution


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.


Solution

  • 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
    
    1. Declare the variables
      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
    
    1. zip and flatten the batches
      my_hosts: "{{ batch_1|
                    zip_longest(batch_2)|map('flatten')|
                    zip_longest(batch_3)|map('flatten')|flatten }}"
    
    1. Create a new group my_group
            - add_host:
                name: "{{ item }}"
                groups: my_group
                my_serial: "{{ my_serial }}"
              loop: "{{ my_hosts }}"
    
    1. Run the next play with the group my_group and serial my_serial
    - 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