Ansible playbook: infrastructure oriented or role oriented?

This is related to Ansible repository organisation but it remain unclear for me which kind of approach for follow for playbooks.

Using molecule lead us (and me, particularly, because I understood it as is) to write infrastructure oriented playbooks for the important roles. When I see molecule/icinga/icinga-playbook.yml or molecule/postfix/postfix-playbook.yml and their testing clients it is clear that those playbooks not only describe a function in the infra (monitoring master or postfix relay) but are also related to a peculiar VM with a given hostname and some roles which may not be related each others (molecule/weblate/weblate-playbook.yml is a good example of this). A contrario, last developed playbooks (like molecule/backup/playbook.yml or molecule/authorized_keys/playbook.yml) are, by far, role oriented (they simply describe which host receive the concerned role).

What concerns me is that even if those playbooks are very different, they have the same position in the repo, and they are directly (indistinguishably) imported from securedrop-club-playbook.yml.

Imho we should have all our infrastructure description in and only in securedrop-club-playbook.yml and molecule/*/playbook.yml. Even if I don’t see currently which design to follow to get it, I wish that, given a molecule.yml file defining the available hostnames in scenario, I would write something like:

hostgroups:
  - name: icinga_masters
    hosts:
      - icinga-host
    vars:
      icingaadmins_email: icingaadmins@{{ domain }}
      vhost_fqdn: securedrop.{{ domain }}
  - name: icinga_clients
    hosts: [...]

Given this, all remaining playbooks should be only role-oriented, that is:

  • focuses only in one ansible role, or a few of related ansible roles (when we have non-trivial dependencies among roles and/or common variables locally defined);
  • are triggered by hostgroups membership;
  • doesn’t define host-related variables (host, fqdn, domain, etc.).

For what I understand about Ansible, hostgroups is the golden way to get role-oriented playbooks. So, it seems for me that the Ansible inventory file is the golden way to get infrastructure description, but since we have a dynamic inventory, I guess we need advanced molecule stuff to accomplish that i.e. to load hostgroups description (in a way defined above) and affect values to the hosts.

What do you feel about it?

It seems that we can easily mix dynamic and static inventories : Working with dynamic inventory — Ansible Documentation

So it may be much more easier than I thought.

Another way: http://molecule.readthedocs.io/en/stable-1.22/configuration.html#host-group-vars

Thanks a lot for this very well articulated description. I’ll have to think about it more to be able to usefully contribute. At first glance it makes sense. I also feel uneasy about how the playbook & roles are organized. Specially since the weblate migration. The good thing is that we now have a production and a test environment to think about. It helps to have a real use case when trying to figure out an architecture.

In fact the current setup hides the inventory capabilities of Ansible. Before I tried to write on this subject, I thought that all we had is roles and playbooks. Now it’s pretty clear for me:

  • roles => do stuffs;
  • playbooks => distributes roles on hostgroups;
  • inventory => setup hostgroups and variables.

So the answer of the question asked is clear.

Right: I removed all groups and only used host names instead of groups. That was deliberate because the groups we had quickly got artificially confusing. For instance we had a group “bind client” and if you forgot to add a host in the group… it did not have access to the DNS server. What we really needed was to use the implicit group all. And we also had a weblate group or a postfix master group although … there only was one machine in these groups, therefore an unnecessary level of indirection.

I’m not saying groups are not useful :wink: Just explaining why I thought it would be a simplification to not use them unless we need them.

This seems promising ! We know our host names in advance so we can group them. But we need dynamic inventory because we don’t know their IP in advance. I understand what the doc says about mixing dynamic and static inventory… in theory :wink: But I don’t know of an example we could use ?

The platform part of molecule.yml can associate one or more groups to a given host. But it’s something we won’t be able to use with ansible-playbook.

Yes, maybe we shouldn’t over-engineer hostgroups. For what I see, in mosts interesting cases we have a single server setup (e.g. any http daemon), or a client/server setup (dns, mail, monitoring). In the first case, we need to attach the playbook to a single host. In the second case, we need to attach some roles to the master, and some other roles to a “all but the master” hostgroup. Maybe the good way to handle it is to define a playbook attached to all and to switch internally the roles between master and clients depending on the current defined inventory_hostname. Switching seems easy, either at role or playbook level, via conditional importation.

I started to do it in this way. See http://lab.securedrop.club/fpoulain/securedrop-club/compare/master...refactor_monitoring

What I followed:

  • playbook.yml is only used for molecule test environment.
  • icinga-playbook.yml is a generic monitoring playbook which acts on all hosts.
  • A global variable monitoring_master define the master.
  • A host can set a not_monitored variable flag to be ignored by the playbook.

I am pretty satisfied by the result, event if it is not fully functional:

  • I faced some issues due to parallelism. It is welcome but I didn’t thought about it before: I started to do all in the same “play”. Splitting the playbook in different “plays” resolve efficiently this issue.
  • I am facing issues with variables: group_vars and host_vars seems ignored by molecule. So I temporarily introduced them in molecule.yml.
  • I am facing problem with tests. test_icinga_api.py silently hang for an unknown reason.
1 Like

Solved using symlinks. Molecule doc says “An alternative to the above Host/Group Vars is the creation of group_vars and/or host_vars directories in the project root.” Actually the “project root” is molecule/icinga and not ./.

Actually the up-to-date doc gives also alternative answer:

    provisioner:
      name: ansible
      inventory:
        links:
          group_vars: ../../../inventory/group_vars/
          host_vars: ../../../inventory/host_vars/

Got it!fit was due to firewall issues due to refactoring. Moreover no timeout was set in tests when calling requests, which leads to test hanging.

The use of when everywhere is a bit bloated, overload run with “skipped”, and doesn’t fit well chen we have to use multiple roles in the same task (coucou debops).

Then I tried yesterday to use groups with hybrid dynamic/static inventory sources. tl;dr : it doesnt works.

I face with at least two problems:

  • Once created an hybrid inventory, it doesn’t works because openstack.py seems to create a group for each host. Then we get this failure:
    ANSIBLE_INVENTORY=./inventory/ USE_CACHE=1 ansible-playbook --syntax-check molecule/postfix/playbook.yml -vvv
    [...]
     [WARNING]: Found both group and host with same name: postfix-host
  • It seems not possible to tell molecule to use ./inventory/. Molecule use a self generated inventory and I failed to understand (in a reasonable time) how does it manage from a groups attribute in molecule.yml to a group in ansible_inventory.yml. I feel not comfortable with forking molecule for now. :slight_smile:

Finally, I leave it out and acknowledge that VM roles are hardcoded by names in ansible philosophy. At least, a good news is that since we have a group for each host, we can easily make set operation as in http://lab.securedrop.club/main/securedrop-club/commit/3c233dc75ab128ca48fec3df91f250cf072f9401#2f96db3355c6179cf48bbe32dffd6195c6a60962_4_3

Now that we have static inventory generated from molecule, that should be better :slight_smile: I’m still not sure how to create groups that are understood by both molecule and ansible-playbook. One thing at a time.