A quick overview of Ansible
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"