In this series
- Motivation & Ansible 101
- Terraform & Ansible
Enterprise developers are responsible for deploying infrastructure to multiple environments, such as development, staging, and production. One core problem with configurations in Terraform is that with the number of environments and variables, the number of “.tfvars” files used to manage configurations will increase. Several tools, such as Puppet, Chef, and Ansible, help simplify the management of configurations.
Ansible
Ansible is an open-source configuration management and deployment tool. It has a unique declarative language for describing system and application configurations.
You can install Ansible on one of the VMs (called Control Node) in your datacenter from where it can work against other VMs in your datacenter. Ansible stores the collection of systems that it can act on in its inventory file. Ansible can act on portions of its inventory and also on different inventories.
Ansible does not require agents/daemons executing on remote systems. It uses SSH to manage the remote systems, which leads to clean environments that have no Ansible components installed on them.
Installation
Ansible requires Python 2 or Python 3 as a prerequisite. You can install Ansible using the instructions on its documentation.
I am running Ubuntu on my Windows machine with WSL2. Ubuntu users can execute the following commands to install Ansible.
sudo apt update
sudo apt install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
To verify your installation, execute the command ansible --version
, which will produce a bunch of information about your installation. Let’s now discuss a few concepts that we will use to build our Ansible playbook.
Inventory
The default Ansible inventory is located at “/etc/ansible/hosts”. You can specify a different location of the inventory with the following command.
ansible -i <inventory_path>
Execute the command cat /etc/ansible/hosts
to view the default inventory specified in the INI format. The default inventory contains several examples of how you can set individual hosts, host groups, and patterns to select a group of hosts. You can use YAML to write the inventory file as well.
Suppose you want to specify several VMs as part of your inventory (SSH’able from the control node) that have a sequential hostname, e.g., frontend-1.example.com and frontend-2.example.com. You can specify them as part of the group frontend
with the following configuration.
[frontend]
frontend-[1:2].example.com
Playbooks
Ansible playbooks are files that contain configurations and definition of steps that should be executed in a defined manner. You can store this file in source control and manage configurations and your deployment workflow as code. Playbooks are expressed in YAML format.
Let’s create a basic playbook to understand it in detail. Create a file named writer_pb.yaml and add the following task to it.
- name: Write a simple file
hosts: localhost
tasks:
- name: Create a file here with text "The Cloud Blog".
copy:
content: "The Cloud Blog"
dest: "tcb.txt"
The definition of the playbook is self-explanatory. We defined the name of the playbook and then a list of tasks. The tasks are executed against one or more hosts, which you specify in the inventory. We defined one task in the playbook and the name of the built-in module used by the task. The copy
module takes the content of the file and target location as input. You can use the module to copy a file, or in this case, create a new file and add contents to it. You can view the plugins packaged in the Ansible binary in the Ansible documentation.
You might be wondering where the details of the host localhost
are coming from, even though it is not defined in the inventory. If localhost
is not defined in the inventory, Ansible creates an implicit localhost
for you. If you define a localhost
in your inventory, the implicit definition will be ignored.
To run the playbook, execute the following command.
ansible-playbook writer_pb.yaml
Following is the output generated by executing the command.
Execute the following command to view the contents of the file created by the playbook.
$ cat tcb.txt
The Cloud Blog
Congratulations! You successfully wrote and executed your first playbook. Ansible playbooks support parameters and environment variables as well, which make them very flexible.
Roles
A large number of playbooks and Ansible files can make your project unwieldy. Ansible Roles help you load related vars_files and tasks based on a known file structure.
Following is the standard Role directory structure recommended by Ansible. You can omit unused folders from the actual implementation.
dev.yml
test.yml
prod.yml
roles/
[role-name]/
tasks/
handlers/
library/
files/
templates/
vars/
defaults/
meta/
Here is what each folder contains.
- tasks: List of tasks to be executed by the role.
- handlers: Contains handlers that can be used within this role or outside this role.
- defaults: Default variables for the role.
- vars: Variables for the role.
- files: Files that can be deployed by the role.
- templates: Templates that can be deployed by the role.
- meta: Files containing metadata for this role.
- library: Modules used within the role.
We will soon build a role for deploying our infrastructure, so we will not address this feature in detail just yet.
Templating with Jinja2
Remember the copy
module? Ansible has a built-in module named template
that is used to generate configuration files. Ansible uses the Jinja2 templating language to enable dynamic expressions and access to variables.
Let’s create a simple playbook to gain familiarity with templating. Create a file named variable_writer_pb.yaml with the following content.
- name: Write a simple file
hosts: localhost
tasks:
- name: Create a file here with text read from variable.
template:
src: template.j2
dest: tcb.txt
Let’s define a template file named template.j2 at the same location as the previous file.
I am learning Ansible on {{ blog }}
Execute the following command to execute the playbook and pass the value of the parameter blog
.
ansible-playbook variable_writer_pb.yaml -e 'blog="The Cloud Blog"'
Inspect the contents of the file tcb.txt after executing the command, which should contain the complete message with the parameter substituted with the actual value.
We have covered all the information that we require for simplifying our Terraform configurations. In the next part of this article, we will use the concepts discussed here and build a Terraform plan that we can execute to provision infrastructure for different environments.
Did you enjoy reading this article? I can notify you the next time I publish on this blog... ✍