On best practices

Hi,

Since ansible best practices are being discussed these days, I would
like to share how I use ansible, and receive your opinions. Wrong way ?
Suboptimal ? Completely off-track ? Nice ?

I'd like to hear what you think. It's a bit long for the list, so I
wrote a gist on it :

https://gist.github.com/leucos/4953943

Thanks for your time if you read it !

M

I generally prefer to not break things up to install vs configure but
keep one description of desired state when possible.

I also like to keep a playbook for each of my major roles, and that
playbook just includes the tasks and handlers that they use

For instance, webservers.yml or dbservers.yml or cluster.yml

If I want to do everything, I can have a site.yml that includes all of those.

I think you're a bit more data-driven than most, but I think it's interesting.

I think a playbook per host is suboptimal as you don't want each hosts
to be unique little snowflakes per se, but rather you should think of
playbooks per role or function,
and then use host_vars/group_vars to account for variance between
hosts and groups.

Your 'pivot playbook' is kind of invalid YAML syntax that is covered
by including inside of a 'tasks' directive.

I generally prefer to not break things up to install vs configure but
keep one description of desired state when possible.

Yes. May be this is overkill. It doesn't really add anything since I
never call tasks elsewhere.

I think you're a bit more data-driven than most, but I think it's interesting.

I like variables ineritance and key overriding a lot as you might have
guessed. I thinks this is pretty cool to maintain setup-wide defaults,
and change them when nedded without overriding perculiar hosts/groups
requirements.

I think a playbook per host is suboptimal as you don't want each hosts
to be unique little snowflakes per se, but rather you should think of
playbooks per role or function,
and then use host_vars/group_vars to account for variance between
hosts and groups.

Clearly, you're right. However, I have a small setup here and per role
is almost per host in our shop.

However I will change "top playbooks" to map to a role instead of host,
this is really the way to go. Who knows, some servers might have
siblings someday. I already have cases of ucarp connected machines which
could benefit from the change.

Your 'pivot playbook' is kind of invalid YAML syntax that is covered
by including inside of a 'tasks' directive.

Yes. Thus I think I would have to include the `service/task/*.yml` stuff
instead of `service/setup.yml`, right ? This is a good excuse to remove
that service/setup.yml file. However, this implies I always call the top
level `site.yml` file and can not call a service playbook anymore.

But adding tags in the soup could solve this.

So instead of :

    abk -l server.example.org tmux/setup.yml

I could :

    abk -l server.example.org site.yml -t tmux

Is this what you were thinking of ?

Thanks for taking time to comment Michael.

M

also sprach Michel Blanc <mblanc.networks@gmail.com> [2013.02.15.0541 +1300]:

I'd like to hear what you think. It's a bit long for the list, so I
wrote a gist on it :

https://gist.github.com/leucos/4953943

Thanks for your time if you read it !

I left a comment on the gist. Why don't you move this to
a collaborative editor, e.g. http://titanpad.debian.net ?

Thanks for taking the time to gives such a detailed description of your set up. Much food for thought :slight_smile:

First thought is to not conflate the concept of a single playbook and the concept of (one or more) playbooks bundled with a set of files, handlers, vars_files and tasks. Perhaps we could borrow the term 'bundle' from bcfg2 for the latter?

I like the idea of making playbook bundles per-service or per-role (one or more services grouped, like, say, postfix and dovecot). This is what I do too. :slight_smile:

I used to build host-agnostic playbooks like you describe, but ran into a number of difficulties getting it to manage certain situations without loosing the wonderful clarity and simplicity of ansible.

Then I discovered a little gem buried in the documentation.

"It is the purpose of a play to map a selection of hosts to tasks"

Eureka moment! Playbooks are data too!

The hosts file defines hosts and groups;
The host_vars and group_vars assign data to hosts;
Playbooks define mappings from hosts (or groups) to tasks.

I think trying to shoehorn the 'host to task' mapping into the inventory data is an exercise in futility, or at least I found it to be.

I'm currently reworking my service bundles to contain separate playbooks for each host (or group of hosts) that need to be managed differently. Being able to include task files and even other playbooks means these playbooks can be quite short and simply express the required host to task mapping, as data. This also means I can run playbooks without having to use overly complicated command line arguments (or script wrappers).

Does this make any sense?

Cheers,

Kal

Hi,

Better late than never, thanks guys for commenting on my pbook extract.
A few replies here, sorry for being long.

TL;DR: on the difficulty of having host-agnostic per-service playbooks

I'd like to hear what you think. It's a bit long for the list, so
I wrote a gist on it :

https://gist.github.com/leucos/4953943

Thanks for your time if you read it !

I left a comment on the gist. Why don't you move this to

Thanks, I've reproduced them here.

a collaborative editor, e.g. http://titanpad.debian.net ?

Well, you can fork gists too though I agree hat for gists is it not
really convenient (no PR AFAIK).
But done anyway :

http://titanpad.com/RFU9FrzGGS

I'm in the process of curating sensible data from my playbooks. When
done, I'll create a GH repos. We need more playbook examples, I'll try
to add my 2 cents to the mix.

I have two comments:

Wouldn't it be better not to include the tmux playbook on machines
that don't get tmux, rather than turning it into a play
conditional play?

Yes, sure. This is why I have 'per machine top level' playbooks.
For instance, goat.example.com will have a goat.e.c.yml playbook.
So yes, "only_if: ${tmux.install}" is probably an overkill safety
measure in this case.

A case could be made for tmux.install==False causing tmux to be
purged from the system, but you don't do that.

Yes right, thats is an idea ! I wouldn't do that right now, since I'm
in the process of migrating hosts under ansible management. Some of
them are partly managed with ansible, and some of them appear in
inventory jyst because their IP is needed somewhere else (firewall
deployment on other hosts).

So I wouldn't like ansible to uninstall my cyrus server just because I
messed up things.
When all hosts will be under ansible management, this is definitely a
great idea.

And even if you did, I think there are numerous cases where
parametrisation via variables should actually affect the
composition of the playbook, not just the behaviour.

Yes, this is true, and I'm still scratching my head for this. I might
end up with generic services playbooks, and some specific
configuration playbooks. For instance, a generic postfix playbook that
uses a relayhost (just for emailing out stuff), and a dedicated,
specific playbook for our much more complex MX.

Something like :
- include: host-specific/smtp.example.org/setup.yml
  # contains postfix configuration for smtp.example.org

in the "host-dedicated top level playbook" could do the trick.
However, it would kill idempotency since configurations installed by
the postfix "service playbook" would be overwritten at every run (and
vice-versa).

Have a look at
https://groups.google.com/forum/?fromgroups=#!topic/ansible-project/HetiQdNKOj4

and the referenced post to the salt-users list and chime in (on the

ansible list of course).

Thanks a lot for your comments Martin !

I'm currently reworking my service bundles to contain separate
playbooks for each host (or group of hosts) that need to be
managed differently.

That could be interesting to see. Do you have an example ?

Being able to include task files and even other playbooks means
these playbooks can be quite short and simply express the required
host to task mapping, as data. This also means I can run playbooks
without having to use overly complicated command line arguments (or
script wrappers).

I personnaly end up running stuff like this :

abk -l host.example.org h.e.o.yml

where h.e.o.yml is a "top level" playbook including service playbooks :

Suppose I'm managing postfix for a mail hub with a secondary MX, but I also have a bunch of other servers that I want to run a local relay on.

Lets start with the following layout:

postfix/
     files/
     handlers.yml
     tasks/
         setup.yml
         configure.yml
  whatever.yml
  ...

     mail-hub.yml
     local-relay.yml

with the following playbooks