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
is a list of hostnames or IP addresses, placed in groups.
[databases] dbhost1 dbhost2 dbhost3 [webservers] webserver1 webserver2
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
test, we’ll make a folder in roles called
test. Any tasks that
performs will be put in a
tasks folder under test.
Whew! Ok. So, at last, we can start a YAML file, at
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 apt: 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
emacs package. After this task, the state of the package should be
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
Run it with
ansible-playbook playbook.yml, while sitting in the
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
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
pong, if all is well.
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.