Parallel execution of tasks in playbook

78 views
Skip to first unread message

Build Admin

unread,
Nov 14, 2018, 7:27:04 AM11/14/18
to Ansible Project
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
Message has been deleted
Message has been deleted

Lucas Jackson

unread,
Nov 14, 2018, 7:47:06 AM11/14/18
to Ansible Project
See this, async tasks, may be what you're looking for

Brian Coca

unread,
Nov 14, 2018, 9:07:18 AM11/14/18
to ansible...@googlegroups.com
I would look at the 'free' strategy, but you have others:

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




--
----------
Brian Coca

Build Admin

unread,
Nov 15, 2018, 10:40:34 AM11/15/18
to Ansible Project
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

J Hawkesworth

unread,
Nov 16, 2018, 3:35:26 AM11/16/18
to Ansible Project
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.
<html>
<body>

<h3>List of failed Apache servers<
/h3>
<table>

<table><tr><th>Hostname</
th><th>Port</th></tr>
<%for host_result in apache_check_result %>
<tr><td>{{ examine apache_check_result to find hostname from results }}</td>{{ again use apache_check_result to get at the port used | default('Failed' }}</tr>
</table>
</
body>
</html>

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

Saravanan

unread,
Nov 18, 2018, 6:58:21 PM11/18/18
to Ansible Project
Thanks a bunch Jon. It helps a lot.
Reply all
Reply to author
Forward
0 new messages