Understanding Ansible Playbook – Write your First Playbook

This tutorial will help you to understand about Ansible Playbook. At the end of this post, you will be able to understand What is Ansible Playbook, how to write a playbook for the automated configurations.In the previous posts, we have explained the below topics. Refer those links to understand this topic from basics.

1. What is Ansible, How Ansible works, Ansible Introduction, Ansible Basic Tutorials
2. Ansible Inventory Introduction – Ansible Beginner Tutorials
3. Ansible Ad hoc Commands – Ansible Tutorial for Beginners
4. Managing Ansible Configuration Files Explained with Examples
5. Understanding Ansible Playbook – Write your First Playbook
6. Ansible Roles Explained with Examples – Ansible Tutorials
7. How to use Ansible Vault to Protect Ansible Playbooks

Understanding Ansible Playbook – Write your First Playbook

Lets get started.

What is Ansible Playbooks?

Ansible Playbook Tutorial

Ansible playbooks are a way to send commands to remote computers in a scripted way. Instead of using Ansible commands individually to remotely configure computers from the command line, you can configure entire complex environments by passing a script to one or more systems.

Ansible playbooks are written in the YAML data serialization format. If you don’t know what a data serialization format is, think of it as a way to translate a programmatic data structure (lists, arrays, dictionaries, etc) into a format that can be easily stored to disk. The file can then be used to recreate the structure at a later point. JSON is another popular data serialization format, but YAML is much easier to read.

Each playbook contains one or more plays, which map hosts to a certain function. Ansible does this through something called tasks, which are basically module calls.

Also Watch this “Ansible Playbook” Tutorial video on our YouTube Channel.

How to Create Ansible Playbooks?

Create Ansible Playbook with a file name, not necessary to have the filename with any extension. but create with extension with “.yml” else you wont find the difference of normal text file and a playbook.

The file starts with: —

Example :

[[email protected] ~]# vi install.yml

– hosts: all
sudo: true
vars:
packages: [ ‘vim’, ‘git’, ‘curl’ ]
tasks:
– name: Install Package
apt: name={{ item }} state=latest
with_items: packages

– hosts: all
tasks:
– name: Install httpd Package
apt: name=httpd state=latest

This is a requirement for YAML to interpret the file as a proper document. YAML allows multiple “documents” to exist in one file, each separated by “—“, but Ansible only wants one per file, so this should only be present at the top of the file.

YAML is very sensitive

We should be more cautious with the spaces while writing a ansible playbook. Tabs are not allowed here. Character should start exactly or after the previous parameter starts and it should looks like a statement as shown in the above examples.

Basically Playbooks consists of three sections,
1. Host declaration
2. Variable declaration (optional)
3. Action / Tasks Declaration

Hosts declaration (- hosts: all) – It defines that on which server groups playbook should run based on the ansible inventory file.
Variable declaration (vars) is optional, we see some examples how to declare a variable below.

Action / Tasks Declaration:

You can also use other parameters like, name, actions, notify, remote users depend on the requirement.

As shown in the above example, we should define the tasks to be performed.

Under the tasks (tasks:) – You specify the list of tasks to be carried out. Every task should have a name, which will show you in the output while running the playbook and also its easy for us to identify it.

For example. Lets say configuring a basic Apache Webserver. Following tasks are needed.
1. Installing a httpd packages
2. Configuring the httpd service
3. Starting and Enabling httpd service.

So lets create the task.

[[email protected] ~]# vi install.yml

– hosts: all
tasks:
– name: Install httpd Package
yum: name=httpd state=latest
– name: Copy httpd configuration file
copy: src=/data/httpd.original dest=/etc/httpd/conf/httpd.conf
– name: Start and Enable httpd service
service: name=httpd state=restarted enabled=yes

We can create a multiple task for each actions as shown in the above example.

Name : describe the task what it is actually going to perform.
Then action what are you going to do. Each task is to execute a module, with very specific arguments. here we have used different modules. yum used to install the package, copy used to transfer the file from source to target server and service used to start and enable the httpd service.

Verify the playbook for syntax errors:

Lets do syntax check to ensure there is no syntax error using below command.

[[email protected] ~]# ansible-playbook install.yml –syntax-check
playbook: install.yml
[[email protected] ~]#

To see what hosts would be affected by a playbook before you run it, you can do this:

[[email protected] ~]# ansible-playbook install.yml –list-hosts
playbook: install.yml
play #1 (all): all    TAGS: []
pattern: [u’all’]
hosts (1):
      server1

Above output shows that only host “server1” will be affected with this playbook.

Run a playbook and configure the httpd service.

[[email protected] ~]# ansible-playbook install.yml
PLAY [all] *****************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************
ok: [server1]
TASK [Install httpd Package] ***********************************************************************************
changed: [server1]
TASK [Copy httpd configuration file] ***************************************************************************
ok: [server1]
TASK [Start and Enable httpd service] **************************************************************************
changed: [server1]
PLAY RECAP *****************************************************************************************************
server1                    : ok=4    changed=2    unreachable=0    failed=0

Above output shows the summary of the playbooks.

Play – Display that this playbook runs on all hosts as per the hosts declaration.
Task – Ansible gathering facts(catalog) from all servers to run the actions.
Task – Name of each action as per the playbook
Under the task – Changes of the state.

Finally, you got the status of the complete playbook as, 4 tasks are OK without any errors and 2 changes are done which are installing httpd package and starting / enabling httpd service. Unreachable and failed are zero.

Variable Declarations:
Instead of creating 10 tasks for installing 10 different packages, you can create a single task by using variables in a same playbook as below,

vars:
package: vim,yum-utils

tasks:
– name: Install Package
yum: name={{ package }} state=latest

Above example use a variable definition (vars:) to install a multiple packages vim and yum-utils. Similarly, you can modify only the package names.

Using Loops

Loops are typically used to repeat a task using different input values as we have used variable declaration.

To create a loop within a task, include the option with_items with an array of values. The content can be accessed through the loop variable item, as shown in the example below:

– name: Install Packages
apt: name={{ item }} state=latest
with_items:
– vim
– git
– curl

You can also use an array variable to define your items:


– hosts: all
sudo: true
vars:
packages: [ ‘vim’, ‘git’, ‘curl’ ]

tasks:
– name: Install Package
apt: name={{ item }} state=latest
       with_items: packages

Notify and Handlers in Ansible Playbook

[[email protected] ~]# vi install.yml

– hosts: all
tasks:
– name: Install httpd Package
yum: name=httpd state=latest
– name: Copy httpd configuration file
copy: src=/data/httpd.original dest=/etc/httpd/conf/httpd.conf
notify:
– restart apache

– name: Start and Enable httpd service
service: name=httpd state=restarted enabled=yes
handlers:
– name: restart apache
service: name=httpd state=restarted

The “notify” item contains a list with one item, which is called “restart apache”. This is not an internal Ansible command, it is a reference to a handler, which can perform certain functions when it is called from within a task. We will define the “restart apache” handler below the palybook.

The “handlers” section exists at the same level as the “hosts” and “tasks”. Handlers are just like tasks, but they only run when they have been told by a task that changes have occurred on the client system.

For instance, we have a handler here that restarts the apache service after the package is installed. The handler is not called unless the “copy httpd configuration file” task results in changes to the system, meaning that httpd file from source should be copied to the target server and wasn’t already there.

There is no use of restarting the service when there is no changes in configuration file. Once copied the new configuration file, service should be restarted.

Getting help for Modules and its arguments:
To list all modules available in ansible,

ansible-doc -l

These modules are catagorized.
Cloud Modules
Clustering Modules
Commands Modules
Crypto Modules
Database Modules
Files Modules
Identity Modules
Inventory Modules
Messaging Modules
Monitoring Modules
Net Tools Modules
Network Modules
Notification Modules
Packaging Modules
Remote Management Modules
Source Control Modules
Storage Modules
System Modules
Utilities Modules
Web Infrastructure Modules
Windows Modules

If you are not sure about the value of modules like state, Documentation for each module can be accessed from the command line with the ansible-doc tool:

ansible-doc yum

If you find any options started with “=” its a mandatory and should be included in the actions.

Example:

[[email protected] ~]# ansible-doc yum | grep -i “=”
OPTIONS (= is mandatory):
installed higher version of that package. Note that setting allow_downgrade=True
Package name(s) to exclude when state=present, or latest
= name
state=latest, this can be ‘*’ which means run `yum -y update’.  You can also pass
a url or a local path to a rpm file (using state=present). To operate on several
If set to `yes’, and `state=latest’ then only installs updates that have been

So hope you have got an idea on Ansible Playbook. Going forward we will play more with ansible tool. Keep practizing and have fun. thank you.

Keep practicing and have fun. Leave your comments if any.

Support Us: Share with your friends and groups.

Stay connected with us on social networking sites, Thank you.