An Ansible Project Setup that Scales

So I have been using Ansible for over two years now .. I use it for damn near everything — provisioning infrastructure, configuring nodes, deploying Web applications, testing whatever I can, and other ad hoc tasks (sadly, I’m still working on a “get me beer” playbook) ..  Long story short, it’s been a game changer .. Problem is, as my (and my team’s — hi guys !!) Ansible usage grows (50+ playbooks and 130+ roles) — so does my desire to organize it in a way that is scaleable ..

There are many ways you can setup your Ansible project (one, two, three, four, etc ..) — which is great !! That said, I love me some simplicity .. After trying out a few setups, I finally settled on one that works for me .. You can see it here ..

The view from 30,000 feet:

  • inventories
    • All of my inventory files, static and dynamic, will be children of the inventories directory
      • FULL DISCLOSURE: by design, I only have two inventory files — localhost and .. every once in a blue moon we will add additional inventory files (PoCs, targeted testing, etc ..), but we always fallback to only the two
    • Group and other variables
      • the group_vars directory can be relative to an inventory file, no matter where the playbook is .. since I like to add some structure to my playbook organization, it makes sense to put it here
      • variable files (i.e. Ansible Vault) that need to be explicitly loaded go in the vars directory
      • IN THEORY: you could also put a host_vars directory here .. but as y’all know, host_vars are the devil
  • playbooks
    • Let me explain my logic here .. In my work, I essentially perform five functions: 1) provision infrastructure, 2) configure infrastructure, 3) deploy to infrastructure, 4) test infrastructure (and other things), and 5) save the world (i.e. ad hoc tasks) .. Knowing this:
      • construct/*
        • since the line between provisioning and configuring infrastructure can get murky, I combined the two “functions” into one directory
      • deploy/*
        • guess what goes here 🙂
      • test/*
      • adhoc/*
        • the one-offs that don’t fit nicely anywhere — but here
  • roles
    • resource/*
      • these are the bits and pieces that make up a useful piece of infrastructure .. for example, we have resource roles for AEM, Bitbucket, CPANm, .forward, Java (1.6, 1.7, and 1.8), Apache, Netcat, Nagios, NRPE, etc .. all solid implementations .. all reusable ..
      • STYLE ALERT: we DON’T use Ansible Galaxy — directly .. we often refer to it for inspiration — but always end up using our own implementation
    • <primary>
      • this is a “completed”piece of infrastructure .. the sum of the (resource) parts .. the cherry on top .. for example, we have primary roles for user_web_api_server, internal_dns_server, aem_author_server, aem_publish_server, etc ..
    • action/*
      • this is what I “do” to my infrastructure that doesn’t maintain any real “resource” …. for example, we have action roles for silencing/unsilencing Nagios, deploying code, restarting application servers, taking data centers offline, etc ..

The view from 30 feet:

  • PROBLEM: “I want my playbooks to be able to refer to my roles in a way that is consistent and easy” .. Great idea !! The problem is, your playbooks and roles are gonna be all over the place — so you can’t take advantage of the “relative referencing” you can do in a traditional project structure .. Let’s also assume you don’t want to define an absolute path in the config file ..
  • SOLUTION: Hello bootstrap !! Take a path that will always be consistent (inventory_dir) and use it to define other paths with some regex magic .. When finished, shove it all into a external variables file ..

  • FINALLY: Refer to the bootstrap, early and often, in every playbook you create,  ..

Again, this project setup works for me .. “Me” being myself and 4 other sys admins ..

Anywho — I need to get back to work on that “get me beer” playbook ..


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s