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.
Table of Contents
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.