Multi Environment Ansible Layout – Part 1
One of the more difficult things about using Ansible is deciding on how to lay things out in the file system.
This is the layout I’ve settled on after a few different tries.
This layout solves the following issue:
-
Multiple environment (development, integration, staging, production)
-
Supports environments living in different AWS accounts
-
Per-environment variables
-
Global variables
-
-
Hybrid inventory (some hosts from AWS, some locally defined)
-
Secrets and variable are managed using smaller scopes
Overview
The layout looks like this:
. ├── ansible.cfg ├── ansible-roles.yml ├── .gitignore ├── inv/ │ ├── group_vars/ │ │ ├── all/ │ │ │ ├── 10-global-secrets.yml │ │ │ └── 10-global-variables.yml │ │ ├── integration/ │ │ │ ├── 10-integration-secrets.yml │ │ │ └── 10-integration-variables.yml │ │ └── production/ │ │ ├── 10-production-secrets.yml │ │ └── 10-production-variables.yml │ ├── host_vars/ │ │ └── backup.example.com/ │ │ └── 10-ansible.yml │ ├── int/ │ │ ├── ec2.ini │ │ ├── ec2.py -> ../.shared/ec2.py │ │ ├── group_vars -> ../group_vars/ │ │ ├── host_vars -> ../host_vars/ │ │ ├── localhost -> ../.shared/localhost │ │ └── mapping.yml │ ├── prod/ │ │ ├── ec2.ini │ │ ├── ec2.py -> ../.shared/ec2.py │ │ ├── group_vars -> ../group_vars/ │ │ ├── host_vars -> ../host_vars/ │ │ ├── localhost -> ../.shared/localhost │ │ └── mapping.yml │ └── .shared/ │ ├── ec2.py │ └── localhost ├── playbooks/ │ ├── app.yml │ ├── db.yml │ ├── Site.yml │ └── web.yml ├── roles/ │ └── .gitkeep ├── roles-inline/ └── .vault/ └── password
A git repository with the full layout can be found here
The term environment
is reserved in Ansible.
I’ve created two new terms to get around this limitation:
-
environ
— a "short" term for an environment (akaint
orstage
). -
environment_long
— the longer version of an environment (akaintegration
orproduction
).
These are set using the YAML inventory mapping file inv/<environ>/mapping.yml
.
Top-Level Files and Folders
-
ansible.cfg
— The Ansible configuration file. We make a few changes from the stock file which ships with Ansible.-
roles_path
— We add the two folders we’re using for roles into the roles path settingroles_path = roles/:roles-inline/
-
vault_password_file
— I set this to avoid having to type the password when using theansible-vault
commandvault_password_file = .vault/password
-
retry_files_enabled
— I find the creation of retry files annoying, so I turn it offretry_files_enabled = False
-
nocows
— Some people find the use of thecowsay
command in the Ansible output annoying. If you agree, set the following:nocows = 1
-
-
ansible-roles.yml
— The third-party roles file. This file is used with the commandansible-galaxy
to install third-party Ansible roles.ansible-galaxy install -r ansible-roles.yml -p roles/
-
.gitignore
— Git ignore file. This file helps us keep secrets and third-party Ansible roles out of our git history. Currently the contents look like this:.vault/ roles/
-
inv/
Top-level inventory folder. (more on this later) -
playbooks/
— Playbook storage. -
roles/
— Storage location for third-party Ansible roles.-
Notice the
.gitkeep
file there, we usegit add -f roles/.gitkeep
to override the gitignore file above to keep this empty directory on checkout.
-
-
roles-inline
— Where we write Ansible roles which we want to be a part of this git repository. -
.vault
— Where we store the password file for theansible-vault
command.-
Normally this password file would be ignored in git, I’ve added it so that the
ansible-vault
commands will work for people using my example layout.
-
Inventory Drill-Down
Tomorrow we’ll cover where the real power for this layout comes from, the inventory!