3
votes

It seems that in the ansible world there are a bit too many ways to deal with inventory and we faced some hard questions.

We currently have 4 official target environments: production, staging, testing and local (localhost). Now they are all groups of hosts inside a single inventory.ini which is located in the root.

Almost all entire infrastructure is running on AWS, the only exception is that some developers are running their local environment on localhost or a local VM. Still, all the other non-personal environments are on AWS.

Some staff would like to split this into different inventories for each environment in order to avoid accidental execution against all at once. I am a bit concerned that this could increase the maintenance costs and that will probably make harder to work with tools like Ansible Tower, Semamphore or RunDeck. I also want to switch to ec2 dynamic inventory which makes the split less intersting.

Here are few questions that have to be addresed by an optimal setup:

  • how do I deploy a specific component towards a specific environment?
  • how do I test a playbook without affecting production or staging?
  • what default value should he keep as "hosts: value" inside our playbooks
  • what should be the default inventory if we would use multiple files
  • how can we deploy something against the entire infrastructure (multiple inventories at the same time)
2
regardless of my answer, i think the target environment is nothing related to a playbook. It should always be a additive information you should provide explicite.flxPeters

2 Answers

2
votes

I think it's time for a dynamic inventory. I faced a similar issue, where I had 3 environments to deploy to and a single inventory file. I solved it by storing all the hosts in a database (MongoDB in my case ) and then writing a dynamic inventory to create the host list. The selection of the environment was done by adding an env variable before calling ansible ( something like environ=PROD ansible-playbook -i inventory ... There also was a bit of logic in the inventory to avoid anyone to deploy to production ( uid/gid based ). To answer your questions:

  • You can use several ways to do this, use an env variable and a dynamic inventory, separate inventory files, or use a single inventory and name the groups (prod|dev|staging)_<hostgroup>
  • This entirely depends on how you choose to manage the inventory
  • There's no default value for - hosts: in a playbook. Only select the hosts you need from the correct inventory.
  • The default depends on what you decide, but I would say, don't use production as default.. Not the safest thing, maybe use dev as default?
  • Just use -i inventory_dir/. You can pass a directory to -i ansible will read all the files and execute all the -x files.
1
votes

When you are on AWS i would use a dynamic inventory.

We are not on AWS or something similar. So i unfortunately do not have a fancy api with tag etc. In this case a inventory for each environment is the best solution for us. In this inventories we use simple host groups.

Inventory files are stored in a subfoder: inventory/prod.ini

[mysql]
db-server.prod.domain

[web]
app-1-server.prod.domain
app-2-server.prod.domain

Playbooks are organized via groups. So i have a mysql.yml playbook for all database stuff and a web.yml playbook for webserver. They are included in a main.yml playbook to orchestrate them for a full run in maybe a specific order.

include mysql.yml
include web.yml

This is maybe not the best or smartest solution, but it works and it is easy to explain to all team members. I like the idea of environment variables, but in my opinion is't better to have a simple but working solution. We use this schema since some month now without any accidental rollout to the wrong environment.

I you need some more magic or a simple command for any environment you can wrap this in task runner like ant or something similar.