blog06: Ansible!

3 minute read

This past week was mostly be playing around with Ansible. I’ve been tasked with orchestrating new hardware, and tinkering with database values to squeeze out speed.

Ansible seemed like a nice tool for this task: it was easy to get started (after learning a few terms). After using it for a few days, it seems like a nice balance between templating and shell scripting.

My first thought after looking into Ansible: why not just use shell scripts, and tons of ssh? The more I thought about it, it becomes a problem of scale and maintenance. Instead of shell scripts, Ansible tasks and plugins aren’t ad-hoc, and they aren’t maintained by me. 🙂 Having a way to run a series of commands, set values, etc., that’s backed by Red Hat devs, means I have more trust in what I’m writing, and trust in the results.


There’s a few terms to learn as you get started. But they’re pretty simple.

  • task: An action to perform. Install a package, delete a line from a file, start a service, et al.
  • role: A bundle of tasks. For example: installing a database package, its dependencies, and then configuring it.
  • playbook: A list of roles to run, against a list of hosts. This is the “action” bit: perform the tasks in these roles on these hosts.

Hosts: the target machines

Hosts are listed in Ansible’s hosts file, typically at /etc/ansible/hosts. This is a list of hostnames or IP addresses, placed in groups.



This grouping lets you run different roles against different hosts in a playbook. For example, a role to set up the database should likely be run against the databases group of hosts, and not the webservers group.

A simple role

Roles go in the roles folder, under /etc/ansible/roles. For an example role called test, we’ll make a folder in roles called test. Any tasks that test performs will be put in a tasks folder under test.

Whew! Ok. So, at last, we can start a YAML file, at /etc/ansible/roles/test/tasks/main.yml.

I’m running Debian on my webserver group, and want to make sure Emacs is installed, for all my editing needs. Therefore, my test tasks will only consist of one task:

# main.yml: tasks list for the test role
- name: Install Emacs
    name: emacs
    state: present

Our tasks list has a single entry. Each entry is named with the name tag, and the task’s module is included as the other tag. In this case, we’re using apt to install the emacs package. After this task, the state of the package should be present.

A simple playbook

A playbook must include hosts, and roles. In our case, both of these are simple:

# playbook.yml: Configure webservers with the test role
- hosts: webservers
- roles:
    - test

This should go in /etc/ansible/playbook.yml.

Run it with ansible-playbook playbook.yml, while sitting in the /etc/anisble directory.

Depending on how you SSH into your hosts, you may need to provide a password, or tell Ansible which SSH keys to use for which host. All the options for logging into hosts are available with ansible-playbook –help.

Ad-hoc commands

Another fun Ansible tidbit is informal commands. These aren’t supposed to be run regularly, like playbooks, but they’re useful for learning about your environment.

These are run with the ansible command. For example, to ensure all Ansible hosts can be SSHed into, run: ansible all -m ping. All your hosts should reply with a pong, if all is well.

Wrapping up

I’ve probably put half a dozen hours into Ansible now, and already have my database servers created and configured automatically. This involved exploring Ansible’s template module, some repository adding, and GPG key accepting. But all in all, not too bad! My nodes install and configure themselves, then join the DB cluster, as soon as I point Ansible at them.

I feel like this will make deployment, redeployment, and reconfiguration much easier in the future.