Ansible Roles


In this video we will look at Roles inside Ansible.

Roles are really all about keeping ourselves organised.

If left unchecked, our Playbooks can quickly become large and unwieldy.

Ansible uses the concept of Roles to address this problem. By following a standardised directory structure, we can keep our Ansible project structure nice and tidy, along with maintaining some semblence of sanity and order.

So really, a Role is nothing more than a more specific Playbook. We already have covered the basics of Playbooks, and a Role takes the concept of a Playbook and applies it to a common set of tasks to achieve a specific thing.

That sounds quite vague. An example may serve us better.

Let us imagine we have a list of common tasks we always want to perform on every server we manage.

We want to install some software (git, curl, htop, whatever), we want our authorised SSH keys to be set so we don't have to muck about with passwords, and it'd be quite nice if our User accounts were created, along with our standard home directory structure.

We could think about these as our 'Common' tasks.

This would make a perfect Role. The 'Common Role'.

With a Common role defined, we can then remove all that standard set up from every Playbook we have, and simply request that the Playbook includes that Role when it executes.

In many ways, it's pretty similar to Traits in PHP.

Ansible Galaxy - Home of Many, Many Roles

Now, we will come back to Ansible Galaxy in more depth in a future video, but I want to cover it here - briefly - because of its relation to Roles.

I would strongly encourage you to browse the Ansible Galaxy as it's really what piqued my interests in Ansible, when compared to other similar infrastructure automation systems like Chef and Puppet.

Ansible Galaxy is like the Apple App Store for geeks. Think of any 'thing' you might want to play with - Redis, Jenkins, Blackfire, Logstash, NodeJs - and there will, more likely than not, be a Role created by a friendly community member to download and use with almost no effort.

Of course, life is never that easy, and many of the Roles on Ansible Galaxy will need at least a basic grasp of the software you are trying to install, before you can make the most of the Role in your own setup.

Again, we will come back to Ansible Galaxy in more detail in a future video.

Role Your Own

As already mentioned, by following this standard Role directory structure, we can leverage the powers of Ansible to organise our infrastructure into subsets of repeatable tasks, which can be easily read and understood by our Playbooks.

We covered using ansible-galaxy init your-role-name-here in the video on using Git with Ansible, but not a lot was said on why we were doing that.

Using ansible-galaxy init will generate us a standardised directory structure for our Role.

We can then populate the individual files and folders with our own data, and bonza, we have a working Role.

I recommend following the method I used in the Git with Ansible video as we likely won't be working locally on the server, so won't have easy access to the ansible-galaxy command every time we want to create a new Role.

Simply, if we create our Role using ansible-galaxy then all the files we need - /tasks/main.yml, /handlers/main.yml, vars/main.yml, etc, will be created for us already, and we can just copy and paste our existing Playbook entries into the files and life will be good.

Creating those files by hand isn't a problem - nor does ansible-galaxy do anything particularly special - it's just a time saver.

Example

In the video we migrate from having all our Apache set up - tasks and handlers - in one Playbook, and instead, we start moving these blocks of config (the tasks block, the handlers block) into their own yaml files: roles/apache/tasks/main.yml and roles/apache/handlers/main.yml.

The actual file contents don't change, only their locations.

We start off with our original apache-playbook.yml - and remember, this is merely a demonstration, this won't get you a working Apache install at this stage:

First of all, we need to create our Apache Role:

cp -R roles/__template__ roles/apache 

That creates us the desired role structure.

apache-playbook.yml contents:

---
- hosts: all

  vars:
    - website_dir: /var/www/oursite.dev/web

  tasks:
    - name: Install Apache
      apt: pkg=apache2 state=installed update_cache=true
      notify: 
        - start apache

    - name: Create website directory
      file: dest={{ website_dir  }} mode=775 state=directory owner=www-data group=www-data
      notify:
        - restart apache

  handlers:
    - name: start apache
      service: name=apache2 state=started

    - name: restart apache
      service: name=apache2 state=restarted

And we then extract the tasks section into roles/apache/tasks/main.yml.

Notice, we don't need the tasks section heading.

---
- name: Install Apache
  apt: pkg=apache2 state=installed update_cache=true
  notify: 
    - start apache

- name: Create website directory
  file: dest={{ website_dir  }} mode=775 state=directory owner=www-data group=www-data
  notify:
    - restart apache

Next, extract the handlers section into roles/apache/handlers/main.yml.

Again, we don't need the handlers section heading.

---
- name: start apache
  service: name=apache2 state=started

- name: restart apache
  service: name=apache2 state=restarted

Now, back in apache-playbook.yml, we can remove the entire tasks and handlers sections, and replace them with roles.

We use the standard yml syntax for listing our roles, of which we could have more than one.

---
- hosts: all

  vars:
    - website_dir: /var/www/oursite.dev/web

  roles:
    - apache

We could go further and extract the variables out also - it's the exact same process.

Running our apache-playbook.yml still works exactly the same as before the change:

ansible-playbook apache-playbook.yml -k -K -s

But note, the output changes ever so slightly.

We will now see the Role name as part of the task:

GATHERING FACTS ***
ok: [127.0.0.1]

TASK: [apache | Install Apache] ***
ok: [127.0.0.1]

*cut*

Notice the [apache | Install Apache] line - this now takes the format of:

[role name | task name]

This can be helpful for identifying where things are as your Playbooks grow in size and complexity.

Further Reading

Of course, there is much more to be learned about Roles, but these basics are enough to get started.

Be sure to check out the official documentation, as well as Ansible Galaxy. You can use the Roles you find on Ansible Galaxy to learn from, as each one will list its source code - usually via Github - so you can pry inside and find out how things are achieved.

Code For This Course

Get the code for this course.

Episodes