Ansible Part IV: Roles Overview

You may find Ad-hoc mode (from Part II) easy to use on day-to-day tasks such as for quick systems checks or when updating a config file on multiple systems. Stepping up simple ad-hoc commands are Ansible playbooks (from Part III) and Ansible roles which are very powerful ways to utilize Ansible’s features.

When most people think of Ansible, they tend to think of the roles feature, because it’s the way most Ansible code is shared. So first, it’s important to understand the relationship between ad-hoc mode, playbooks and roles. On this section we will have an introduction on how to use Ansible roles.

Ad-hoc Mode (a little review)

Ad-hoc mode is simply a one-liner that uses an Ansible module to accomplish a given task on a set of computers. Something like:

# ansible all_servers -b -m apt -a "name=vim state=latest"

This will install vim on every computer in the all_servers group. The -b signals to elevate privilege (“become” root), the -m means to use the apt module, and the -a says what actions to take. In this case, it’s installing the latest version of vim.

Usually when we use ad-hoc mode to install packages, I’ll follow up with something like this:

# ansible all_servers -b -m service -a "name=apache2 state=started enabled=yes"

This one-liner will make sure that the apache2 service is running and set to start on boot automatically. Now, when there are new rollouts/deployments or patches which requires a lot of commands, it makes sense to create a playbook.

Playbook Mode (a little review)

Playbooks are YAML (Yet Another Markup Language) formatted text files that contain a list of things for Ansible to accomplish. For example, to install Apache on a lab full of computers, you’d create a file something like this:

---
- hosts: webservers
  tasks:
  - name: install apache2 on CentOS
    yum: name=httpd state=latest
    notify: start httpd
    ignore_errors: yes
- name: install apache2 on Ubuntu
    apt: update_cache=yes name=apache2 state=latest
    notify: start apache2
    ignore_errors: yes
  handlers:
- name: start httpd
    service: name=httpd enable=yes state=started
- name: start apache2
    service: name=apache2 enable=yes state=started

This contains a single play that tries to install httpd with yum and apache2 with apt. If the webservers is a mix of CentOS and Ubuntu machines, one or the other of the installation methods will fail. That’s why the ignore_errors command is in each task. Otherwise, Ansible would quit when it encountered an error. It would be much better to create conditional statements that would allow for a graceful exit on incompatible platforms.

Roles

Playbooks that are more complex and do more things tend to evolve into a “role” in Ansible. Roles aren’t really a mode of operation; rather, roles are an integral part of playbooks. Just like a playbook can have tasks, variables and handlers, they can also have roles. To put simply, roles are just a way to organize the various components referenced in playbooks. It starts with a folder layout:

 roles/
  webserver/
    tasks/
      main.yml
    handlers/
      main.yml
    vars/
      main.yml
    templates/
      index.html.j2
      httpd.conf.j2
    files/
      ntp.conf

Ansible looks for a roles folder in the current directory, but also in a system-wide location like /etc/ansible/roles, so you can store your roles to keep them organized and out of your home folder. The advantage of using roles is that your playbooks can look as simple as this:

---
- hosts: webservers
 roles:
    - webserver

And then the “webserver” role will be applied to the group “webservers” without needing to type any more information inside your playbook. When a role is specified, Ansible looks for a folder matching the name “webserver” inside your roles folder (in the current directory or the system-wide directory). It then will execute the tasks inside webserver/tasks/main.yml. Any handlers mentioned in that playbook will be searched for automatically in webserver/handlers/main.yml. Also, any time files are referenced by a template module or file/copy module, the path doesn’t need to be specified. Ansible automatically will look inside webserver/files/ or /webserver/templates/ for the files.

Basically, using roles will save you lots of path declarations and include statements. The organization creates a standard that not only makes it easy to figure out what a role does, but also makes it easy to share your code with others.

Ansible Galaxy

On a small scale, roles are a great way to share with your coworkers, especially if you have roles that are customized specifically for your environment. Since many of environments are similar, roles can be shared with an even wider audience—and that’s where Ansible Galaxy comes into play.

If you head over to the  https://galaxy.ansible.com/ you’ll find a ton of online repository for shared roles. You can try searching for Roles and look for apache and sort it by the number of downloads. Try to browse the roles and download the role for installing apache.

Using ansible-galaxy to Install Roles

It’s possible to download an entire repository and then unzip the contents into your roles folder. Since they’re just text files and structured folders, but it’s less convenient than using the tools built in to Ansible.

Before you download the roles, you should view the codes and check readme for the requirements and playbook instructions.

In order to use Ansible to download a role, you need to do this:

# sudo ansible-galaxy install geerlingguy.apache

Notice two things. First, you need to execute this command with root privilege. That’s because the ansible-galaxy command will install roles in your system-wide roles folder, which isn’t writable by default if you use a regular user account. Second, the role names format is username.rolename, which is also how you reference the role inside your playbooks.

You can also search from the command line by using ansible-galaxy’s search command.

# ansible-galaxy search apache 

Once you install a role, it is immediately available for you to use in your own playbooks, because it’s installed in the system-wide roles folder – /etc/ansible/roles. So now, if you create a playbook like this:

# cat ansible-playbook apache-playbook.yaml
---
- hosts: webservers
  roles:
    - ansible-role-apache-master

Apache will be installed on all my webservers systems, regardless of what distribution they’re using.

 # ansible-playbook apache-playbook.yaml
PLAY [webservers] ***********************************
 
TASK [Gathering Facts] **************************************
ok: [ansible3]
ok: [ansible2]
 
TASK [ansible-role-apache-master : Include OS-specific variables.] *****************************************
ok: [ansible2]
ok: [ansible3]
 
TASK [ansible-role-apache-master : Include variables for Amazon Linux.] ************************************
skipping: [ansible2]
skipping: [ansible3]
 
TASK [ansible-role-apache-master : Define apache_packages.] ************************************************
ok: [ansible2]
ok: [ansible3]
 
TASK [ansible-role-apache-master : include] **********************************************
included: /etc/ansible/roles/ansible-role-apache-master/tasks/setup-Debian.yml for ansible2, ansible3
 
TASK [ansible-role-apache-master : Update apt cache.] ******************************************************
ok: [ansible2]
ok: [ansible3]
 
TASK [ansible-role-apache-master : Ensure Apache is installed on Debian.] **********************************
changed: [ansible2] => (item=[u'apache2', u'apache2-utils'])
changed: [ansible3] => (item=[u'apache2', u'apache2-utils'])
 
TASK [ansible-role-apache-master : Get installed version of Apache.] ***************************************
ok: [ansible3]
ok: [ansible2]
 
TASK [ansible-role-apache-master : Create apache_version variable.] ****************************************
ok: [ansible2]
ok: [ansible3]
 
TASK [ansible-role-apache-master : include_vars] ***********************************************************
skipping: [ansible2]
skipping: [ansible3]
 
TASK [ansible-role-apache-master : include_vars] ***********************************************************
ok: [ansible2]
ok: [ansible3]
 
TASK [ansible-role-apache-master : include] ****************************************************************
included: /etc/ansible/roles/ansible-role-apache-master/tasks/configure-Debian.yml for ansible2, ansible3
 
TASK [ansible-role-apache-master : Configure Apache.] ******************************************************
ok: [ansible3] => (item={u'regexp': u'^Listen ', u'line': u'Listen 80'})
ok: [ansible2] => (item={u'regexp': u'^Listen ', u'line': u'Listen 80'})
 
TASK [ansible-role-apache-master : Enable Apache mods.] ****************************************************
changed: [ansible3] => (item=rewrite.load)
changed: [ansible2] => (item=rewrite.load)
changed: [ansible3] => (item=ssl.load)
changed: [ansible2] => (item=ssl.load)
 
TASK [ansible-role-apache-master : Disable Apache mods.] ***************************************************
 
TASK [ansible-role-apache-master : Check whether certificates defined in vhosts exist.] ********************
 
TASK [ansible-role-apache-master : Add apache vhosts configuration.] ***************************************
changed: [ansible3]
changed: [ansible2]
 
TASK [ansible-role-apache-master : Add vhost symlink in sites-enabled.] ************************************
changed: [ansible2]
changed: [ansible3]
 
TASK [ansible-role-apache-master : Remove default vhost in sites-enabled.] *********************************
skipping: [ansible2]
skipping: [ansible3]
 
TASK [ansible-role-apache-master : Ensure Apache has selected state and enabled on boot.] ******************
changed: [ansible3]
changed: [ansible2]
 
RUNNING HANDLER [ansible-role-apache-master : restart apache] **********************************************
changed: [ansible3]
changed: [ansible2]
 
PLAY RECAP ****************************************************
ansible2        : ok=16   changed=6    unreachable=0    failed=0
ansible3        : ok=16   changed=6    unreachable=0    failed=0

Creating Your Own Roles

Since you easily can create a roles folder and then create your own roles manually inside it, but ansible-galaxy does give you a shortcut by creating a skeleton role for you. Make sure you have a roles folder, then just type:

# ansible-galaxy init roles/rolename 

Then you’ll end up with folder structure for your new role. Then you can edit the files on each folder as you need them.

Sharing Your Roles

You can also share your  roles on Ansible galaxy too. You just have to setup your GitHub account for the role. You can use ansible-galaxy to “import” them into the publicly searchable Ansible Galaxy site. You first need to authenticate:

# ansible-galaxy login

Before you try to log in with the command-line tool, be sure you’ve visited the Ansible Galaxy website and logged in with your GitHub account.

# ansible-galaxy import githubusername githubreponame 

The process may take a while, so you can add the -no-wait option if you want, and the role will be imported in the background.

Where to go from here?

Playbooks and roles are usually where people focus their attention in Ansible, but for quick tests or tasks, you should take advantage of ad-hoc mode. Ansible in some ways is just another DevOps configuration management tool, but for those who are coming from a System Administrator background which traditionally accustomed to Bash scripts, Ansible feels like a tool designed for them. From here on, you should try to learn Ansible enough so you can determine whether it fits into your workflow and how you can integrate it to your current infrastructure.

That completes the four part series for Ansible.

Ansible Part I: Installation and Setup
Ansible Part II: Using Modules
Ansible Part III: Using Playbooks
Ansible Part IV: Roles Overview

———————————

– masterkenneth

Leave a Reply

Your email address will not be published. Required fields are marked *