A quick overview of Ansible

Levente Balogh
4 min readDec 22, 2018

--

I always had a problem completely grasping how Ansible works and to create a mental map in my head how its parts are connected together to make a single piece. The tutorials are either super long, or they assume a preliminary knowledge on the subject, which I didn’t really have.

That’s why I read Ansible — From Beginner to Pro by Michael Heap, which is an easy read and you get almost everything from it that you need.
Let’s share what I got from it.

Table of Contents

Playbooks
Inventory Files
Roles
Parameterizing Playbooks
Blocks
Ansible Vault

Playbooks

Playbooks are the main entry-point in Ansible for encapsulating deploy scenarios. They are actually just YAML files that use special terminology to tell Ansible what it should do.

- hosts: all
tasks:
- name: Check connection
ping

Using modules inside tasks
Ansible has a lot of available modules that you can use inside tasks.
E.g. installing something with apt has never been easier:

- hosts: all
tasks:
- name: Install PHP
apt: name=php5-cli state=present

Running a task with root privileges
It is as easy as adding become: true to your task.
Also can be added to the top level, so all tasks will run as root.

- hosts: all
tasks:
- name: Install PHP
apt: name=php5-cli state=present
become: true

Running the same task for multiple items
Using the with_items property you can define multiple items
to run your task with. You will be able to reference the current item as {{item}}.

- hosts: all
tasks:
- name: Install PHP
apt: name=php5-cli state=present
with_items:
- php5_cli
- nginx

Inventory Files

An inventory file is just a list of hosts that you would like to run your playbooks against. This can be a separate file called hosts for example, that we will specify when we run the playbook.

They can be in two different formats: INI and JSON.

Some INI examples:

; A simple list of hosts
host1.example.com
host2.example.com
host3.example.com
; Defining a custom SSHD port for a host
host1.example.com:50822
; Specifying the login user
host1.example.com ansible_user=bob
; Setting a variable available across all playbooks
host1.example.com vhost=foo.com
; Inventory Groups
; You can reference these by their names
[web]
host1.example.com
host2.example.com
[database]
db.example.com
; Setting variables for specific inventory groups
[web:vars]
apache_version=2.4
bar=true

Roles

You can think of a role as a playbook that is split up into multiple different files. You can have a file for variables, one for tasks, one for handlers.
You cannot run a role though, you need to include it into a playbook.

Running a role from a playbook
Simply just list the name of the roles you would like to run.

- hosts: all
roles:
- install_nginx
- install_php

Directory Structure for a role
Every role has it’s own directory under roles/ with the name of the role.
Most of the subfolders are optional except tasks.

defaults/main.yml Define default values for your variables in this role.
files/… Static files required for your role. They only can be copied.
handlers/main.yml Define your handlers here, like “Restart Nginx”.
tasks/main.yml Actions defined here will be run when your role runs.
templates/… Contains files that need to be processed as jinja2 templates.

playbook.yml
roles/

├── install_nginx/
│ ├── defaults/
│ | └── main.yml
│ ├── files/
│ | └── ...
│ ├── handlers/
│ | └── main.yml
│ ├── meta/
│ | └── main.yml
│ ├── tasks/
│ | └── main.yml
│ ├── templates/
│ | └── main.yml
│ └── vars/
│ └── main.yml

Dependencies between roles
It can easily happen that you would like to run certain roles before others, and luckily this is quite easy to do with Ansible:

dependencies:
- mheap.common
- mheap.php
- mheap.mysql
- mheap.nginx

Parameterizing Playbooks

Variables in Ansible are global.
This means that whether you declare a variable in a role, in a playbook or anywhere else it can be used by all roles and all other playbooks.

Because of this variables inside a role are generally prefixed with the role name.

Referencing a variable
{{ variable_name }}

Set variables inside a Playbook
These will be available in the roles as well.

- hosts: all
vars:
your_name: World

Variable files
You can instruct Ansible to read variables from a file while processing a Playbook:

- hosts: all
vars_files:
- my-variables.yml

Role variables
You can specify variables for a specific role as well.

- hosts: all
roles:
- role: mheap.wordpress
database_name: michaelwp
database_user: michaelwp
database_password: bananas18374

Blocks

Blocks make it possible to group tasks. Why is it good for us? Two reasons:

  • Common variables and directives: they can be specified once and all tasks inside the block are going to inherit them.
  • Error Handling: we catch and react on failed tasks inside a block with the rescue keyword.
# Exampletasks:
- name: Install Apache
block:
- yum:
name: "{{ item }}"
state: installed
with_items:
- httpd
- memcached
- template:
src: templates/src.j2
dest: /etc/foo.conf
- service:
name: bar
state: started
enabled: True
become: true
become_user: root

Ansible Vault

It is a command file-encryption tool for Ansible which uses the AES cipher.

Why would you use it?
Let’s say you would like to have the credentials next to the project but you wouldn’t like to make them public. In this case you encrypt them and you only have the password for decrypting them available on the target hosts.

The following command asks for a password to encrypt the file with:
$ ansible-vault encrypt roles/my-role/vars/main.yml

Then you can specify where Ansible should look for the passwords:
$ ansible-playbook ... --vault-password-file "/path/to/password-file"

--

--

Levente Balogh

I think one of the most important thing in our life is curiosity. Stay curious, understand truly how things work and become a master craftsman. This is my goal.