How to Use Ansible delegate_to to Run Task on Specific Host

Ansible delegate_to Module

In Ansible, tasks usually run on the hosts listed in the inventory file. However, there are times when you need to execute a task on a different host. Ansible’s delegate_to module allows you to delegate a task from one host to another. This feature is handy for tasks involving centralized services or managing dependencies across multiple hosts.

In this guide, we’ll explain how to use the Ansible delegate_to module to run tasks on a specific host.

Basic Syntax and Usage

The basic syntax for using delegate_to is simple. You add the delegate_to keyword to a task and specify the target host. Here’s the basic syntax for using delegate_to in an Ansible playbook.

- name: Example playbook
  hosts: target_host
  tasks:
    - name: Task to be executed on the target host
      command: echo "This is run on the target host"
      
    - name: Task to be executed on a different host
      command: echo "This is run on the delegated host"
      delegate_to: delegated_host

In this example.

  • First task runs on the target_host.
  • Second task is run on the delegated_host because of the delegate_to directive.

Gathering Facts from Different Hosts

In some scenarios, you may need to gather facts from one host and use them on another. This example demonstrates how to gather facts from a database_server and use them on the web_server.

---
- name: Gather facts from a different host
  hosts: web_server
  tasks:
    - name: Gather facts from database server
      ansible.builtin.setup:
      delegate_to: database_server
      register: db_facts

    - name: Use database server facts on web server
      ansible.builtin.debug:
        msg: "Database server IP is {{ db_facts.ansible_facts.ansible_default_ipv4.address }}"

This playbook gathers facts from a database_server, stores them in db_facts, and then uses these facts to display the database server’s IP address on a web_server.

Managing Certificates on a Central Host

Imagine you have a central server that manages SSL certificates for your web servers. You can use delegate_to to perform actions on this central server.

---
- name: Managing SSL certificates using delegate_to
  hosts: web_server
  tasks:
    - name: Generate SSL certificate on central server
      ansible.builtin.command: >
        openssl req -new -newkey rsa:2048 -nodes -keyout /etc/ssl/private/mycert.key -out /etc/ssl/certs/mycert.csr
      delegate_to: central_cert_server

    - name: Copy SSL certificate to web server
      ansible.builtin.copy:
        src: /etc/ssl/certs/mycert.csr
        dest: /etc/ssl/certs/mycert.csr
      delegate_to: web_server

In this scenario, the SSL certificate is generated on the central_cert_server with the command module and then copied to the web_server.

Running Commands on Multiple Hosts Sequentially

You might need to perform a series of tasks on different hosts in a sequence. Here’s how you can achieve that.

---
- name: Running commands on multiple hosts sequentially
  hosts: all
  tasks:
    - name: Run a script on the first server
      ansible.builtin.command: /tmp/script.sh
      delegate_to: server1

    - name: Run a script on the second server
      ansible.builtin.command: /tmp/script.sh
      delegate_to: server2

    - name: Run a script on the third server
      ansible.builtin.command: /tmp/script.sh
      delegate_to: server3

In this example, each task runs a script on a different server in the specified order.

Backing Up MySQL Database

Imagine you have a production MySQL database server that’s essential to your company’s operations. To protect your data, you decide to back up the database regularly to a separate backup server. This way, the main database server’s performance remains unaffected by the backup process, and your backups are safely stored in a different location.

Here is an example playbook that connect to the db-server, creates a backup of the database, and then transfers it to the backup-server.

---
- name: Backup MySQL database and transfer to backup server
  hosts: db_servers
  become: yes
  vars:
    db_name: db_name
    db_user: db_user
    db_password: db_password
    backup_dir: /tmp/db_backups
    backup_file: "{{ db_name }}_backup_{{ ansible_date_time.iso8601 }}.sql"
    remote_backup_dir: /var/backups/mysql

  tasks:
    - name: Install MySQL client
      apt:
        name: mysql-client
        state: present

    - name: Create backup directory
      file:
        path: "{{ backup_dir }}"
        state: directory
        mode: '0755'

    - name: Backup MySQL database
      command: >
        mysqldump -u{{ db_user }} -p{{ db_password }} {{ db_name }} > {{ backup_dir }}/{{ backup_file }}
      environment:
        MYSQL_PWD: "{{ db_password }}"

    - name: Ensure remote backup directory exists on backup server
      delegate_to: backup_servers
      file:
        path: "{{ remote_backup_dir }}"
        state: directory
        mode: '0755'

    - name: Transfer backup to backup server
      delegate_to: backup_servers
      copy:
        src: "{{ backup_dir }}/{{ backup_file }}"
        dest: "{{ remote_backup_dir }}/"

    - name: Clean up local backup file
      file:
        path: "{{ backup_dir }}/{{ backup_file }}"
        state: absent

This playbook:

  • Installs the MySQL client on the db-server, backup the specified database, and temporarily stores the backup in a local directory.
  • Uses the delegate_to directive to create the backup directory on the backup-server and copies the backup file with copy module.
  • Finally, it deletes the local backup file on the db-server to free up space.

Running Security Scans from a Security Node

Tasks like vulnerability scans are often conducted in security-sensitive environments from dedicated security nodes. These nodes have the necessary permissions, tools, and configurations for performing comprehensive security checks.

Here is an example playbook that performs security scans on security_node.

- name: Security Scans Playbook
  hosts: all
  become: yes
  tasks:
    - name: Run security scan on all hosts
      command: nmap -sS -T4 {{ inventory_hostname }}
      delegate_to: security_node
      register: scan_results

    - name: Display security scan results
      debug:
        msg: "Scan results for {{ inventory_hostname }}: {{ scan_results.stdout }}"

The above playbook:

  • Uses a command module to run an Nmap scan on each host in the inventory. The scan is executed from the security_node, ensuring that all network scans are centralized and controlled.
  • It then uses the debug module to output the security scan results for each host, allowing administrators to review any detected vulnerabilities or issues.

Conclusion

This article explored the Ansible delegate_to module, starting with the basic syntax and progressing through several advanced, real-world examples. By leveraging delegate_to, you can efficiently manage tasks across different hosts, optimize your playbooks, and easily handle complex configurations.

FAQs

1. What happens to facts collected when using delegate_to?

When using delegate_to, facts collected are from the delegated host, not the original host. Be mindful of this if you need specific data for the target host.

2. How is delegate_to different from delegate_facts?

delegate_to is used to run tasks on a specific host, whereas delegate_facts is used to delegate the collection of facts from one host to another.

3. Can delegate_to be used for gathering facts?

No, delegate_to is not typically used for gathering facts. Instead, you can target specific hosts using the hosts keyword for fact gathering.

About Hitesh Jethva

I am Hitesh Jethva Founder and Author at LinuxBuz.com. I felt in love with Linux when i was started to learn Linux. I am a fan of open source technology and have more than 15+ years of experience in Linux and Open Source technologies.

View all posts by Hitesh Jethva

Leave a Reply

Your email address will not be published. Required fields are marked *