Ansible — Inheritance of Variables
In Ansible there are severall ways to pass variables to a Role, Task or a playbook.
I personally was very confused with this, when building my infrastructure.
If every single uses the same variables I could have put everything in a inventorie file. But after building some servers for infrastructure which all should use individual ntp or dns servers. It started to mess up.
Even today there are some quick runs from just a playbook where I for example need a specific log-file to be backed up.
Then I use the playbook file itself to specificy the path to the logfile I need.
I will try to explain where you’ve to put your variables to get them where you need them.
Which places are there?
- Inventories
- Group variables
- Host variables
- Playbooks
- Variables in Roles
In the following I will describe those places and how the inharitance goes along…
1. Inventories
Ansible is learning its variables from the :vars
section.
# ------------------------------------------------------
[Servergroup]
hostname.domain.local ansible_host=<ip of your host>
otherhost.domain.local[Servergroup:vars]
ansible_port=<ssh Port>
ansible_user=<user to connect via ssh>
ansible_become=<yes/no>
ansible_become_method=<su or sudo>
ansible_become_user=<user has the needed priviliges>
2. Extended Inventories Group-/Hostvars
2.1 Groupwise
I like to use group directories which contain a file which must be named as the group itself. So for example if you have a group Servergroup
you should name your group-var-file Servergroup.yml
.
ansible-inventories
├── group_vars
│ ├── all
│ │ ├── default.yml
│ ├── Servergroup
│ │ └── Servergroup.yml
[...]
The Servergroup.yml
then contains all variables you need for your group Servergroup.
---# Network Setup
dns_servers:
- 192.168.1.1
- 192.168.1.2
- 192.168.1.3
ntp_servers:
- 192.168.1.4
- 192.168.1.5
- 192.168.1.6
subnet: 192.168.1.0/24
domain_name: domain.local# Docker vars
docker_installed: true
2.2 Hostwise
You should use this as less as possible. This also will override your groupvars.
I use this for example to provision my infrastructure hosts which have individual DNS or NTP endpoints to use.
ansible-inventories
├── group_vars
│ ├── [...]
├── host_vars
│ ├── myinfrahost_one.yml
│ ├── myinfrahost_two.yml
The file should be named like your actuall host in your inventorie.
For example:cat host_vars/myinfrahost_one.yml
---
ntp_servers:
- ntp1.domain.com
- ntp2.otherdomain.com
- ntp3.thirddomain.com
dns_servers:
- 1.0.0.1
- 8.8.4.4
- 1.1.1.1
3. Playbooks
I use playbook variables if I want to do a quick run on one or more hosts.
Everything else which should remain on your hosts longer then one ansible_run should be stored in group_vars
or host_vars
.
- hosts: hostname.domain.local
vars:
ntp_server: ntp6.domain.com
4. Roles
In tasks you can easily use jinja2 templating language (see below) to refer to either in the defaults/main.yml
or vars/main.yml
.
$ cat tasks/main.yml
---
- name: Install Package
apt:
name: apt-transport-https
state: "{{ package_state }}"
4.1 Default Vars
Usually you use the defaults/*
dir which really should just contain default variables.
For example, my package should per default be installed.
$ cat defaults/main.yml
---
package_state: present
4.2. Vars (constants)
The vars/*
is more likely for lets say constants which will override any pre-defined-values.
This will always remove or not even install the package.
$ cat vars/main.yml
---
package_state: absent
5. Inheritance summary
Inventories:
Servergroup:vars
will be overritten bygroup_vars
,host_vars
and playbooks
Extended Inventories group_vars
:
- will be overritten by
host_vars
and Playbooks
Extended Inventories host_vars
:
- Overritten by Playbooks
Playbooks:
- Just by constants from Roles
Roles:
vars/*.yml
will override every pre-defined variabledefaults/*.yml
will be overritten by basically everything