All -
I'm trying to get my head around "the ansible way" for organizing
things. I greatly appreciate the design goals of ansible and find it
mirrors largely how I think; but I still am a bit confused about
proper use of variables, multiple data centers and have yet to find a
definitive "example/template".
So, here's a first attempt at how we've organized thing. Its a bit
long because my plan is to take this description with accompanying
playbooks and make it public as an example/template for others like us
But, I want to first get confirmation this is the "right" way to do
things and help on a few issues :).
Anyhow, here's the complete story and accompanied thinking.
We have a cluster of machines, as I imagine so does everyone else in
some manner or form.
So, we defined how it looks in the hosts file. The groups are
different roles/functionalities (say web-app, db-master, cache - we
have about 15). We use groups of groups for machines that have shared
functionality. Its beautiful because we can look at one file and
clearly see, without distractions, exactly what machines we have and
how they are grouped.
Now, we write playbooks to setup and/or maintain different aspects of
this infrastructure. For example, there are "all" playbooks: a hosts
playbook that copies a shared host file to all the machines; an
iptables playbook updates the iptables config file (using {% if 'blah'
in group_names %}) and so on. We also have a general "base_setup"
playbook that includes all the tasks from these specific "all"
playbooks.
Then we have role specific playbooks that achieve things we might want
to run on a role; things like 'configure webserver', 'deploy
application x code', and so on.
For each role we have a number of task files (i.e. things like
install, config, reload). Each role then has playbooks to achieve
different objectives based on the tasks. The simplest example is a
basic webserver:
Tasks: install, config, reload
Playbooks: setup (includes install, config, reload tasks), reconfigure
(includes config, reload tasks)
A more complex example would include playbooks to deploy new code from
git and so on.
When we setup a new machine we assign it to a group(s)/roles, run the
base_setup playbook and then run the associated playbooks based on its
roles.
If we change something (like say the hosts file or webserver config),
we run that specific playbook. If we want to deploy new code, we run
the deployment playbooks.
Compared to where we came from (i.e. 'chef') it all feels very sane
and logical. One file defines what servers we have. One group of
files (playbooks) define aggregate objectives (plays) we want to
achieve on these servers. Another group of files (tasks) has the
specific task.
Yes, we need to make sure we run the right playbooks when we update a
config, but this is one command and we always feel like we know
exactly what's happening.
Is this correct so far?
Now, there are a few things we haven't quiet figured out:
a) How to deal with multiple clusters. The simplest case is having a
staging and production cluster. We have that plus ones in different
countries.
Based on how we organized things above, we create different hosts
files. The problem with this is we need to have different
configuration files (in some instances) or different variables
depending on which cluster we are deploying to. How to achieve this
in a simple clean way?
My intuition is to have host file level variables (i.e. at the top of
the host file say: cluster=cluster_name...but I feel like we are
missing something.
It *seems* the way ansible is designed is to have one host file with
different clusters organized into different groups. But, I can't
figure out how to get that to work. Let's say we have a webserver
with production and and staging. We *could* group like this:
[production-webservers]
server1
[staging-webservers]
staging1
[webservers] productions-webservers, staging-webservers
We could then ask if the server was in the staging or production
group.
But, what about the "deploy play"? I want to be able to say: "run the
deploy play on production servers". Instead, I would need to have two
copies of this play? It seems to get rather messy rather quickly.
b) Knowledge of other servers. Often times in configuration files, we
need to enumerate over a list of servers. For example, we have a play
to configure a munin master. The master config points to all of the
other servers. Right now, for each cluster I have different config
files and each time a server is added we need to modify the config
file. This is very repetitive.
I understand the goal to keep ansible very simple and not have complex
callbacks and so on. However, to the extent that groups are a key
construct, I keep running into the simple idea that if I could query/
access the host structure in variables the code would be much
simpler. Am I thinking in the wrong direction?
Thanks!
JP