The Most Simplified Integration of Ansible and Terraform
By: Isha Jain
Tags: AWS, Terraform, Integration, DevOps, Ansible

Hola everyone! I am back with another demonstration to integrate different tools in the most simplified and elaborate manner.

Terraform and Ansible are two isolated tools having their own purposes but the fact that they can be integrated to solve typical use cases and the way they complement each other makes them even more popular.

Terraform

It is an infrastructure as a code (IaC) software tool used for building, changing, and versioning infrastructure. It works with 500+ providers whose resources can be used to provision the infrastructure.

Ansible

It is a configuration management tool that comes in handy in configuring and deploying applications on the infrastructure that is already set. In this article, we have configured the infrastructure deployed by terraform using Ansible.

Here in this demonstration, I have tried to integrate these tools by coordinating Terraform managed nodes with Ansible control nodes. For this, I will launch an AWS instance using terraform and then will use Ansible to configure that instance to deploy our webpage that will automatically open up after deployment. Let’s see how this can be done …

Creating AWS EC2 instance using terraform

To begin with the setup we use terraform code to create the infrastructure on AWS. We create an AWS EC2 instance and an EBS volume attached to it.

#aws instance creation

resource "aws_instance" "os1" {

ami = "instance-image-id"

instance_type = "t2.micro"

security_groups = [ "secret-group-name" ]

key_name = "key-name-used-to-create-instance"

tags = {

Name = "TerraformOS"

}

} #ebs volume created

resource "aws_ebs_volume" "ebs"{

availability_zone = aws_instance.os1.availability_zone

size = 1

tags = {

Name = "myterraebs"

}

} #ebs volume attatched to instance

resource "aws_volume_attachment" "ebs_att" {

device_name = "/dev/sdh"

volume_id = aws_ebs_volume.ebs.id

instance_id = aws_instance.os1.id

force_detach = true

}

After the infrastructure is created using Terraform all the information regarding the provisioned resource is saved in its terraform.tfstate file. This state file is used to retrieve the IP of the launched instance which is passes in the Ansible inventory file. This inventory file holds the information regarding its managed node where Ansible needs to install necessary applications.

Dynamic Ansible inventory file created and copied to remote Ansible Control node

For transferring the IP of launched AWS instance to Ansible, the IP is first copied to a file (ip.txt), which will work as an inventory for Ansible. This file is then copied to the Ansible control node using terraform connection. To connect to remote Ansible control node terraform use SSH connection.

#IP of aws instance copied to a file ip.txt in local system

resource "local_file" "ip" {

content = aws_instance.os1.public_ip

filename = "ip.txt"

} #connecting to the Ansible control node using SSH connection

resource "null_resource" "nullremote1" {

depends_on = [aws_instance.os1]

connection {

type = "ssh"

user = "root"

password = "${var.password}"

host= "${var.host}"

} #copying the ip.txt file to the Ansible control node from local system

provisioner "file" {

source = "ip.txt"

destination = "/root/ansible_terraform/aws_instance/ip.txt"

}

}

The inventory file gets copied to the Ansible control node from the above code:

inventory copied at Ansible control node

Variable.tf file

A variable.tf file is used to hold variables like “password” and “host” as shown below.

variable "password"{

type = string

}

variable "host"{

}

When we run the terraform file (ansi_terraform.tf) the values of password and host variable are asked dynamically, this prevents your password and personal IP from being exposed to anyone who has access to your code files.

variable’s value passed while running the terraform file

Running ansible playbook on remote system using remote-exec in terraform file

Now to configure the launched instance using Ansible we need to run the ansible playbook on a remote ansible control node from our local system where we have terraform. This can be performed by using the remote-exec feature of terraform which enables us to run commands on a remote system.

Note: In this demonstration, Terraform is used on Windows and since Ansible needs Linux OS we have used a remote Linux system as Ansible control node.

provisioner "remote-exec" {

inline = [

"cd /root/ansible_terraform/aws_instance/",

"ansible-playbook instance.yml"

]

}

The complete terraform code file ansi_terraform.tf can be found here.

Ansible playbook Tasks

We use ansible playbook to perform few tasks on AWS instance:

install httpd, php, git packages,

start the httpd service,

making a folder /var/www/html/web

formatting and mounting storage on /var/www/html/ folder

cloning the GitHub repository in /var/www/html/web folder

Note: In case you want to create a partition in Linux use the command fdisk device_name for example: fdisk /dev/xvdh , and an interactive terminal will open, it will ask for different options. You can enter ‘n’ for creating a new partition, ‘d’ for deleting one, and ‘h’ for help.

instance.yml ansible playbook

instance.yml ansible playbook

Note: For the complete downloadable ansible playbook please visit the GitHub repository here.

A detailed explanation on how to deploy a webserver on AWS using Ansible can be found in my previous article here:

Ansible config File

We are done with the major chunk here. Also, we need to provide the location of the ip.txt file on the Ansible control node in the ansible.cfg file as inventory address.

ansible.cfg file

Note: Ansible config file can be downloaded from here.

Terraform code block to open webpage automatically on local system

The final step is to open the webpage automatically on our local system when we are done with the setup. For this we use the following terraform code block:

provisioner "local-exec" {

command = "chrome http://${aws_instance.os1.public_ip}/web/"

}

All the terraform codes and Ansible playbooks can be found on the link below:

Now we are good to go on and run our terraform code, use terraform apply . It is a recommended to run terraform plan first.

terraform apply

AWS instance configured and ansible playbook running

output shows IP of instance

As soon as the output comes the webpage opens up to show the deployed webpage.

webpage automatically opens

Let us verify if our playbook was successful in installing the required packages in our instance. For this I logged in to my instance using EC2 Instance Connect.

required packages were installed and the git repository was cloned successfully

To summarize….

With just one click we have automated the whole workflow such is the power of automation by integrating DevOps tools. This was just a glimpse of its tremendous power. This integration can be extended to other cloud platforms like Microsoft Azure, GCP etc. as well to expand its scope.

Hope this article was capable to instill some curiosity to learn about the power of integration. Do leave a few claps if you liked my article or it helped in some way.