How I use Ansible

March 14th, 2019

What is Ansible?

Directory structure

File management is important in any project. Keeping things clean and organized in a sensible way makes life easier for everyone involved. Ansible is no different.

An example project looks like this:

inventories/
	production/
		group_vars/
			web/
				vars.yml # contains variables for the web group
				vault.yml.gpg # contains encrypted secrets
		hosts # inventory file for production servers
	development/
		group_vars/
			web/
				vars.yml # contains variables for the web group
				vault.yml.gpg	# contains encrypted secrets
		hosts # inventory file for production servers

playbooks/
	provision.yml # master playbook that provisions everything by including the rest of the playbooks
	web.yml # playbook that provisions just the web group

roles/
	jordanknott.common/
		tasks/
			main.yml
		handlers/
			main.yml
		templates/
			service.conf.j2 # jinja2 templates end with .j2 extension

keyrings/ # BlackBox folder for handling encrypted secrets

ansible.cfg # contains some settings for ansible
requirements.yml # describes role dependencies from ansible galaxy or Git
Vagrantfile # Vagrantfile to setup a local dev machine

While some advise putting your playbooks in the top level directory, I like to keep all of my playbooks in their own folder, hence the playbooks directory.

I also like to namespace my roles. When you download a role from Ansible Galaxy, they are namespaced so it only makes sense to keep things the same.

Ansible Galaxy

One of the great things about Ansible, is Ansible Galaxy. It's a community repository of roles that handle everything from setting up MySQL to setting up a Jenkins instance.

You can download the roles from Galaxy, using the ansible-galaxy install command.

Custom Roles

While Ansible Galaxy has many roles, sometimes you need some custom tasks done.

For setting up a basic role directory structure, I like to use the ansible-galaxy init ${ROLENAME} command.

Managing Roles

There are many ways to manage roles (both custom and ones from Galaxy).

If all of the roles are in a Git repository somewhere, then one option is to use Git submodules. While it defintely works, submodules bring a certain amount of complexity into a project.

A second option is through a requirements.yml file (checkout the docs for the exact format) and keeping the roles directory out of the VCS.

The second option is the one that I go with though the first option does have some allure.

Aliases

I love Ansible but the command names it uses are pretty wordy. To save some keystrokes, I have a couple shell aliases that I use.

The main three are: an-p, an-pd, and an-gi.

The first one, an-p, is used to run a playbook using the development hosts file. It expands to ansible-playbook.

The second one, an-pd, is used to run a playbooks with the product host file. It expands to ansible-playbook -i inventories/production/hosts.

The final alias, an-gi, expands into ansible-galaxy install.

Managing secrets

Part of configuration management is handling secrets such as database credentials, SSL certifications, etc.

While you could just leave everything in plaintext (meaning anyone can read it), that's certainly not very secure.

The next step up from leaving things in plaintext is encrypting them!

Ansible even has a built in solution for doing so, called ansible-vault.

While ansible-vault does look nice it encrypts secrets using what a single password. That's fine if you're a team of one, but when you start adding more people it becomes a nightmare to maintain.

In place of using ansible-vault, I use a tool called blackbox from the StackExchange team. It uses a special mode of GPG to encrypt files that allows multiple people to decrypt.

If someone is removed from the team, it's a simple matter of removing them from the admin list and then re-encrypting the secrets (as well as revoking the existing credentials which you SHOULD be doing).

To get started using blackbox, checkout the getting started section.