Earlier this year I intended to do a mulit-part blog series on Ansible. If you are not familiar with Ansible it’s basically a configuration management tool that’s part of a config mangement/infrastructure as code approach to managing your infrastructure.
In the past I’ve worked extensively with Puppet, SaltStack and Chef but have never played around with Ansible until about a year ago. At a high level Ansible is a tool written in Python with “playbooks” written in yaml. One of the great advantages to Ansible is that it’s got a fairly low barrier to entry and can be one giant self contained playbook or can be used in a broader configuration management strategy, which is what I intend to touch on throughout this series on Ansible. One of the greatest parts about Ansible is all you need are a couple of Python dependancies that are likely pre-installed with your distribution of Linux as well as an SSH connection and a user with sudo permissons if you are using it to configure configuration files and install packages. There is a paid version of Ansible but frankly the free version covers every use case that I need for it, but your mileage and support needs may be different from mine.
One of the ways in which Ansible is quite different than other config management tools is that it is agentless. This can be an advantage if you are working in an environment where you do not want changes to be automatically applied or if you are worried about the resources used on the box by an agent. Generally speaking there isn’t really a right or wrong way to structure your Ansible project which is both the beauty and the difficulty of Ansible. If you want to build a scalable well thought out configuration management tool not skipping foresight and planning is essential. Much like Chef’s Marketplace, or the Puppet forge there is Ansible Galaxy where you can find pre-built Ansible roles, however there really aren’t as many available as there are in Chef or Puppet and quality varies greatly between them. Currently in my existing role the only 2 Galaxy roles I’ve used are the DataDog and Zabbix agent roles as those met my needs and are rather well documented and straightforward. Galaxy roles can also offer a good insight into the ways in which to structure an Ansible role and how to make use of their various pieces.
While this is a general overview I promise the coming installments will have more to offer including instructions on installing Ansible, building a basic project, and building out roles, playbooks and inventory files. Before I wrap up this post I want to cover the basic components to our Ansible strategy that I’ll be moving forward with in this series.
Inventory: The inventory is a file that can either be structured as an INI file or a yaml file. An inventory file consists of a set of groups, the hosts they contain, host level variables, as well as group variables or global variables. I’ve found the yaml file to be a better structure because the rest of what we’re working with is yaml which makes it a familiar format and you can use encrypted variables from Ansible vault within the inventory file. In general I’ve found it makes the most sense to structure inventory files around environments (dev, qa, uat, stage, production, etc) and in cases where multiple regions are involved using an inventory file for each region as this will help to keep things more organized.
Vault: Ansible vault isn’t so much part of the file structure of a project but rather an important tool. Ansible Vault lets us encrypt strings so that we can safely store values like AWS key pairs, DB creds, and more in version control without having them exposed in plain text. This of course means the vault password you use should not be stored in version control as this would be problematic to security.
Roles: Roles are not a requirement within Ansible but they are incredibly useful if you are planning to scale Ansible. Roles make the most sense to divide into logical functions say Web, DB, DataDog, Varnish, Users, or whatever you may have in your server farms. Within these logical roles we can handles things such as installing, adding configuration files, making sure that services are enabled to autostart and that services are running. If you intend to use similar configurations across multiple environments we will want to be sure to templatize and turn things into variables. Variables can be associated at the role level, playbook level, or inventory level. We’ll see more later on how to decide what’s the best place to put things.
Playbooks: The actual runbook for what Ansible is supposed to do. This is the essential bit of Ansible, as you can run your entire config management within a playbook, or as I will show you we can use this to define server roles such as webservers, dbservers, etc, and include any relevant variables, some sanity checks around execution strategy, what method of becoming sudo, and listing which roles to include in the playbook. In general my preference is to just include a few housekeeping items at the top and then a yaml list of roles to include, as this scales well, keeps playbooks clean and readable. One thing to note about Ansible is unlike Puppet the execution order of an Ansible playbook is top to bottom. You will want to keep this in mind as you determine which order to apply your roles in, for example if a set of directories needs to be owned by a user you’re creating the user role may need to come before the role that’s creating the directories.
Thanks for tuning in, we will continue with more fun with Ansible in the coming several blog installments.