Make your Ansible playbooks flexible, maintainable, and scalable

Notes on Geerlinguy's presentation at AnsibleFest 2019

Thursday, September 19, 2019

Jeff Geerling (geerlingguy) gave a presentation at AnsibleFest 2019 in Austin (TX). This post is an abstract of his presentation. Jeff’s presentation covers how he builds and maintains Ansible playbooks, roles, and gives tips for making them easy to expand and scale.

Jeff Geerling: Make your Ansible playbooks flexible, maintainable, and scalable

Lessons learned

  1. Stay organized
  2. Test early and often
  3. Simplify, optimize

Stay organized

  • Everything is in version control
  • Playbooks always run from build server (AWX/Tower or Jenkins)
    • build server is a consistent environment that tracks every change that you make


“If it’s important it will be forgotten.” - Jeff Geerling

Every repository that you make, no matter how small always add a readme file

  1. Purpose
  2. Links (CI, docs, issue tracking)
  3. Instructions for local testing

Small files

  • < 100 lines per file
  • Start by splitting out related tasks with **include_***
  • Progress to single-responsibility roles


  • Make roles generic
  • Share roles among projects
  • Contribute to / use from Galaxy
  • User semantic versions for roles (format 1.0.0, “”)
  • Add downloaded Galaxy roles to .gitignore, add version to build server

Test early and often

Testing Drupal and Ansible on on a Dramble cluster (Raspberry Pi)

The Ansible CI Spectrum

  1. yamllint
  2. ansible-playbook –syntax-check
  3. ansible-lint 🔗
  4. molecule test (integration) 🔗
  5. ansible-playbook –check (against prod)
  6. Parallel infrastructure (blue-green deployment)

Complexity increases with the number 😉

Note: Molecule is now an official Ansible project.

More tips for testing

  • Read through porting guides (every new release)
  • Disable annoying WARN messages:
    - name: Check if firewalld is installed.
      command: "yum list installed firewalld"
        warn: no
      register: firewalld_installed
  • Target latest Ansible release
  • Keep CI environment updated

Simplify, Optimize

“YAML is not a programming language.” - Jeff Geerling

  • Prefer simple, flat variables over dicts

??? example “Example” !!! caution “Complex nested structure”

      startservers: 2
      maxclients: 2

!!! hint "Simple flat structure"

    apache_startservers: 2
    apache_maxclients: 250


  • CI is useless slow
  • Disable gather_facts if not needed
  • forks config - fully utilize resources (default is 5 forks)


  • package - pass list to name instead of a loop
  • copy - only for single files or small dirs
  • lineinfile - try to switch to template instead of looping on one file

Profiling your playbook

Ansible config file:

callback_whitelist = profile_roles, profile_tasks, timer


  • Code smell: Checking in inventory file changes
  • Static environment, static inventory
  • Dynamic environment, dynamic inventory

And More!

  • Automation should be all or nothing
  • Be explicit (always define state).
  • Try other callback plugins (my fave: yaml).

Recap: Lessons learned

  1. Stay organized
  2. Test early and often
  3. Simplify, optimize