An Introduction To Ansible Playbooks

Michael Jonaitis
6 min readAug 3, 2020

--

This tutorial will teach you how to install Ansible on an Ubuntu server and connect a minion server to the Ansbile control server. We will then create an Ansible playbook which will be used to install some basic software packages on the minion server. The tutorial will also give an overview of basic Ansible commands which will come in handy down the road.

Why Ansible?

If you have ever worked in dev-ops or have spent time configuring servers to run your applications. You would know how cumbersome it can be to do it all by hand. Not only do you need to install or configure the same services over and over again, you also need to manually keep track of exactly what you have done and what is left to do. Ansible helps solve this problem. Ansible is installed on a server and is used as the control station which stores and applies “states” to servers you choose to connect to it. This allows you to efficiently configure servers to do your bidding without having to painstakingly do it by hand.

Provision Linode Ubuntu Servers

To work through this tutorial, first go to linode.com and create 2 servers using the Ubuntu Linux distribution. One named ansible-control and another named ansible-web. Be sure to set a root password and let them spin up.

The Linode tutorial showing the steps to launch a new Linode server can be found here.

https://www.linode.com/docs/getting-started/

Installing Ansible

Once the servers are done initializing ssh into your ansible control server.

First ssh into your new ansible control server.

ssh root@<ip-address-of-ansible-control-server>

Now we must add the ansible ppa repository. Afterwards we can install the Ansible package onto the control server.

sudo apt update
sudo apt install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install ansible

Connecting our first minion

Once Ansible is installed we can add the ip address of our web server to the /etc/ansible/hosts file. You will see many commented lines out. These are just an example, but since this is a web server we can put it under the commented out [webservers] group. To take advantage of the groups feature we will uncomment the [webservers] line as well.

# Ex 2: A collection of hosts belonging to the 'webservers' group
[webservers]
<ip-address-of-web-server>
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110

Generate an ssh key to allow your control server to connect to the minions.

ssh-keygen

Copy the ssh key to the minion server.

ssh-copy-id <ip-address-of-web-server>

Check that Ansible can connect to all the minion servers (we only have one).

ansible -m ping all

OR we can also target the group of webservers specifically by adding the group name after the ansible command. Remember the [webservers] group in the hosts file?

ansible webservers -m ping

You should be seeing a response that looks like this.

<ip-address-of-web-server> | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}

If you see this response, our control server was successfully able to connect to the minion server via ssh. We have a blank minion connected and we are ready to go.

Creating our first playbook

A playbook is a YAML file which contain a number of YAML structures called “plays”. Plays are a named parent structure which contain a number of “task” definitions. A task is an individual command or directive that is sent to a minion server. A play is a collection of tasks that are organized under a single name. A playbook is a collection of plays in a single named file.

Plays and playbooks also have attributes which give you the ability to specify which hosts in your inventory would like the tasks to run on.

In the /etc/ansible folder lets create a file called playbook.yml

touch /etc/ansible/playbook.yml

Now lets open the file and add some “plays”.

vi /etc/ansible/playbook.yml

Our first play will be very simple and will be made to install 3 basic packages as an example. We will be installing vim, dnsutils, and git.

Paste the following YAML into the playbook.yml file.

---
- name: install basic packages
hosts: webservers
tasks:
- name: "Installing Vim"
apt: pkg=vim
- name: "Installing DNS Utils"
apt: pkg=dnsutils
- name: "Installing Git"
apt: pkg=git

As you can see the top of the file has three hyphens. These indicate that the following text is in YAML format.

After that the first YAML attribute is the name of our play. We can call this anything we want, but we want the name to describe the overall purpose of all grouped tasks that are nested within.

Second we have the hosts attribute. This tells Ansbile which group from our inventory to run the following tasks on. If we replaced webservers with all it would run on all the servers in our inventory.

Third, we have the tasks attribute which is the parent of all the tasks we want to run for this specific play.

As you can see, each tasks under tasks has two required attributes. One is the name of the task, which we can choose to name whatever we like. The second part of the task tells Ansible which module we are invoking. Depending on the module we want to use there will be different required information to provide along with the module name.

In this instance we are using the apt module.

A list of all the available modules, sorted by category can be found here.

https://docs.ansible.com/ansible/latest/modules/modules_by_category.html

To use the apt module. Two attributes are required.

- name: "Installing Git"
apt:
pkg: git

The top name attribute is your chosen name for the task. the second attribute apt is the module name. Following that are the required and optional attributes for that given module.

To apply this playbook.

ansible-playbook playbook.yml

This will apply the playbook to all the hosts in the [webservers] group in the inventory. You will be given a report showing the status of each host and the tasks that had been run.

PLAY [install basics] **********************************************************TASK [Gathering Facts] *********************************************************
ok: <ip-address-of-web-server>
TASK [Installing Vim] **********************************************************
changed: <ip-address-of-web-server>
TASK [Installing DNS Utils] ****************************************************
changed: <ip-address-of-web-server>
TASK [Installing Git] **********************************************************
changed: <ip-address-of-web-server>
PLAY RECAP ********************************************************************
<ip-address-of-web-server> : ok=1 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

As you can see from the PLAY RECAP at the bottom of the output, there were 3 changes made to the minion server. There was 1 OK result from the Ansible control server gathering initial data from the minion before applying our playbook.

A cool feature of Ansible is that it will not attempt to rerun tasks that have already been successfully run. If we run the playbook again you will see this in action.

PLAY [install basics] **********************************************************TASK [Gathering Facts] *********************************************************
ok: <ip-address-of-web-server>
TASK [Installing Vim] **********************************************************
changed: <ip-address-of-web-server>
TASK [Installing DNS Utils] ****************************************************
changed: <ip-address-of-web-server>
TASK [Installing Git] **********************************************************
changed: <ip-address-of-web-server>
PLAY RECAP ********************************************************************
<ip-address-of-web-server> : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

As you can see at the bottom, 4 tasks completed with OK status and there were zero changed servers.

You have now learned how to connect a server to your Ansible control server and install packages using the apt module. In the next tutorial we will be using Ansible roles to better organize our control server.

Links:

https://www.ansible.com/overview/how-ansible-works

https://www.linode.com/docs/getting-started/

https://docs.ansible.com/ansible/latest/modules/modules_by_category.html

--

--