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?
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
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)
<%for host_result in apache_check_result %>
{{ again use apache_check_result to get at the port used | default('Failed' }}
Hostname
Port
{{ 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
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.