Ansible delegate_to Examples - Run task on specific host

Ansible Delegate_to module helps us to execute a specific task in our playbook to run in other host or machine.

This process of handing over the control of execution to another host (or) executing a task in another machine is called as delegation and  the module delegate_to helps you to configure it properly and achieve the desired result.

While we have already written various playbooks in Devops Junction with delegate_to directive.

This post is going to be dedicated for this directive and to give you a collective example to know everything about this ansible delegate and how to execute a task on other machine or host.

Here are the top three examples published already with delegate_to module in Devops Junction, excluding this one.

  1. Ansible SSH Key Exchange between hosts
  2. Ansible update /etc/hosts file across multiple machines
  3. How to copy files between remote hosts in Ansible

Let us continue to our objective and cover ansible delegate_to from basics.

 

Ansible delegate_to Example and explanation

As ansible delegate_to is a directive, not an individual module, It integrates with other modules and it controls the task execution by deciding which host should run the task at runtime.

Refer to the following snapshot of the playbook, there are few tasks.

If you look at the Task3, you can see there is a delegate_to used to change the control of execution back to the ansible master from the remote host where the task was supposed to run.

this is a simple delegation where the control of execution transferred from remote host to the master.

You can write playbooks to change the control between the remote servers as well. which is already covered in our aforementioned articles. We will take a look in detail shortly.

 

The Playbook to execute tasks in another host with delegate_to

this is the ansible playbook we have created for this post,  to explain the simple delegation between a remote host and the ansible master.

---
- name: "Ansible Delegate_to examples"
  hosts: testserver
  tasks:

  - name: "Task1: start a quick webserver with NC on remote server"
    shell: "while true; do { echo -e 'HTTP/1.1 200 OK\r\n'; echo Hello from WebServer ;  } | nc -l 8081 > /tmp/serverout.log ; done &"   
    #Fire and Forget the job - let it run in background
    async: 1
    poll: 0

  - name: "Task2: Enabling the port in firewall"
    become: true
    firewalld:
      port: 8081/tcp
      permanent: true
      state: enabled
      immediate: yes

  - name: "Task3: Check the status of the remote server from localhost [Ansible master]"
    uri:
        url: http://{{inventory_hostname}}:8081
        method: GET 
        timeout: 30 
        status_code: 200
        return_content: yes
    delegate_to: localhost
    register: webresult

  - name: "Task4: Printing the website output from the Task3"
    debug: var=webresult

 

Execution Output of this playbook

When you are executing this playbook with a single remote host defined under testserver the output of this playbook would be something like this

ansible delegate_to

Explanation of the playbook

Task1:  On the remote server named mwiapp01 defined under hostgroup named testserver this task would start a quick and simple web server using Netcat command and listen to port 8081.

We have used async and poll of ansible to execute the job and run it background to know more about this refer to our previous article

Task2:  On the remote server release the firewall using firewalld module and enable the port 8081 of our web server, for the public traffic to come in ( in this case, from ansible master)

Task3: Access the web server we have set up using the uri module. but execute this task on the master server, though the task has been already sent to the remote server mwiapp01

As shown in the following diagram, the task would first be handed over to the remote server and then it will be delegated or re-sent for execution to the master server.

Ansible Delegate_to

If you look at the playbook output presented earlier, You can see something like this

ok: [mwiapp01 -> localhost]

Unlike other tasks, this task would have two names shown before the status OK.

This indicates that the task has been handed off from mwiapp01 to localhost for execution.

This is how you can understand when a task is delegated_to some other host

Task4:  This task is to display the register variable we have used in task3 to save the response content of the URI module.  this would display the status code and the content we get as a response when we are accessing our webserver.

In order to cross-verify this, you can use the curl command on the ansible master like this

curl -v http://mwiapp01:8080/

 

Realtime Example of ansible delegate_to

So far we have talked about how to delegate between a single remote server and a control machine/ansible master. as I mentioned it was very light to start with.

to understand the upcoming playbook and what does it do, it is necessary you read our article on "How to copy files between remote hosts in ansible using delegate_to" and come back here

Hope you read the article we have referred above. so our requirement in that article is to copy files between remote hosts mwiapp01 and mwiapp02

while there were two methods of doing this. the efficient way was using the sync module and it heavily relies upon delegation to complete the copy between the hosts.

I am pasting the playbooks from that article here once again

 

Playbook to copy files from mwiapp01 to 02 using Sync Push

- name: Sync Push task - Executed on source host "{{groups['app'][0]}}"
  hosts: "{{groups['app'][1]}}" 
  user: wlsusr
  tasks:
    - name: Copy the file from mwiapp01 to mwiapp02 using Method Push
      tags: sync-push
      synchronize:
        src: "{{ item }}"
        dest: "{{ item }}"
        mode: push
      delegate_to: “{{groups[‘app’][0]}}“
      register: syncfile
      with_items:
       - "/tmp/app01-to-app02.jar"

 

 

Playbook to copy files from mwiapp01 to 02 using Sync Pull

---
- name: Sync Pull task - Executed on  the Destination host "{{groups['app'][1]}}"
  hosts: "{{groups['app'][0]}}"
  user: wlsusr
  tasks:   
    - name: Copy the file from mwiapp01 to mwiapp02 using Method Pull
      tags: sync-pull
      synchronize:
        src: "{{ item }}"
        dest: "{{ item }}"
        mode: pull
      delegate_to: “{{groups[‘app’][1]}}“
      register: syncfile
      run_once: true
      with_items:
       - "/tmp/app01-to-app02.jar"

 

if you look at this playbook you can see that we have a delegate_to and both of them

In Sync Pull: The execution is handed over/delegated to the destination machine (mwiapp02) from where you are pulling the file from the source

In Sync Push: The execution is handed over/delegated to the source machine (mwiapp01) from there the file gets pushed.

without delegate_to this would have not been possible.

I hope this clarifies about delegate_to and as a by-product, you have also learnt some real-time examples on how to copy files between remote hosts, how to update /etc/hosts file on multiple machines etc.

I know this is a little complex to understand. ( or it was once to me when I began ) but when you are reading this slowly and trying it out. You will get the hang of it. I am sure.

If you have any questions/comments about this article. Please let me know in the comments.

 

Cheers
Sarav

Follow me on Linkedin My Profile
Follow DevopsJunction onFacebook orTwitter
For more practical videos and tutorials. Subscribe to our channel

Buy Me a Coffee at ko-fi.com

Signup for Exclusive "Subscriber-only" Content

Loading