Home Ansible Getting Started With Ansible Playbooks

Getting Started With Ansible Playbooks

What is Ansible Playbook | How to work with Ansible Playbooks

By Karthick
Published: Last Updated on 913 views

In the last article, we have discussed about Ansible ad hoc commands. Whatever we learned there will be applied in this article but in a different way. This tutorial explains what is a Playbook in Ansible and how to work with Ansible Playbooks with examples.

What Is Ansible Playbook?

The playbook is a YAML file that is used to execute one or more tasks against the managed hosts in the environment.

The main difference between ad hoc commands and playbooks is with adhoc commands you can create simple one-liners or use the adhoc command in shell scripts to run simple tasks. When you want to do complex repetitive operations then you should write playbooks and store them in a central repository and use them whenever needed.

Let’s assume you are part of the system admin team. Whenever a new server is built your team is responsible for hardening the server as per your company policy.

In this case, you can build a playbook and harden the server. Now the same playbook can be used against the N number of new host that needs to be hardened.

My Ansible Lab Structure

I am going to use the ansible lab that was created with two Ubuntu 20.04LTS nodes. You can refer to the following article to replicate the same lab setup if needed.

Automated Ansible Lab Setup With Vagrant And Virtualbox In Linux

Create Your First Ansible Playbook

As I stated earlier, Playbooks are written in YAML format. The playbook should have a .yml or .yaml extension. Take a look at the link below if you want to learn about YAML.

YAML Tutorial | Getting Started With YAML

Below is the sample playbook I am going to use to demonstrate how the playbook works. This is a simple playbook that will take care of setting up a custom banner message when I log in to the node.

- name: First Play - Modify banner message
  hosts: ubuntu2
  gather_facts: false
  become: yes

  tasks:
    - name: Remove Execute Permission from /etc/update-motd.d/*
      file:
        path: /etc/update-motd.d/
        mode: u=rw,g=rw,o=rw
        recurse: yes

    - name: ADD BANNER MESSAGE
      copy:
        content: "Welcome to OSTechnix"
        dest: /etc/motd

Let’s look at each section of this playbook. The playbook is divided into two sections. The first section contains play definitions like play name, target hosts, and privilege escalation.

  • name - The playbook should have a play name that is nothing but a logical grouping of the target host, parameters, and tasks. You can have more than one play in the playbook. Give a descriptive name to the play.
  • hosts - Target hosts. Ansible will check the inventory file and verify if the value given in hosts is available in the inventory file.
  • become - When set to 'yes' will run the task with sudo privilege. Since I am modifying the permission under the /etc/ directory, the task should be submitted with elevated privilege.

Take a look at our comprehensive article on privilege escalation to understand it in detail.

Ansible SSH Authentication And Privilege Escalation

Play Definitions
Play Definitions

In the second section, tasks are defined. You should use the keyword "tasks" to define the task. Here I have created two tasks. Each task should be given a name using the keyword "name".

  • The first task will remove execute permission from /etc/update-motd.d/* directory. I am using the file module for this.
  • The second task will write the string "Welcome to OSTechnix" to the /etc/motd file using the copy module.
Playbook - Tasks
Playbook - Tasks

Before running the playbook, let me check the state of my target node(managed2.anslab.com) by logging into the node. You can see when I log in to the node, I get the default banner message and the execute permission is set for all files.

$ ssh [email protected]
Default State - Managed2 Node
Default State - Managed2 Node

To execute the playbook, run the following command from the terminal.

$ ansible-playbook <playbook-name>   # SYNTAX
$ ansible-playbook banner_mod.yml
Play Output
Play Output

Let’s try to understand the output.

1. When you run the playbook the first thing that you are going to see is the play name.

PLAY [Modify banner message] *

2. The first task ansible run is "Gathering Facts". We have not defined this task in our playbook but this will run unless you turn it off.

TASK [Gathering Facts] *
ok: [managed2]

3. Now the task you defined in the YAML file as part of the play will start executing one by one. Ansible will read the playbook from top to bottom so tasks will be executed in the order defined in the playbook.

TASK [Remove Execute Permission from /etc/update-motd.d/*] *******************************************************************************************
changed: [managed2]

TASK [ADD BANNER MESSAGE] ****************************************************************************************************************************
changed: [managed2]

4. Once all the tasks are completed you will have a play recap which will give you the total status count of different tasks. In our case a total of three tasks (ok=3) ran including facts gathering and only two tasks (changed=2) made the changes to the managed node.

PLAY RECAP ******************************************
managed2 : ok=3 changed=2    unreachable=0 failed=0 skipped=0    rescued=0 ignored=0   

Now I can validate the managed node to see if changes are applied successfully.

Validate Result
Validate Result

Disable Facts Gathering

As foretold in the previous section when you run the playbook, ansible will collect facts about the managed nodes by running the setup module. You can disable facts gathering by adding the following line in the playbook.

gather_facts : false
Disable Gathering Facts
Disable Gathering Facts

Now when you run the playbook again, you will only see two tasks that were defined in the playbook. Since Ansible is idempotent, ansible will not try to alter the state of the object if it is already altered. So you will see the output as OK.

Disabled Gathering Facts - Output
Disabled Gathering Facts - Output

Gathering facts will make the plays run slow when you have to run the playbook against a large number of hosts. This is because ansible has to connect with the managed node and collect a lot of data about the node which is not necessary for all the cases.

You can check the execution time difference with and without facts below.

$ time ansible-playbook banner_mod.yml  # WITHOUT FACTS

real    0m1.642s
user    0m0.731s
sys    0m0.220s

$ time ansible-playbook banner_mod.yml  # WITH FACTS

real    0m2.547s
user    0m1.139s
sys    0m0.187s

Execute Multiple Plays

You can have more than one play in the playbook. As you can see in the below image, my second play has one task which is going to restart the sshd service using the service module in a different host.

Multiple Play Definitions
Multiple Play Definitions
- name: Second Play - Restart SSHD service
  hosts: ubuntu1
  gather_facts: false
  become: yes

  tasks:
    - name: Restart SSHD in managed1.anslab.com
      service:
        name: sshd
        state: restarted

Let’s run the playbook again and you can see from the output both the plays are executed successfully.

$ ansible-playbook banner_mod.yml
Execute Multiple Plays
Execute Multiple Plays

Now you should have a fair understanding of how to write a playbook and execute it. Playbook supports additional useful features which we will see in the upcoming section.

Validate Playbook Syntax

You can use the --syntax-check flag to check for any syntax errors in your playbook. I purposely made a syntactical error in the "gather_facts" line in my playbook.

$ ansible-playbook --syntax-check banner_mod.yml
Playbook Syntax Check
Playbook Syntax Check

Prompt For Confirmation

When you use the --step flag, for each task in your play it will prompt for your confirmation to proceed with the task.

$ ansible-playbook --step banner_mod.yml
Prompt For Confirmation
Prompt For Confirmation

Execute A Dry Run

Instead of executing the tasks in managed nodes you can simulate the run using -C or --check flag.

$ ansible-playbook -C banner_mod.yml

Start From A Particular Task

You have an option to start running the playbook from a particular task. You can see from the below image I started from Play2(task1), so both the task in play1 is skipped. Use the flag --start-at-task and pass the task name as the argument.

$ ansible-playbook banner_mod.yml --start-at-task "Restart SSHD in managed1.anslab.com"
Execute From Particular Task
Execute From Particular Task

Run Task Using Tags

You can group plays and tasks with tags. Using tags, you can run only those tasks with particular tags or skip the tasks.

You can take a look at the below image where I have used the "tags" keyword and set some values to it. You can also add multiple values to a single tag.

Tags
Tags

You can run the following command to get the list of tasks along with its tags.

$ ansible-playbook banner_mod.yml --list-tasks
$ ansible-playbook banner_mod.yml --list-tags
List Tasks And Tags
List Tasks And Tags

Use -t flag and pass tag names as the argument. You can either run a particular tag-based task or multiple tags as shown below. In the below example, I am using two different tags from two different plays.

$ ansible-playbook -t "set_perm","restart service" banner_mod.yml
Run Tasks Based On Tags
Run Tasks Based On Tags

You can also skip a task and run all other tasks using --skip-tags flag.

$ ansible-playbook -t "set_perm","restart service" --skip-tags "set_perm" banner_mod.yml
Skip Tasks Based On Tags
Skip Tasks Based On Tags

Increase Verbosity

Sometimes the playbook will not behave in the way you expect it to. It might be something that is happening in the background or different errors.

To debug the issue you can increase the verbosity(-v) when running the playbook. There are four levels of verbosity. You can either set the verbosity in the ansible.cfg file by adding the property "verbosity=<level" or from the terminal using -v or ANSIBLE_VERBOSITY environmental variable.

$ ansible-playbook -vvvv -t "set_perm","restart service" --skip-tags "set_perm" banner_mod.yml # VERBOSE LEVEL SET TO 4(-vvvv)

[OR]

$ ANSIBLE_VERBOSITY=4 ansible-playbook -vvvv -t "set_perm","restart service" --skip-tags "set_perm" banner_mod.yml # VERBOSE LEVEL SET TO 4(ENV VARIABLE)
Verbose Output
Verbose Output

Control Parallelism

When you run the playbook ansible will execute the task in batches. By default, ansible will execute a task in 5 nodes parallelly and once all the task is completed in all 5 nodes it will move to the next set of 5 nodes.

Likewise, it will run a task in batches of 5 until the task is completed in all the nodes and then move to the next task and repeat the same step.

You can control the parallelism and set how many nodes should be processed in parallel by setting the "forks" parameter in the ansible.cfg file.

[defaults]
inventory = inventory
host_key_checking = False
forks=20

I have set the value of forks to 20. It will now process a task at 20 nodes parallelly. Likewise, you can increase/decrease the count depending on your requirement.

You can override the value set in ansible.cfg file by passing -f or --forks flag. When I run the following command the forks value of 20 will be overridden by 15.

$ ansible-playbook banner_mod.yml -f 15

Conclusion

In this article, we have seen how to write Ansible playbooks and the different parameters and options supported in playbooks. There are tons of other features like variables, conditions, loops, etc. that can be used in playbooks which we will cover in our upcoming articles.

Related Next:

You May Also Like

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This website uses cookies to improve your experience. By using this site, we will assume that you're OK with it. Accept Read More