Raymii.org
Quis custodiet ipsos custodes?Home | About | All pages | Cluster Status | RSS Feed
Ansible: access group vars for groups the current host is not a member of
Published: 27-01-2017 | Author: Remy van Elst | Text only version of this article
❗ This post is over seven years old. It may no longer be up to date. Opinions may have changed.
Table of Contents
This guide shows you how to access group variables for a group the current host
is not a member of. In Ansible you can access other host variables using
hostvars['hostname']
but not group variables. The way described here is
workable, but do I consider it a dirty hack. So why did I need this? I have a
setup where ssl is offloaded by haproxy servers, but the virtual hosts and ssl
configuration are defined in Apache servers. The loadbalancers and appservers
are two different hostgroups, the ssl settings are in the appserver group_vars,
which the hosts in the loadbalancer group need to access. The best way to do
this is change the haproxy playbooks and configuration and define the
certificates there, but in this specific case that wasn't a workable solution.
Editing two yaml files (one for the appservers and one for the loadbalancers)
was not an option in this situation.
Recently I removed all Google Ads from this site due to their invasive tracking, as well as Google Analytics. Please, if you found this content useful, consider a small donation using any of the options below:
I'm developing an open source monitoring app called Leaf Node Monitoring, for windows, linux & android. Go check it out!
Consider sponsoring me on Github. It means the world to me if you show your appreciation and you'll help pay the server costs.
You can also sponsor me by getting a Digital Ocean VPS. With this referral link you'll get $200 credit for 60 days. Spend $25 after your credit expires and I'll get $25!
This is applicable for other scenario's as well. In templates this can be worked around by looping over all the groups, then over all the hosts in the specific group, then if the host is the first in the loop, go over all the hostvars for that host and then access the group var you want. This stackoverflow post goes over that. In my case I needed to access it in a playbook, the looping construction woudln't work there.
The inventory
In the inventory file I created a new group. This group has the two other
groups, appservers
and loadbalancers
in them and nothing else. Like so:
[appserver]
app1.cluster
app2.cluster
[loadbalancer]
lb1.cluster
lb2.cluster
[ssl:children]
loadbalancer
appserver
The shortnames expand to specifc SSH configuration. The ssl
hostgroup
effectively includes the following hosts:
- app1
- app2
- lb1
- lb2
However, we do need to modify the playbook that modifies the vhosts to only place the certificates on the loadbalancers, and do nothing with the certificates on the appservers. The playbook should still do it's normal thing, configuring the vhosts, on the appservers, but not on the loadbalancers.
The documentation has more information on hostgroups based on other groups.
The playbook
The playbook (deploy-vhosts.yml
) first was this:
---
- hosts: appserver
roles:
- apache-vhost
After changing the hostgroup we need to add the specific role that deploys the
certificates. We also put a when
in place to make sure the two roles only run
on the hosts where they should and not the other hosts:
---
- hosts: ssl
roles:
- {role: apache-vhost, when: "'appserver' in group_names" }
- {role: sslcerts, when: "'loadbalancer' in group_names " }
The group vars
The group vars for the appservers contain the following information to configure the virtual hosts:
---
apache_vhost:
example.cluster.nl:
name: example.cluster.nl
docroot: /home/example-cluster/domains/example.cluster.nl/public-html/
webuser: example-cluster
ssl_name: example.cluster.nl
serveraliases:
- www.example.cluster.nl
example2.cluster.nl:
name: example2.cluster.nl
docroot: /home/example2-cluster/domains/example2.cluster.nl/public-html/
webuser: example2-cluster
ssl_name: example2.cluster.nl
serveraliases:
- www.example2.cluster.nl
The problem is that, when the deploy vhosts playbook in run on the loadbalancers, they cannot access these variables since they are not in the same group.
The role
The role sslcerts
has one task file and one handler (restart haproxy
). It
makes sure the folder for the certificates exists and it places the certificate
files there. There are extra when statements to make sure it only runs on the
loadbalancers.
- name: create ssl folder
file:
path: /etc/ssl/cluster/
state: directory
owner: root
group: root
when: "'loadbalancer' in group_names"
tags: ssl
- name: place certificates
copy:
src: files/ssl/{{ item.value.ssl_name }}.pem
dest: /etc/ssl/cluster/{{ item.value.ssl_name }}.pem
with_dict: '{{ apache_vhost }}'
when: "'loadbalancer' in group_names"
notify: restart haproxy
tags: ssl
The crux
Even after configuring the special playbook that runs on all the hosts, the
loadbalancers still cannot access the group variables from the appservers. The
dirty hack part is that we symlink the group vars from the appserver
folder to
the loadbalancer
folder:
ln -s /home/deploy/ansible/group_vars/appserver/apache-vhost.yml
/home/deploy/ansible/group_vars/loadbalancer/apache-vhost-symlink.yml
Now, the loadbalancers have the group variable apache_vhost
as well, and when
the file in the appserver
folder is changed, the loadbalancer
file is as
well because it's a symlink.
haproxy
haproxy in this case has one frontend where all traffic comes into, the appservers handle the different virtual hosts:
frontend https-in
mode http
bind 1.2.3.4:443 ssl crt /etc/ssl/cluster/ no-sslv3
acl secure dst_port eq 443
rsprep ^Set-Cookie:\ (.*) Set-Cookie:\ \1;\ Secure if secure
rspadd Strict-Transport-Security:\ max-age=31536000 if secure
option httplog
option forwardfor
option http-server-close
option httpclose
reqadd X-Forwarded-Proto:\ https
default_backend appserver
haproxy handles sni
transparantly based on the requested hostname, if it finds
the certificate in the folder /etc/ssl/cluster/
. The files there are a
concatenation of the public key, the private key and if needed the certificate
chain.
Conclusion
In this case it might be better to change the haproxy playbook to handle this,
or to change the group_vars to all
. However, this environment has certain
constraints set, so this 'suboptimal' workaround works.