The world of Infrastructure as Code (IaC) is massive. On the one hand are the tools that handle infrastructure provisioning; on the other, the tools that handle configuration management. Ansible and Terraform are two of the big names in the IaC space. Let’s see how the Terraform vs. Ansible debate plays out.
What purpose do Ansible and Terraform serve? How do they approach managing infrastructure? Why does that matter? Spoiler alert: This article will show you rather than fight, these tools can complement one another and dovetail into a powerful toolset.
What is the Focus of Terraform and Ansible?
!["Focus" by toolstop is licensed under CC BY 2.0](https://adamtheautomator.com/wp-content/uploads/2021/07/Untitled-76-1.png)
The key to understanding the battle between Terraform and Ansible is to understand their focus. What does each tool aim to achieve?
Terraform is more infrastructure-focused. From the beginning, Terraform was designed to build the infrastructure around physical and virtual machines. Terraform has traditionally been an agnostic infrastructure-provisioning tool. Its focus wasn’t necessarily on the operating system (OS) like Linux or Windows.
On the other hand, Ansible has traditionally been focused on the operating system, not necessarily the infrastructure running the operating system. Tasks such as installing software, managing files, services, and other OS-specific scenarios are done well with Ansible.
As of around 2015, the ability to manage wider infrastructure in AWS, Azure, and other cloud systems has been added to Ansible, but that focus on the operating system remains.
The focus of each tool impacts the way they behave. Configuration management leads to a detailed focus, while an infrastructure focus is a more high level. Both have their place.
Infrastructure as Code: A Crucial Component
When you need to build a virtual machine, some cloud resource, or even just move some files around, the component will ultimately end up in a particular state. That state may have some additional files included in it, a new virtual NIC assigned, or an entirely new virtual machine in it. Regardless, an end state exists.
IaC aims to get you to that end state by allowing you to define it in a configuration and provide a tool that knows how to make it happen. IaC provides a way to define an end state in a configuration, run a tool, and that state automatically appears seemingly like magic.
IaC allows you to leverage the same tools and processes against your infrastructure as developers do against application design. You define the configuration in code and execute that code to build the infrastructure and define the configuration.
You can then set up that code in source/version control and leverage all of the advantages that software developers have when creating and collaborating on software projects like version control, easier collaboration, automated testing, and deployments.
Terraform and Ansible use a language to make IaC possible. Let’s look at the different approaches they take.
Layers of Infrastructure
One of the most important distinctions to understand when comparing Ansible and Terraform is the concept of “layers.” An operating system must have resources to run on; the operating system lies “on top” of the hardware or virtualized environment. You can think of a server as having two “layers.”
Terraform is more focused on the infrastructure, while Ansible is focused on the configuration of that infrastructure. Terraform typically focuses on the infrastructure “layer” where Ansible is more suited for the operating system “layer.”
Although Ansible started as a configuration management tool and has since grown to automate infrastructure provisioning, it’s still primarily used for operating system “layer” tasks. Terraform, on the other hand, was designed from the beginning to provision infrastructure.
Immutable vs. Mutable Resources
Software developers have a concept of mutability, meaning something can be changed. IaC is all about the state of a resource and changing that state to match the expectation. To make that change, you can either modify the state of an existing resource, making it mutable or destroy and create the resource again with the same configuration making it immutable.
To configure a web server on an existing Linux virtual machine, for example, you might need the Apache service installed along with many different Apache configuration items applied.
All tasks to configure Apache end up creating an end state. You can achieve that end state in two ways; changing the VM (mutability) or destroying the entire VM and creating it again from scratch (immutability). Ansible and Terraform are known for different approaches.
Ansible is typically known to focus more on mutability. By default, Ansible will not destroy a resource and instead always attempt to change the state. But, on the other hand, Terraform will destroy some resources and recreate them without much input from you. Each tool takes different approaches.
But, Ansible is not purely a mutable tool. It can just as easily deploy new VM images, such as Amazon Machine Images (AMIs) or Azure Managed VM Images, as Terraform can.
As you may have gathered, Terraform and Ansible are not entirely mutable or immutable. Terraform can perform mutable operations, such as increasing RAM on a VM, without powering off and replacing it. Ansible can deploy templates from base images. It’s worth understanding their default approach to get the most out of each tool.
Let’s Get Declarative
If you’re talking about tools in the IaC space like Terraform and Ansible, you must understand how those tools read and apply the configuration you define. To do that, you must understand the concept of a declarative configuration.
For example, in any server configuration, you’ll always have a set of steps to follow to set the state that you expect. Your tool of choice needs to follow those tasks to make that state possible. How it does so is an important concept to learn when comparing Ansible and Terraform.
Both Ansible and Terraform are known as declarative tools. Unlike imperative or procedural tools like scripts that force you to define how resources are provisioned without much focus on order, declarative tools allow you to define what the state will look like, and it does the rest.
Using a declarative tool, to create five web servers, you’d tell it “I would like five web servers” vs. an imperative or procedural tool, you’d need to say: “If these five web servers don’t already exist, create this one first and then the other four web servers.” Declarative tools save you time.
You can think of a cooking recipe as procedural, it gives instructions in order, and you much follow them one at a time to get the correct result.
Below are two examples comparing an Ansible playbook with a Terraform configuration to build an AWS EC2 instance from an existing AWS AMI. Notice how you don’t have to define how the instances are built; you simply tell them what to build, and it does the rest.
## Ansible configuration
- name: Create EC2 instances
ec2:
region: "us-east-1"
instance_type: "t2.micro"
image: "ami-0323c3dd2da7fb37d"
wait: yes
exact_count: 1
register: ec2
The Terraform configuration below would create the same EC2 instance.
## Terraform configuration
provider "aws" {
profile = "default"
region = "us-east-1"
}
resource "aws_instance" "web" {
ami = "ami-0323c3dd2da7fb37d"
instance_type = "t2.micro"
}
Note that Terraform has two ways of writing its config files, JSON and HCL2. HCL2 is Hashicorp’s configuration language and is preferred in all new code in their products.
When to NOT Use Ansible or Terraform
So far, you’ve read a lot about IaC, infrastructure, and configuration management concepts and how Ansible and Terraform both approach IaC. As of now, you may be thinking that both tools look great for every occasion! That thinking couldn’t be farther from the truth.
Both Terraform and Ansible both have their strengths and weaknesses. Before you start relying on one tool or the other for all of your automation tasks, be sure you know when not to use one tool over the other.
Terrraform
Immutability can sometimes be a hindrance in Terraform. If provisioning VMs using images, you may need tens of different images between web servers, application servers, messaging servers, etc. Since you can’t change the image itself with Terraform, you must have an image containing the exact state you need.
Now consider the services requiring a high rate of change. Do you keep the last three templates to roll back to? Or do you keep the last week’s worth?
If you roll out two changes a day for a week, that’s ten copies of that server. At 40GB+ per copy for a basic Windows Server install, that’s a lot of storage and a lot of templates to maintain.
Ansible
Ansible, on the other hand, struggles with issues outside of its control known as configuration drift. Configuration drift occurs when an administrator changes a setting on a resource under Ansible’s control but without using Ansible.
This configuration drift can lead to systems managed via Ansible becoming out of compliance and could lead to unexpected problems. A change made to Ansible and tested on a clean build in a lab doesn’t necessarily reflect what will happen when the change is applied to production.
Terraform vs. Ansible: Compared
Now that you’ve learned many of the most important concepts around these two tools, how do they stack up against each other on a few key metrics?
Terraform | Ansible | |
Focus | Infrastructure Management | Server Configuration Management |
Mutability | Immutable Templates | Mutateable Configuration |
Approach to applying Configuration | Declarative | Declarative |
Granularity | Server Image | Individual files and even file contents |
Not Terraform vs. Ansible but Terraform AND Ansible
Each tool has its advantages and disadvantages, but the question shouldn’t be “Which tool should I use?” but more “How do I use each tool together?” Terraform can lead to “image sprawl” while Ansible can’t control all changes, so bring them together!
Imagine you provide specialist website hosting. Each of your clients has an identical infrastructure design with a few web servers, a set of application servers, and a few database servers. Most of the configuration for each resource is the same.
To prevent having to create separate VM configurations for each client, you decide to create a separate image for each VM that accounts for all of the similarities across all types of VMs.
You then deploy each server using a set of standardized VM images, which gets you close to your desired end state. But, you must apply some client-specific OS configuration to each VM. To do that, you add Ansible to your deployment process. Using a custom Ansible playbook defined by the client, Ansible then applies all necessary OS-level configuration each client needs.
You have the best of both worlds. You have automated the common infrastructure-level tasks with Terraform and then used Ansible to take care of the remaining tasks. Now, you can deploy a new system quickly when templates are updated, but you don’t have to manage hundreds of different templates.
You can also safely apply changes to an existing environment by deploying a new template and running the Ansible configuration once against it. Configuration drift is a thing of the past.
Too many tools aim to be the “One True Tool.” A few specialist tools can be much better. Just ask a carpenter or mechanic!
Conclusion
Terraform and Ansible are both great tools. They set out to do a job, and they achieve that aim brilliantly. Both tools are evolving to handle the concerns mentioned throughout this article.
Fundamentally, each tool aims to achieve different things and never completely match each other’s feature set. This focus is a good thing! So why not get started with Terraform and Ansible right now and start your IaC journey!