Handling multiple instances of an application on the same host

Hello list!

I’m wondering how you would go about organizing things when you can have several instance of the same kind of application on the same host.

Let me give you an example to make things clearer.

Let’s say with have 3 hosts, with 2 clusters of 2 appservers each.
That would give us something like:

  • cluster1
    – appserver1 on host1
    – appserver2 on host2
  • cluster2
    – appserver3 on host1
    – appserver4 on host3

We could have some configuration that is at the cluster level (external_url).
Also some at the appserver level (http_port).
Potentially, we could also have some default defined at the cluster level but overriden at the appserver level (kind of what exists with groups/hosts).

Now, when we run our playbook, we can’t just have “http_port” defined in group or host vars, because we’d have a conflict on the http_port on host1 which has both appserver1 and appserver3 (for both of which we want to use the same appserver.yml playbook)

So, basically, how would you map an application-centric configuration to the host-centric one we have in ansible (and other configuration tools, the logic is pretty much the same) ?

One idea I had was to actually not use groups/hosts as they were intended but use them as clusters/appservers with a delegate_to to the actual host on each task, but that seems very much a big hack and is probably very inefficient as we’d keep establishing new connections to the actual hosts all the time.

Another idea was nested includes + with_items with vars_files, but I don’t think that’s possible, something like:

  • main.yml:
  • include: cluster.yml cluster=${item}
    with_items: ${clusters}
  • cluster.yml:
  • include: appserver.yml appserver=${item}
    with_items: ${cluster.appservers}
    only_if: “${item.host} == ${host}”
    vars_files: myvars/clusters/${cluster.id}.yml, myvars/appservers/${item.id}.yml

At this point, I’m kinda stumped about what direction I should take among those (if any), and starting to have knots in my brain :wink:

I’d appreciate any ideas/suggestions (other than “don’t put two instances of the same kind of application on the same host”).

How about making a group for each cluster, and use group_vars for the
ports?

That would only work if every variable was cluster-wide, but not when we can have configuration specific to a single appserver instance.Also, in my example, host1 would be a member of both groups cluster1 and cluster2, so unless I’m mistaken one group_vars would override the other.

I have pretty much the same issue. I'm gathering 'cluster1' is a load-balance pair? I handle this with a group_vars file that sets multi-level dictionary. So for you case it might look something like:

# file: inventory/group_vars/cluster2
appservers:
   - appserver3:
  - http_port: 3000
  - dbconnect:
      - username: foo
             - password: bar

   - appserver4:
  - http_port: 3001
  - dbconnect: ...

Then do a 'with_items' on appservers and dig down to appropriate values in your templates.

I also do a sneaky

   vars_files: ../inventory/group_vars/cluster2

in my database management playbooks so I can keep all the database users and passwords in sync. The new multi-level looping may make this cleaner than it currently is. My configuration is still somewhat in flux so I'd been keen to hear how you go and of any other approaches.

K

Ooops indentation got a little screwed there. 'username' and 'password' should be at the same level.

K