The Perfect Duo: Ansible and Terraform

In the world of software development, automation is the unsung hero that saves us from the drudgery of repetitive tasks and the pitfalls of human error. Two tools that have risen to the forefront of this automation revolution are Ansible and Terraform. While they serve different purposes, they complement each other beautifully, making them an indispensable duo in any DevOps toolkit.

What is Terraform?

Terraform, developed by HashiCorp, is a powerful infrastructure as code (IaC) tool. It allows you to define and manage your infrastructure using a declarative configuration file. With Terraform, you can provision and manage resources across various cloud providers, on-premises environments, and even hybrid setups. Its strength lies in its ability to manage the lifecycle of infrastructure resources, from creation to destruction, all through a simple and readable configuration file[2][4].

What is Ansible?

Ansible, backed by RedHat, is a versatile automation tool that excels in configuration management, application deployment, and orchestration. It uses a simple YAML syntax to define playbooks, which are essentially scripts that automate tasks on remote servers. Ansible’s agentless architecture makes it easy to integrate into existing workflows, and its extensive library of modules and roles simplifies complex automation tasks[2][4].

Why Use Ansible and Terraform Together?

While both tools can perform some overlapping tasks, their true power lies in their synergy. Here’s how they can work together seamlessly:

Terraform Provisioning

Terraform is perfect for setting up the underlying infrastructure. You can define your servers, networks, storage, and other resources in a Terraform configuration file. Here’s a simple example of how you might provision a few Droplets on DigitalOcean using Terraform:

provider "digitalocean" {
  token = var.do_token
}

resource "digitalocean_droplet" "web" {
  name       = "web-server-${count.index}"
  size       = "s-1vcpu-1gb"
  image      = "ubuntu-20-04-x64"
  region     = "nyc1"
  count      = 3
}

Ansible Configuration

Once the infrastructure is provisioned, Ansible takes over to configure the servers. You can write an Ansible playbook to install necessary software, configure the operating system, and ensure all components are in their desired state. Here’s an example playbook to install Apache on the provisioned Droplets:

---
- name: Install and configure Apache
  hosts: all
  become: true

  tasks:
    - name: Install Apache
      apt:
        name: apache2
        state: present

    - name: Start Apache
      service:
        name: apache2
        state: started
        enabled: yes

    - name: Create index.html
      copy:
        content: "Welcome to my web server!"
        dest: /var/www/html/index.html

Integrating Ansible with Terraform

There are several ways to integrate Ansible with Terraform, ensuring that your infrastructure is both provisioned and configured seamlessly.

Using Terraform’s Provisioners

Terraform provides local-exec and remote-exec provisioners that allow you to execute commands on the machine running Terraform or on the provisioned instances, respectively. Here’s how you can use these provisioners to run an Ansible playbook after provisioning the Droplets:

resource "digitalocean_droplet" "web" {
  name       = "web-server-${count.index}"
  size       = "s-1vcpu-1gb"
  image      = "ubuntu-20-04-x64"
  region     = "nyc1"
  count      = 3

  provisioner "local-exec" {
    command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i ${path.module}/hosts.ini ${path.module}/apache.yml"
  }
}

Using Terraform Output as Ansible Inventory

Another approach is to use the output from Terraform as input for Ansible’s inventory. Terraform saves the details of the provisioned resources in a state file, which can be parsed to extract IP addresses and other necessary information.

Here’s an example of how you can use the terraform-inventory tool to generate an Ansible inventory file from the Terraform state:

$ terraform-inventory -inventory terraform.tfstate

This will generate an inventory file that Ansible can use to target the provisioned instances.

Workflow Diagram

Here’s a simplified workflow diagram showing how Terraform and Ansible work together:

sequenceDiagram participant Dev participant Terraform participant Ansible participant Cloud Dev->>Terraform: Run terraform apply Terraform->>Cloud: Provision infrastructure Cloud->>Terraform: Return resource details Terraform->>Ansible: Trigger Ansible playbook via provisioner Ansible->>Cloud: Configure provisioned resources Cloud->>Ansible: Confirm configuration Ansible->>Dev: Report completion

Step-by-Step Guide

Here’s a detailed step-by-step guide to get you started:

Step 1: Set Up Your Environment

  • Install Terraform and Ansible on your local machine.
  • Set up your cloud provider account (e.g., DigitalOcean, AWS) and generate the necessary API tokens or keys.

Step 2: Generate SSH Key Pair

Generate an SSH key pair for authentication. This is crucial for both Terraform and Ansible to access the provisioned instances.

$ ssh-keygen -t rsa -b 4096 -C "[email protected]"

Step 3: Write Terraform Configuration

Create a Terraform configuration file to define your infrastructure. Here’s an example for provisioning Droplets on DigitalOcean:

provider "digitalocean" {
  token = var.do_token
}

resource "digitalocean_droplet" "web" {
  name       = "web-server-${count.index}"
  size       = "s-1vcpu-1gb"
  image      = "ubuntu-20-04-x64"
  region     = "nyc1"
  count      = 3
}

Step 4: Initialize Terraform

Initialize the Terraform working directory to prepare it for use.

$ terraform init

Step 5: Apply Terraform Configuration

Apply the Terraform configuration to provision the infrastructure.

$ terraform apply

Step 6: Write Ansible Playbook

Create an Ansible playbook to configure the provisioned instances. Here’s an example to install Apache:

---
- name: Install and configure Apache
  hosts: all
  become: true

  tasks:
    - name: Install Apache
      apt:
        name: apache2
        state: present

    - name: Start Apache
      service:
        name: apache2
        state: started
        enabled: yes

    - name: Create index.html
      copy:
        content: "Welcome to my web server!"
        dest: /var/www/html/index.html

Step 7: Integrate Ansible with Terraform

Use Terraform’s provisioners to execute the Ansible playbook after provisioning the instances.

resource "digitalocean_droplet" "web" {
  name       = "web-server-${count.index}"
  size       = "s-1vcpu-1gb"
  image      = "ubuntu-20-04-x64"
  region     = "nyc1"
  count      = 3

  provisioner "local-exec" {
    command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -i ${path.module}/hosts.ini ${path.module}/apache.yml"
  }
}

Conclusion

Ansible and Terraform are not just tools; they are the dynamic duo of infrastructure automation. By leveraging Terraform’s powerful provisioning capabilities and Ansible’s precise configuration management, you can create a seamless and efficient automation workflow. Whether you’re setting up a complex cloud environment or ensuring your servers are always in their desired state, this duo has got you covered.

So, the next time you find yourself drowning in a sea of manual tasks, remember: with Ansible and Terraform, you can automate your way to a more efficient, more reliable, and more enjoyable development experience. Happy automating