May 17, 2022


Born to play

Ansible variables: choosing the right location

Defining variables for your Ansible playbooks and roles can become challenging as your project grows.

Searching the Ansible documentation, the range of Ansible variables location is complicated, to say the least:

  1. command line values (for case in point, -u my_consumer, these are not variables)
  2. part defaults (outlined in part/defaults/key.yml)
  3. inventory file or script team_vars
  4. stock team_vars/all
  5. playbook team_vars/all
  6. stock team_vars/*
  7. playbook team_vars/*
  8. stock file or script host_vars
  9. stock host_vars/*
  10. playbook host_vars/*
  11. host facts / cached established_specifics
  12. perform vars
  13. perform vars_prompt
  14. play vars_data files
  15. purpose vars (outlined in role/vars/key.yml)
  16. block vars (only for responsibilities in block)
  17. process vars (only for the activity)
  18. contain_vars
  19. established_information / registered vars
  20. purpose (and involve_purpose) params
  21. include params
  22. extra vars (for example, -e "user=my_user")(generally acquire precedence)

There are 22 different destinations wherever to retailer your variables! As your code evolve and turn out to be extra advanced, it can get messy.

Define your very own subset of variables locations

The uncomplicated way

Whenever you feel of a variable, it need to be obvious where by it is defined. If not, it’s possible you are spreading your variables in too several destinations. Start out with a thing easy, for instance getting only 2 destinations in which your variables can be outlined:

  1. job defaults (defined in position/defaults/most important.yml)
  2. role (and consist of_function) params

roles/serviceA/default.yml: this file defines all variables expected by the role, with some default values. Note how we can remark variables that are needed, but for which we really do not want to supply any default value. By executing that, we are documenting each variable the position desires.

servicea_log_dir: /var/log/servicea

servicea_autorestart: yes

serviceA.yml: this file is the playbook in which the role is identified as. We put our custom made configuration there.

- hosts: groupa
  - function: serviceA
      servicea_person: gollum
      servicea_autorestart: no

We chose 2 areas for our challenge: position defaults, et job params. It is easy to know where to uncover our variable. It ought to do the job in most cases.

A a lot more generic way

Let’s have a different subset of areas.

  1. part defaults (defined in role/defaults/most important.yml)
  2. inventory team_vars/*

roles/serviceA/default.yml: part defaults, outlined in the exact same as the preceding case in point.

servicea_log_dir: /var/log/servicea

servicea_autorestart: indeed

stock/team_vars/servicea.yml: these variables are heading to be connected with the group known as servicea

servicea_person: gollum
servicea_autorestart: no

It is then expected to associate the right way the purpose to the hosts exactly where you have defined the variables (reminder: at runtime, variables are in the finish related with a host: there is no groups or job default, only host variables). The playbook:

- hosts: servicea
  - role: serviceA

Now let us say we want to have several roles, servicea and serviceb, to run on a person team called for example worker. We could generate the custom configuration for both equally services (servicea and serviceb) in a solitary file: inventory/group_vars/worker.yml but then it is actually not clear the place to come across your personalized variables.

As an alternative, we can have 1 group per service, so 1 configuration file per support in the team_vars folder (servicea.yml and serviceb.yml). We then affiliate the worker hosts to the team of our different services. inventory/hosts:




A wrong way

Let’s just consider the 2 preceding examples and mix them. We pick 3 destinations:

  1. position defaults (outlined in role/defaults/main.yml)
  2. inventory team_vars/*
  3. role (and involve_role) params

Let us say we want to modify servicea_log_dir variable. We can not adjust the job defaults variable, as we want our own custom benefit. Now do we transform it in the group_vars or in the position params? The two work, and there is no way to determine out which spot you would select, unless there is a specific logic at the rear of it. This is not appropriate and we want to hold points uncomplicated.

Consider gitops

When deciding on the handful of places to use, consider about what impact it will have on your code versionning.

The gitops methodology may well aid you out. In shorter, you want to break up your code in 2 repositories: your code repository, and your ops repository.

Making use of it to Ansible, your code repository is where you edition your roles or your Ansible collections. Your ops repository is the place you version almost everything particular to an occasion of your code namely your stock and custom variables.

When making use of the easy way, you will have to model your playbooks in your ops repository, as they contain your customized variables. When working with the next approach we explained, in which each customized variable is in the inventory group vars, you can edition only the inventory in your ops repository.

What issues is that it should be feasible to split the generic code and the houses that are good to an instance. For illustration, storing tailor made variables in the vars folder of a job (eg. roles/servicea/vars/principal.yml) is not right.

If you imagine of any variable and know for guaranteed wherever it has been described, then you are probaly undertaking issues suitable.