Scale up as you grow — whether you're running one virtual machine or ten thousand.

From GPU-powered inference and Kubernetes to managed databases and storage, get everything you need to build, scale, and deploy intelligent applications.

This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Great article! Having used this approach for the past year, I’ve been working on plans to address some issues this structure doesn’t easily solve: isolating playbook and role changes to specific environments.
The problem especially in environments when multiple individuals are collaborating is merging playbook and/or role changes impacts all environments simultaneously. Most shops want some measure of controlled roll out of changes, so something else is needed. In the Puppet world, this is done through tools like r10k that leverage git branches for each environment and externalize the management of puppet modules (or ansible roles in our case) to separate git repositories with something like ansible galaxy to pull environment-specific versions in.
Each environmental branch looks something like:
ansible.cfg
group_vars/
all/
vars
vault
db/...
web/...
host_vars/
inventory
playbooks/
db.yml
web.yml
requirements.yml
roles/
where the requirements.yml file contains URLs to relevant versioned roles to pull in.
Would love to hear thoughts and ideas on addressing this class of problem!
Thank you! This is exactly the kind of explanation of the how’s and why’s of Ansible environment separation I’ve been looking for, great write-up.
Insightful comment from Andrew also.
Hi Justin, thanks for the fantastic article! It gives me some idea on how to accomplish my current work to migrate and consolidate a huge bash based deployment scripting (with 103 different configurations) into a idempotent and more versatile approach.
Say, we have a set of n Customers, each one requiring a DEV, TEST, PROD stage. With each stage there should be setups of webservers and appservers. It can be possible, that you have different amounts of webservers and appservers (e.g. for HA or scaling), so maybe DEV has 1 WS and 1 APP while TEST and PROD consist of 2 WS and 3 APP each.
Formalized file system structure:
customer_n/environments/{DEV, TEST, PROD}/group_vars/{APP, WS}
I guess it would be right to model this and the further configuration (e.g. ports and so on) of each WS/APP instance in a (nested) dictionary approach in group_vars.
I’m elaborating on this and would be interested in any suggestion.
Hi Justin! Quick question. Is there a Github repository I could tinker with? I’m trying to replicate the structure at the end of the article, but I’m still trying to understand how to properly arrange each hosts inventory file in order to leverage the variable definitions workaround you’re proposing.
Thanks again for an awesome article!
In Ansible >1.2, you can put a group_vars folder in the playbook directory. Variables in that group_vars folder will overwrite variables in inventories/environment/group_vars
Tip: In Ansible 1.2 or later the group_vars/ and host_vars/ directories can exist in the playbook directory [AND] the inventory directory. If both paths exist, variables in the playbook directory will override variables set in the inventory directory.
Justin n all, great write-up and discussion! The twist in my case is that the production server farm is completely separate - (fire)walled off - from the staging one, where we have multiple environments (dev, QA, functional, non-functional). It follows that each (of the two) server farm has its own ansible (installation and) controller. Do you think it’s worth “pretending” (in configuration terms) that production is part of the whole? Shouldn’t we “abstract” production and instantiate the staging ones from it?
I’ve been using --limit make my playbooks run on a specific environment instead. Issue I ran into with the other suggestions is that I can’t use it to automate things which need to be aware of the entire network. For example, I was trying to generate my haproxy configuration.
My directory looks like this:
group_vars/
prod
stage
roles/
...
deploy.yml
load-balancer.yml
inventory
Inside my inventory file, I have something like the following:
[stage_db]
db1.stage.com
[stage_web]
web1.stage.com
[stage]
stage_web
stage_db
[prod_db]
db.prod.com
[prod_web]
web1.stage.com
[prod]
prod_db
prod_web
[db]
prod_db
stage_db
[web]
prod_web
prod_stage
This way, I can still reference, in my roles/playbooks, groups as I would normally:
- name: open up firewall for db
become: yes
with_items: "{{groups['web']}}"
ufw:
rule: allow
from_ip: "{{hostvars[item].ansible_eth1.ipv4.address}}"
port: 3306
Where I need to I can also reference the prod and stage environments explicitly.
The only downside to this approach is that I can’t have one big site.yml with everything in it, but I personally never needed one.
lets say we have different environment and we want to manage large domain name in inventory can we use as variable like we have different environment. dev.example.com qa.example.com prod.customer.com
vars dev=dev.example.com qa=qa.example.com prod=prod.customer.com
so in inventory can we just define host
like host.{dev} host.{qa} host.{prod}
Great post! After the following directory setup, I am planning to use the roles/ to store my tasks per ansible project.
Questions:
├── ansible.cfg ├── environments │ ├── prod │ │ ├── group_vars │ │ └── hosts │ ├── uat │ ├── group_vars │ └── hosts ├── roles │ └── push_ssh_config | └── install_nginx ├── play1.xml ├── play2.xml ├── play3.xml
PS: Please excuse me for the alignment above, I hope you get the idea of the directory structure.
Great article! Do you have a public repo with an example? I’m still new to ansible and would be useful. Thanks!