Hi,
To clarify, what you want is a playbook that contains multiple plays,
like this. The roles of individual plays in a playbook is to map
individual tasks to groups of systems. So your multi-tier rollout
where you need to talk to webservers before dbservers looks about like
this:
hosts: webservers
tasks:
- ...
hosts: dbservers
tasks:
- ...
Thanks, I think I can see a way to do it like you describe, but it seems fragile. Perhaps you have a better way than I'm thinking of. Might you or anyone else have a working example they could show?
My preference would be to try and define a yaml schema which grouped related bits of information together - so that adding a new system is a matter of adding a single yaml block. Whereas, if I am guessing what you mean correctly, I would need to add elements in different places all across my schema.
Here's a specific stripped-down example: granting ssh access to a backup server for various and arbitrary system users on different machines. Access requires allowing the client's IP through the firewall server, and adding its public key to the backup account's authorized_keys file (meaning, there may be more than one component and more than one host which needs to be orchestrated).
What I imagine I'd need to do in Ansible currently is to describe the backup ssh account in one place, including a list of allowed public keys. Something like this:
- hosts: backup servers
vars:
backups:
pubkeys:
- <webserver X key ...>
- <dbserver Y key ...>
- <reposerver Z key ...>
tasks:
- name: enable ssh access for backup clients
action: authorized_key user=backup key=${item}
with_items: ${backups.pubkeys}
On the firewalll server I'd need a list of IP addresses which should be allowed:
- hosts: firewall servers
vars:
firewall:
allowed_hosts:
- <webserver X addr>
- <dbserver Y addr>
- <reposerver Z key>
tasks:
- name: configure firewall
action: template src=templates/iptables.j2 dst=/etc/sysconfig/iptables
# ...implicitly uses allowed_hosts variable within template
Elsewhere, I'd describe the systems which need access to this account to perform their rsync backups:
- hosts: webservers
# ... remember to add an entry to pubkeys list and allowed_hosts list
tasks:
# ...
- hosts: dbservers
# ... remember to add an entry to pubkeys list and allowed_hosts list
tasks:
# ...
- hosts: reposervers
# ... remember to add an entry to pubkeys list and allowed_hosts list
tasks:
# ...
In each case, each new system that wants to access backup space requires an item added to an appropriate list in the first two plays. New systems need alterations to three disconnected places in the schema, probably more once you factor in other things like monitoring. With this distributed arrangement, it seems it'd be easy to forget, when one system is retired, that it also needs to be removed from all the other places it is mentioned.
Is it actually what you had in mind?
I'm not sure how one might allow grouping the information associated with webservers/dbservers/reposervers together. Thinking out loud, perhaps one could invoke an xpath-style query of the yaml schema to get items to iterate over (in which case the pubkey and allowed host info could be put in webservers.yml, dbservers.yml, etc, and still found)?
- hosts: backup servers
vars:
pubkeys: query("//backups/pubkey")
Or, perhaps have the webservers / dbservers/ etc. plays' variables somehow append or insert items into the relevant lists in backup-server play's variables?
- hosts: webservers
vars:
backups:
pubkeys:
- <webserver X key ...>
tasks:
# ...
- hosts: dbservers
vars:
backups:
pubkeys:
- <dbserver Y key ...>
tasks:
# ...
In either case, the point is that if a new (class of) server is added, the pubkeys and host addresses are listed in the new play for this server, not in the existing plays. And it'd be handy if you could add more complicated data structures, as well as just single values.
(This is just off the top of my head, I don't think either is currently possible in Ansible - I just want to illustrate the kind of thing I mean.)
Obviously whatever scheme is used, it'd be better to avoid ones in which typos or incomplete refactoring of variable names results in things silently breaking. I'm thinking specifically of the xpath-style query: it would only take a typo to have an empty list returned. The latter scheme might be safer, if you couldn't append data just anywhere, but only to sites marked as receivers for this kind of addition.
Cheers,
Nick