How to Use Ansible Playbooks to Automate Complex Tasks on Multiple Remote Servers – Part 2

In the previous article of this Ansible series, we explained that Ansible is an agent-less tool that allows you to quickly and efficiently manage multiple machines (also known as nodes – and perform deployments to them as well) from a single system.

Use Ansible Playbooks to Automate Complex Tasks on Linux
Use Ansible Playbooks to Automate Complex Tasks on Linux – Part 2

After installing the software in the controller machine, creating the keys for passwordless login and copying them to the nodes, it’s time to learn how to optimize the process of managing such remote systems using Ansible.

Ansible Testing Environment

Throughout this article, as well as the next one, we will use the following test environment. All hosts are CentOS 7 boxes:

Controller machine (where Ansible is installed): 192.168.0.19
Node1: 192.168.0.29
Node2: 192.168.0.30

In addition, please note that both nodes have been added in the webservers section of the local /etc/ansible/hosts file:

Ansible Host File
Ansible Host File

That said, let’s get started with the topic at hand.

Introducing Ansible Playbooks

As described in the previous guide, you can use the ansible utility to run commands in remote nodes as follows:

# ansible -a "/bin/hostnamectl --static" webservers
Ansible: Run Commands on Remote Linux
Ansible: Run Commands on Remote Linux

In the example above, we ran hostnamectl --static on node1 and node2. It doesn’t take long for one to realize that this method of running tasks on remote computers works fine for short commands but can quickly become burdensome or messy for more complex tasks that require further well-structured configuration parameters or interactions with other services

For example, setting up and configuring WordPress on multiple hosts – which we will cover in the next article of this series). This is where Playbooks come into scene.

Simply put, Playbooks are plain text files written in the YAML format, and contain a list with items with one or more key/value pairs (also known as a “hash” or a “dictionary”).

Inside each Playbook you will find one or more group of hosts (each one of these groups is also called a play) where the desired tasks are to be performed.

An example from the official docs will help us to illustrate:

1. hosts: this is a list of machines (as per /etc/ansible/hosts) where the following tasks will be performed.

2. remote_user: remote account that will be used to perform the tasks.

3. vars: variables used to modify the behavior of the remote system(s).

4. tasks are executed in order, one at a time, against all machines that match hosts. Within a play, all hosts are going to get the same task directives.

If you need to execute a different set of associated tasks for a specific host, create another play in the current Playbook (in other words, the purpose of a play is to map a specific selection of hosts to well-defined tasks).

In that case, start a new play by adding the hosts directive at the bottom and starting over:

---
- hosts: webservers
  remote_user: root
  vars:
    variable1: value1
    variable2: value2
  remote_user: root
  tasks:
  - name: description for task1
    task1: parameter1=value_for_parameter1 parameter2=value_for_parameter2
  - name: description for task1
    task2: parameter1=value_for_parameter1 parameter2=value_for_parameter2
  handlers:
    - name: description for handler 1
      service: name=name_of_service state=service_status
- hosts: dbservers
  remote_user: root
  vars:
    variable1: value1
    variable2: value2
…

5. handlers are actions that are triggered at the end of the tasks section in each play, and are mostly used to restart services or trigger reboots in the remote systems.

# mkdir /etc/ansible/playbooks

And a file named apache.yml inside of there with the following contents:

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
  - name: replace default index.html file
    copy: src=/static_files/index.html dest=/var/www/html/ mode=0644
    notify:
    - restart apache
  - name: ensure apache is running (and enable it at boot)
    service: name=httpd state=started enabled=yes
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

Second, create a directory /static_files:

# mkdir /static_files

where you will store the custom index.html file:

<!DOCTYPE html>
 <html lang="en">
 <head>
 <meta charset="utf-8"/>
 </script>
 </head>
 <body>
 <h1>Apache was started in this host via Ansible</h1><br>
<h2>Brought to you by Tecmint.com</h2>
 </body>
 </html>

That said, now it’s time to use this playbook to perform the tasks mentioned earlier. You will note that Ansible will go through each task by host, one at a time, and will report on the status of such tasks:

# ansible-playbook /etc/ansible/playbooks/apache.yml
Ansible: Automate Tasks in Linux
Ansible: Automate Tasks in Linux

Now let’s see what happens when we open a browser and point it to 192.168.0.29 and 192.168.0.30:

Ansible: Confirm Automated Tasks
Ansible: Confirm Automated Tasks

Let’s go one step further and manually stop and disable Apache on node1 and node2:

# systemctl stop httpd
# systemctl disable httpd
# systemctl is-active httpd
# systemctl is-enabled httpd
Stop and Disable Apache Service
Stop and Disable Apache Service

Then run again,

# ansible-playbook /etc/ansible/playbooks/apache.yml

This time, the task reports that the Apache web server was started and enabled on each host:

Ansible: Start Web Server
Ansible: Start Web Server

Please consider the above example as a glimpse of the power of Ansible. While these are relatively easy tasks when performed on a small number of servers, it can become very tedious and time-consuming if you need to do the same in several (perhaps hundreds) of machines.

Summary

In this article we have described how to run commands and execute complex tasks on several remote hosts simultaneously using Ansible. The official documentation and the GitHub repository provide a lot of examples and guides on how to use Ansible to achieve almost any imaginable task.

As you start learning how to automate tasks on remote Linux hosts using Ansible, we would like to hear your thoughts. Questions, comments, and suggestions are also always welcome, so feel free to contact us using the form below any time.

Gabriel Cánepa
Gabriel Cánepa is a GNU/Linux sysadmin and web developer from Villa Mercedes, San Luis, Argentina. He works for a worldwide leading consumer product company and takes great pleasure in using FOSS tools to increase productivity in all areas of his daily work.

Each tutorial at TecMint is created by a team of experienced Linux system administrators so that it meets our high-quality standards.

Join the TecMint Weekly Newsletter (More Than 156,129 Linux Enthusiasts Have Subscribed)
Was this article helpful? Please add a comment or buy me a coffee to show your appreciation.

19 thoughts on “How to Use Ansible Playbooks to Automate Complex Tasks on Multiple Remote Servers – Part 2”

  1. Hello TecMint Team,

    Need your small help, I want to collect multi-data from at least 50 servers like their RAM, os-version, Disk space,kernel-version, and so on things, I have created one script there I am able to get data as required at the remote host, but I want that all 50 remote host data which available at there /tmp/report-1. I want to fetch and override all 50 server data into one file at a local ansible machine.

    Thanks in advance for your help.

    Best Regards,
    Wajid Shaikh

    Reply
  2. Hi All

    Can anyone tell me how to set hostname using ansible. Please find the given below requirement.

    I have 100 servers and I want set hostname like web01 for first server and second server web02 and so on. Please help me out for the same.

    I have also use ansible module hostname but it works only when I am set same hostname in 100 servers.

    Reply
  3. Hi, When I run multiple server automation on ansible, it generates reports individually for each servers. that is making me tough when testing multiple servers at a time and wanted to how many failed and how many passed. is there any way that i can get a single report (resulting all servers) in ansible automation?

    Reply
  4. when i am running the playbook i am getting below output , Can you please explain what does it mean?

    [root@localhost ~]# vim ./Path/To/ansible/playbooks/apache.yml
    [root@localhost ~]# ansible-playbook ./Path/To/ansible/playbooks/apache.yml

    PLAY RECAP *********************************************************************

    Reply
    • Can you add more details? “PLAY RECAP ****************” is not enough for us to help you troubleshoot this.

      Reply
    • you need to change your hosts= in the hosts group you added in you anisble host.

      example here in tecmint its -“hosts: webservers” replace webservers with entry you did in /etc/anisble/hosts

      [group]
      ip address

      Reply
  5. I get this error:
    TASK [replace default index.html file] *****************************************
    fatal: [192.168.0.104]: FAILED! => {“changed”: false, “checksum”: “105317b5614e0de4463045e059a76aab62210ffd”, “failed”: true, “msg”: “Destination /var/www/html not writable”}

    NO MORE HOSTS LEFT *************************************************************
    [WARNING]: Could not create retry file ‘/etc/ansible/playbooks/apache.retry’. [Errno 13] Permission denied:
    ‘/etc/ansible/playbooks/apache.retry’

    please help

    Reply
  6. On executing the command – ansible-playbook /etc/ansible/playbooks/apache.yml

    I get below error:

    TASK [replace default index.html file] *****************************************
    fatal: [192.168.0.104]: FAILED! => {“changed”: true, “failed”: true, “msg”: “Destination /var/www/html not writable”}

    NO MORE HOSTS LEFT *************************************************************
    [WARNING]: Could not create retry file ‘/etc/ansible/playbooks/apache.retry’. [Errno 13] Permission denied:
    ‘/etc/ansible/playbooks/apache.retry’

    please suggest

    Reply
  7. Hi friends,

    Try adding this below lines & it works.


    – hosts: webservers
    vars:
    http_port: 80
    max_clients: 200
    remote_user: root
    tasks:
    – name: ensure apache is at the latest version
    yum: name=httpd state=latest
    – name: write the apache config file
    template: src=/static_files/index.html dest=/var/www/html mode=0644
    notify:
    – restart apache
    – name: ensure apache is running (and enable it at boot)
    service: name=httpd state=started enabled=yes
    handlers:
    – name: restart apache
    service: name=httpd state=restarted

    Reply
    • @Sadashiv,
      As other users have pointed out, copying and pasting directly from this article into a terminal results in indentation errors.
      @Ravi,
      Please place a notice in this article saying so.

      Reply
  8. Hi everyone,
    Regarding the “ERROR: Syntax Error while loading YAML” message, it is hard to assess based on the code formatting as viewed in the comment area. Please take a look here (https://github.com/ansible/ansible/issues/8243) and make sure you don’t have indentation errors or typos throughout the configuration files. If this does not resolve your issues, please upload the playbook files to an online storage service (such as Pastebin) and share the details of your system (distribution + version and Ansible version) so that I can reproduce.

    Reply
  9. Gabriel,

    I have encounter an issue

    ERROR! Syntax Error while loading YAML.

    The error appears to have been in ‘/etc/ansible/playbooks/apache.yml’: line 2, column 8, but may
    be elsewhere in the file depending on the exact syntax problem.

    The offending line appears to be:


    – hosts: web-servers
    ^ here

    My playbook as follows


    – hosts: web-servers
    vars:
    http_port: 80
    max_clients: 200
    remote_user: root
    tasks:
    – name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
    – name: replace default index.html file
    copy: src=/static_files/index.html dest=/var/www/html/ mode=0644
    notify:
    – restart apache
    – name: ensure apache is running (and enable it at boot)
    service: name=httpd state=started enabled=yes
    handlers:
    – name: restart apache
    service: name=httpd state=restarted

    Reply
  10. I am getting error after loading the ansible-playbook

    ERROR: Syntax Error while loading YAML script, /etc/ansible/playbooks/apache.yml
    Note: The error may actually appear before this position: line 7, column 4

    remote_user: root
    tasks:

    Reply
  11. Thanks for this useful article, actually I was working on it this night to make something like a monitor for Apache, MySQL, Exim, FTP, Load Average and Disk Usage, which will execute a command and send an email in case of failed, I gone through hard time to be honest but finally made it.

    Reply
    • What are the difficulties you encountered while setting up and using Ansible? Feel free to share with the rest of the community – that way we will all benefit from each other’s experience.

      Reply

Got something to say? Join the discussion.

Thank you for taking the time to share your thoughts with us. We appreciate your decision to leave a comment and value your contribution to the discussion. It's important to note that we moderate all comments in accordance with our comment policy to ensure a respectful and constructive conversation.

Rest assured that your email address will remain private and will not be published or shared with anyone. We prioritize the privacy and security of our users.