Parallel execution of tasks in playbook

Hi Experts,
Can you please share the tips to improve the execution time of Ansible playbook by executing the tasks in parallel? Currently all tasks are executed in sequential manner and waiting for prior task to complete the execution. Is there anyway each ask can execute in parallel?

-Build admin

See this, async tasks, may be what you’re looking for

https://docs.ansible.com/ansible/2.5/user_guide/playbooks_async.html

I would look at the 'free' strategy, but you have others:

https://docs.ansible.com/ansible/latest/plugins/strategy.html#plugin-list

Thank you for your reply.
I tried using strategy as free and unable to use async in the task as task has dependency task. Could you please suggest code change or alternate method for running the task in parallel.

`

---
- name: Main playbook
  gather_facts: no
  hosts: 127.0.0.1
  strategy: free

  tasks:
    - name: Create csv file and html file
      file:
        path: "{{ item }}"
        state: touch
      delegae_to: localhost
      become_user: awx
      become: no
      with_items:
        - /tmp/apache.csv
        - /tmp/apache.html

    - include_vars: apache_sever_list.yaml

    - include_tasks: apache_task.yaml
      with_items: '{{ apacheSevers }}'

    - name: Run the csv2html script
      shell: |
        echo "<h3>List of failed Apache servers</h3>"
        echo "<table>" ;
        echo "<table><tr><th>Hostname</th><th>Port</th></tr>"
        while read INPUT; do
        echo "<tr><td>${INPUT//,/</td><td>}</td></tr>";
        done < /tmp/apache.csv
        echo "</table>"
      delegae_to: localhost
      become_user: awx
      become: no        

    - name: append
      lineinfile:
        dest: /tmp/apache.html
        line: "{{ output.stdout }}"
        insertafter: EOF
      delegae_to: localhost
      become_user: awx
      become: no

`

apche_task.yaml

`

    - name: Check the apache server status
      uri:
        url: "{{ item.hostname }}:{{ item.port }}"
        method: GET
        status_code: 200
        body_format: raw
        follow_redirects: all
        return_content: yes
        validate_certs: no
        force: yes
      delegae_to: localhost
      become_user: awx
      become: no

    - name: append output to file
      lineinfile:
        dest: /tmp/apache.csv
        line: "{{ item.hostname }},{{ item.port }}"
        insertafter: EOF
      delegae_to: localhost
      become_user: awx
      become: no 

`

Hello,

Ansible will run tasks in parallel against groups of hosts, so I suggest you convert your`

apache_sever_list.yaml

`
file into ansible inventory format

and put all the hosts in it into a group called ‘apache’

then you can run tasks against

  • hosts: apache
    tasks:
  • name: any tasks here run against all the hosts in apache group simultaneously

What its nice is you can still use ‘delegate_to: localhost’ for your uri task and it will still run the task from the ansible controller (but run it in parallel for each host in your ‘apache’ group).

Also, have a look at ‘template’ module I think you will find it a lot easier to create the html file than the combination of shell commands and lineinfile.

I don’t have time to test this today but try experimenting with organising things as follows:

Create an inventory file for your apache hosts:

`

file: apache_hosts

this is an ansible inventory file (using ‘ini’ format but can use yaml)

see https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html for more about inventory

[apache]
host1 ap_port=8081
host2 ap_port=80
host3 ap_port=8080
host4 ap_port=8008
host5 ap_port=8123
`

Create a template file like this:

`

ansible template file: apache.html.j2

see https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#magic-variables-and-how-to-access-information-about-other-hosts

for how to use variables in templates.

List of failed Apache servers

<%for host_result in apache_check_result %> {{ again use apache_check_result to get at the port used | default('Failed' }}
HostnamePort
{{ examine apache_check_result to find hostname from results }}
`

Create a playbook like this:

`

playbook: apache_check.yml

  • name: report on apache status
    gather_facts: yes
    hosts: apache

tasks:

  • name: Check the apache server status
    uri:
    url: “{{ ansible_hostname }}:{{ ap_port }}”
    method: GET
    status_code: 200
    body_format: raw
    follow_redirects: all
    return_content: yes
    validate_certs: no
    force: yes
    register: apache_check_result
    ignore_errors: yes
    delegate_to: localhost

  • name: show results for debugging purposes
    debug:
    var: apache_check_result

  • name: template out the results
    template:
    src: apache_html.j2
    dest: /var/apache.html
    delegate_to: localhost

`

and run the playbook like this

`
ansible-playbook -i apache_hosts apache_check.yml

`

Sorry I haven’t got time to debug this but I hope the above will illustrate that by using ansible’s inventory you can get your tasks to run in parallel (and also that using the ‘template’ module is a great way to create files from ansible.

Hope this helps get you on the right track.

All the best,

Jon

Thanks a bunch Jon. It helps a lot.