This is a set of loosely-related remarks and observations, accrued due to recent use of Ansible in several work and personal projects (and on the latter note, I made a thing).
The entry is mostly intended as a writing exercise, so if you’re evaluating Ansible at the moment, please keep this in mind.
A word of Introduction
Ansible, like Chef, Puppet and Salt, is configuration management software. Despite my best intentions to reach the widest audience possible, providing a comprehensive overview of the field would require creating a whole series of blog posts.
Therefore, wanting to convey the following statements in reasonable time, I’m forced to limit the target readership to those that posses basic knowledge of the subject. In other words, if you are unfamiliar with the subject, please do take your time to browse the included links. Sorry!
Ansible - the good, the bad, the ugly
All those remarks are made by someone who is strictly more a dev than an op, so the things I’m writing about here may or may not apply to your situation as much as they did to mine.
Also, the entry was writen when going through the Through of Disillusionment, halfway to the Slope Enlightenment, and therefore may sound more negative than intended.
Good: Workerless setup
The absolutely wonderful thing about Ansible is its agentless architecture - you don’t need to setup anything on the
services machines, other than a valid SSH connection to a user (usually with possible
sudo access). No special nodes
requiring additional setup (like in Chef), nothing of the sort.
This in fact makes it very convenient to bootstrap setups for CI and the like, or even a quasi Inversion-of-Control setup,
Such a feature may seem like a small thing, but it reduces the error rate during the "metagame" of setting up your servers.
Good: Easy to understand syntax
Ansible uses YAML with embedded Jinja2 for its configuration definitions, and most of the basic stuff can be expressed that way. Getting the majority of desirable output defined is pretty straightforward, once you learn the basics.
Bad: …that’s sometimes not as intuitive as it should be
A big stumbling block I’ve encountered is correctly specifying the conditions in
when blocks (saying when to execute
a task) and similar ones. Truth be told, even after viewing the parsing source code for the "playbooks", I’m
still not entirely confident on what is and isn’t allowed.
I think this is due to the fact that the Jinja2-based syntax sits pretty squarely in the Uncanny Valley for someone with an off-and-on Python background. In effect, you end up writing those conditions like in Python, which works… about 90% of the time. The remaining 10% will piss you off to no end.
Good: Has a strong focus on idempotency
Pretty much a given for all modern configuration management software, but nevertheless I could excitedly rave and rant about that at you the entire day - it’s awesome that Ansible specifically focuses on what the state should be, rather than what tasks to do.
Good: Trivial to customize
To recap, here’s how config management works in Ansible:
the unit of work is a task, meant to encapsulate a single "end-state" quantum, i.e. something that should be ensured to be fulfilled once this task is done.
tasks use modules, which do the actual grunt work and can be implemented in most languages (a lot of them use Python, obviously since Ansible is written in that). There exists a cornucopia of Ansible built-in modules, from user management through ensuring a given is in a file, to EC2 instance setup.
tasks can be grouped into roles, which can also contain common variables, custom modules etc..
task and role mixes are codified into playbooks, which describes what your actual configuration should look like. You "run" the playbooks on your "inventory" to achieve that desired state.
You’ll notice that such a structure allows you to modularize your configuration management logic as you see fit. That includes creating several "internal" modules for complex actions and sticking them into your roles.
Bad: …but no code reuse for Python modules
Funilly enough, due to how Ansible is structured, you cannot have "common" code files for Python-based modules.
That sucks, but is probably an edge case for most stuff.
Good: Good introductory documentation
Ugly: …with no formal sections
I fail to see, in the documentation, a "Big Picture" overview of how the various components of an Ansible definition are structured.
Good: A globally shared role repository
Ugly: …very nascent in the current state
However, especially if you display perfectionist tendencies , you will spend quite a bit of time examining the roles for the functionality your require.
One problem is that, while a rating system exists, it’s severely underused, and you have to fish for the well-made roles.
The former offer a definitely correctly functioning role, but make a metric f-ton of assumption about what a given piece of setup software is going to operate as. The latter, meanwhile, while not being entirely correct idempotency-wise, allow for very diverse configuration variants.
The general picture that I’ve painted hopefully shows a framework with a number of nits that you can pick, but built on solid foundations nevertheless. Those solid foundations will provide a payoff as the framework grows and matures, eliminating the smaller problems along the away. Be aware of the shortcomings, but rest assured that I recommend you check out Ansible for you configuration management needs.