Using variables in Ansible for better configuration

When deploying infrastructure with IaC, the code used is often composed of two parts:

  • A part that describes the elements or resources that make up the infrastructure
  • Another part that differentiates the properties of this infrastructure from one environment to another

This second part of differentiation for each environment is done with the use of variables, and Ansible has a whole system that allows us to inject variables into playbooks.

To see the use of variables in Ansible, we will complete our code and add a role called mysql in the roles directory with the following tree structure:

In the main.yml file of this role, we write the following code:

---
- name: Update apt cache
apt: update_cache=yes cache_valid_time=3600
- name: Install required software
apt: name="{{ packages }}" state=present
vars:
packages:
- python-mysqldb
- mysql-server

- name: Create mysql user
mysql_user:
name={{ mysql_user }}
password={{ mysql_password }}
priv=*.*:ALL
state=present

In this code, some static information has been replaced by variables. They are as follows:

  • packages: This contains a list of packages to install and this list is defined in the following code.
  • mysql_user: This contains the user admin of the MySQL database.
  • mysql_password: This contains the admin password of the MySQL database.

The different tasks of this role are as follows:

  1. Updating packages
  2. The installation of the MySQL server and Python MySQL packages
  3. The creation of a MySQL user

As we can see, in the user creation task, we have put in the mysql_user and mysql_password variables for the name and password. Hence, this information may be different depending on the environment, or may be instantiated dynamically when running Ansible.

To define the values of these variables, we will create a group_vars directory, which will contain all of the values of variables for each group defined in our inventory.

Then, in this group_vars folder, we create a database subdirectory corresponding to the database group defined in the inventory and a main.yml subfile.

In this main.yml file, we put the desired values of these variables as follows:

---
mysql_user: mydbuserdef
mysql_password: mydbpassworddef

Finally, we complete our playbook with a call to the mysql role by adding the following code:

- hosts: database
become: true
roles:
- mysql

We execute Ansible with the same command as the previous one, ansible-playbook -i inventory playbook.yml, and this is the output generated:

Ansible has therefore updated the database server with two changes that are the list of packages to be installed and the MySQL admin user. We have just seen how to use variables in Ansible, but this one is clear in the code, which raises security issues.

For more information about Ansible variables, read the complete documentation here:  https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html.

Let's now look at how to use Ansible Vault to protect playbook variables.