Multiple clients and multiple sub groups

Hi, I would appreciate it if someone could direct me to the appropriate documentation or give me a tip.

The company I work for manages hundreds of sites for hundreds of clients. For some of them we use Ansible.
I want to take it to the next level!

I am looking for the most efficient way to do the following: a client named jack has 2 db servers, 2 web servers and 1 stg server.

I would build the inventory file like this:
[jack]
db1
db2
web1
web2
stg1

[jack-db]
db1
db2

[jack-web]
web1
web2

[jack-stg]
stg1

This way, I can run a different play-book for each sub group, and also a playbook for the whole main group. (jack)
Now lets say that I have the same structure for the rest of the clients.

I am looking for a way to run a play-book for all the db servers for all of our clients for example.
Or all the web servers…
I would like not to create multiple inventorys, but to keep it simple as possible.

Do you know this kind of solution?

I think you can experiment with patterns - Patterns: targeting hosts and groups — Ansible Documentation

For example, if all the “db servers” groups will be named -db, I would think you could run against *-db

I don’t use static inventory files, but I do use wildcards often when calling hosts/groups/etc. …

We do something similar… We look at it as a horizontal and vertical inventory. We are able to run on a specific instance (say PROD) or a specific type (say web). You can also join groups using the “:children” option and have groups of groups.

We are able to use this inventory and say PROD:!WEB and that will run on all servers in PROD that are not type WEB. Or we can union two groups and say PROD:&APP this will run on PROD servers that are type APP. We also use the children option for patching. We might patch all of NONPROD at the same time and that would exclude any PROD servers.

Our inventories look something like this:
[WEB]
web101
web102
web103

[APP]
app101
app102
app103

[DB]
db101
db102
db103

[PROD]
web103
app102
db102

[DEV]
web101
app101
db101

[STG]
web102
app102
db102

[NONPROD:children]
DEV
STG

Hope that helps,

dp

Personally I prefer using YAML to INI for the inventory file, there are example of both in the documentation.

We have a naming convention for both inventories and groups within, and some guidelines.

  • Each inventory source should have a clear purpose.
  • All groups from a given inventory source will start with the same prefix.
  • All sub-groups are named such that it’s obvious which group(s) they are a sub of.
  • Any host should show up only once in a given inventory source.

Problems with that last bullet point indicate that we either haven’t fully articulated our groups in the inventory source, or that we’re mixing inventory purposes - i.e. we’re trying to use one inventory source for two different things, such that we probably need another source at that level.

So if we were looking at your inventory, we’d structure it like this (maybe):
{prefix}_{customer}_{environment}_{tier}
and the whole thing might look like this:

[client_all:children]
client_jack
client_jill

#### jack ####
[client_jack:children]
client_jack_dev
client_jack_prd

[client_jack_dev:children]
client_jack_dev_db
client_jack_dev_web
client_jack_dev_stg

[client_jack_dev_db]
dbdev1

[client_jack_dev_web]
webdev1

[client_jack_dev_stg]
stgdev1

[client_jack_prd:children]
client_jack_prd_db
client_jack_prd_web
client_jack_prd_stg

[client_jack_prd_db]
dbprd1
dbprd2

[client_jack_prd_web]
webprd1
webprd2

[client_jack_prd_stg]
stgprd1

#### jill ####
[client_jill:children]
client_jill_dev
client_jill_prd

[client_jill_dev:children]
client_jill_dev_db
client_jill_dev_web
client_jill_dev_stg

[client_jill_dev_db]
dbdev2

[client_jill_dev_web]
webdev2

[client_jill_dev_stg]
stgdev2

[client_jill_prd:children]
client_jill_prd_db
client_jill_prd_web
client_jill_prd_stg

[client_jill_prd_db]
dbprd3
dbprd4

[client_jill_prd_web]
webprd3
webprd4

[client_jill_prd_stg]
stgprd2

Only we’d use hosts’ FQDNs, For us, {{ inventory_hostname }} always equals {{ ansible_fqdn }} after gathering facts.

About hosts only being listed in one place: If you set up your groups right, then the hosts will always pop into whatever parent groups they should be in. But if they’re listed in multiple places, then every time you add or change a host, you have to examine the whole inventory source’s groups and make a decision about each one. That’s the kind of work computers were supposed to do for us, not the other way around.

This looks overblown for such a small set of hosts, and maybe it is practical to leave out some intermediate groups if you never need them. But if you ever do, it’s clear just from the group names how the hierarchy fits together so you could add them later.

If you take nothing else from our experience, consider this suggestion: Although Ansible allows you to structure your inventory in gajillions of ways besides a strict hierarchy, don’t do it. It’s easy to understand, verify, and maintain a hierarchy, and therefor easy(ish) to see when you mess it up. But if you accidentally build an N-dimensional ad hoc polyfrackus inventory from Mordor, you could get in pretty deep before you realize you’ve created a monster.