Learn how Porter executed their cloud migration at scale → Watch Now
Terraform is an open-source tool created by HashiCorp that brings IaC to life. It is a declarative language that helps you define your infrastructure as code.
When I first started to code, I remember staring at my computer screen, fingers hovering over the keyboard as I had to update a load balancer configuration—a seemingly simple change to the infrastructure.
But even so, I was anxious. One mistake or typo could take down our system.
Managing infrastructure shouldn't feel so risky. There had to be a better way.
Infrastructure as Code (IaC), with tools like Terraform, changed this.
IaC allows you to manage and set up infrastructure using machine-readable files instead of touching hardware or using configuration tools. You write code to automate the process and this code replaces manual infrastructure setup.
In fact, the 2023 State of DevOps report found that organizations using IaC, achieve 30% higher organizational performance. And 68% of respondents saw faster development cycles after adopting platform engineering practices, which often include IaC.
Now, you might be reading this because you've had a similar experience as I did. Maybe you were tired of manual configuration errors. Perhaps your company is growing, and you want to scale your infrastructure management. This guide will help you.
We'll explore the basics of Infrastructure as Code(IaC) with Terraform and help you gain a solid conceptual understanding. But first, what exactly is Terraform and IaC?
Infrastructure as Code (IaC) is a dramatic shift in how developers manage and provision computing resources. IaC treats infrastructure configuration like software, so instead of manually setting up physical servers, networks, and other IT components, you define the setup in code. This code becomes a single source of truth for your infrastructure, helping you automate deployments, ensure consistency across the board, and scale your setup easily with no infrastructure drift.
But then, what’s Terraform and how does it relate to IaC?
Terraform is an open-source tool created by HashiCorp that brings IaC to life. It is a declarative language that helps you define your infrastructure as code.
You specify what you want—like a cluster of web servers and a load balancer—and Terraform figures out how to make it happen, whether you are using AWS, Azure, Google Cloud, or a mix of providers.
Terraform understands the current state of your infrastructure and makes only the necessary changes to achieve your desired state. This means you can update your infrastructure over time, adding new components or modifying existing ones.
Is there any benefit to using Terrform?
Terraform is like a Swiss Army knife for infrastructure management. Its versatility and ease of use have made it the go-to language for DevOps teams. Here are some of the key advantages of using Terraform:
These examples highlight just a few of Terraform's many benefits. As you begin using it, you will discover even more ways it can optimize your infrastructure management processes.
Let’s now jump into the steps to setup Terraform so you can get started implementing it.
You need Terraform on your computer before you can use it. Downloading Terraform is easy because it lives in a single file.
That’s it, Terraform is now installed on your computer.
With Terraform installed, you can begin your first project. Here's how to set up a basic Terraform configuration:
provider "aws" {
region = "us-west-2"
}
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
Congratulations! You used Terraform to provision your first resource. While this example is basic, it shows the fundamental workflow of using Terraform.
Let’s now explore the fundamentals of Terraform one by one—starting with what configuration files actually are.
Terraform configurations are written in HashiCorp Configuration Language (HCL) and describe exactly how you want your infrastructure to look. They detail the resources you want, their settings, and how they connect.
A typical Terraform configuration usually consists of one or more .tf files within a directory. When you use Terraform commands, it reads all these files. It then builds a dependency graph based on the resources you've defined.
Here’s a simple example of a Terraform configuration file:
provider "aws" {
region = "us-west-2"
}
resource "aws_instance" "facets_default_server" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
This tells Terraform to use the AWS provider. It sets the default region to "us-west-2" and creates an AWS EC2 instance. This instance uses the specified AMI and instance type.
Terraform configurations are declarative so you describe the desired end state and Terraform figures out how to make it happen. This differs from imperative programming where you specify every step.
This declarative approach offers several advantages:
Terraform configurations can include several block types:
As your infrastructure becomes more complex, you'll likely use multiple .tf files which helps organize different parts of your configuration. Terraform will automatically read and combine all these files into a single configuration later.
Terraform keeps track of the resources it creates in a state file (usually terraform.tfstate). Think of this file as the single source of truth for your infrastructure.
When you run terraform apply, Terraform follows these steps:
This ensures Terraform always knows the current state of your infrastructure and it can then make precise, incremental changes as needed. The state file is necessary for Terraform to work correctly so make sure that you store it safely and take backups at regular intervals in case of a loss..
Terraform supports various backends:
Here's how to configure an S3 backend in Terraform:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "directory-path/to/the/key"
region = "us-east-1"
}
}
With this configuration, Terraform will store its state file in the “my-terraform-state” S3 bucket, under the key “directory-path/to/the/key”.
The terraform plan and terraform apply commands let you preview and execute changes to your infrastructure safely and predictably.
Unless you disable it, Terraform first refreshes its understanding of the current state when you run terraform plan. It then determines the necessary actions to achieve the desired state you defined in your configuration files.
Do note that this command doesn't make any actual changes. It simply shows you what Terraform will do. You can review the plan before anything happens, helping you spot potential errors or unwanted modifications.
Here’s an example output from terraform plan:
$ terraform plan
# aws_instance.example will be created
+ resource "aws_instance" "example" {
+ ami = "ami-0c55b159cbfafe1f0"
+ arn = (known after apply)
+ associate_public_ip_address = (known after apply)
+ availability_zone = (known after apply)
...
}
Plan: 1 to add, 0 to change, 0 to destroy.
This plan shows that Terraform will create a new AWS EC2 instance with the specified AMI. The + indicates this is a new resource.
Once you've reviewed the plan and are happy with the proposed changes, use the terraform apply command. This command executes the plan and applies the changes.
By default, terraform apply asks you to confirm you want to proceed. You can skip this prompt using the --auto-approve flag. Just remember to be absolutely sure about the outcome before using this flag.
Here's an example of applying a Terraform configuration:
$ terraform apply
aws_instance.example: Creating...
aws_instance.example: Still creating... [10s elapsed]
aws_instance.example: Creation complete after 15s [id=i-01234as39a123df0]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
After the apply completes, your infrastructure will match the state described in your configuration files.
One of the key benefits of Terraform's plan and apply lifecycle is its focus on safe and predictable changes. Reviewing the plan before applying helps you catch potential issues early as Terraform tracks your infrastructure's state, making only the necessary modifications.
This contrasts with some other infrastructure management tools. They might require you to specify your entire infrastructure every time, leading to potential inconsistencies over time.
These concepts—configuration files, state management, and the plan and apply lifecycle—form the foundation of working with Terraform. Everything you build will be based on these basics.
However, the core workflow remains constant:
Terraform modules are a powerful way to organize and reuse your infrastructure code. Let's explore how to create and implement these valuable components.
As your infrastructure becomes more complex, managing it with a single Terraform configuration can feel overwhelming. This is where modules simplify things.
A Terraform module is essentially a set of Terraform configuration files grouped within a single directory.
These modules become your building blocks: they let you create reusable components, organize your code better, and manage parts of your infrastructure as self-contained units.
Think of a typical module structure like this.
├── main.tf
├── variables.tf
├── outputs.tf
└── modules/
├── vpc/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── ec2/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── rds/
├── main.tf
├── variables.tf
└── outputs.tf
Don’t worry if you don’t fully understand this right now. Just look at it as a sample directory structure of how modules and terraform configuration files are stored.
In this setup, you have a root module defined by the main.tf, variables.tf, and outputs.tf files in the main directory. The modules directory houses subdirectories for each of your infrastructure components, like VPC, EC2, and RDS. Each of these subdirectories represents a separate module.
You can use a module within another Terraform configuration. Use a module block to do this:
module "vpc" {
source = "./modules/vpc"
# Other module configuration
}
The source argument points to the module's location. Here, it's a relative path on the same machine, but it could also be a remote source like a Git repository or the Terraform Registry.
Modules offer several advantages for your Terraform configurations:
The Terraform Registry (https://registry.terraform.io/) offers a vast collection of pre-built modules for common infrastructure elements and these existing modules can significantly speed up your infrastructure development.
Now that you’ve understood the basics of Terraform for IaC, let’s look at the best practices for implementing IaC with Terraform.
Managing Terraform configurations effectively means adopting a GitOps workflow. This approach makes Git the single source of truth for your infrastructure and applications, just like your code.
You store your Terraform configurations in a Git repository to benefit from the version control and collaboration features. This approach lets you manage infrastructure code like application code.
You can use pull requests, code reviews, and automated testing. Here is an example of a typical GitOps workflow with Terraform:
This workflow ensures that all changes to your infrastructure are tracked and reviewed. It also helps make sure that you apply changes in a controlled way—you will always have an audit trail.
Terraform state keeps track of the resources Terraform creates. It also makes sure that Terraform can update or destroy those resources.
The state is stored locally by default using a file named terraform.tfstate. This works fine for one person.
However, it can cause problems for teams. If multiple people run Terraform at the same time, they can overwrite each other's changes and corrupt the state file.
To avoid these issues, use a remote backend to store your state. It stores the state file in a shared location. It could be Amazon S3, Azure Blob Storage, or any other cloud setup that you already have.
They often have locking mechanisms that prevent concurrent modifications and protect the integrity of your state file.
Terraform modules are a great way to package and reuse common configurations. You can easily create reusable Terraform code to reduce duplication and make your configurations easier to maintain. It also reduces duplication and promotes consistency.
A well-designed module should:
When creating modules, follow naming and structure conventions. HashiCorp recommends a standard module structure. This includes main.tf, variables.tf, and outputs.tf files.
Try to establish a consistent naming convention for your Terraform resources. This makes them easier to maintain and understand. Here are a few pointers for good naming:
Here’s an example naming convention:
<project>-<environment>-<resource_type>-<descriptor>
For instance:
myapp-prod-ec2-webserver
myapp-staging-rds-database
Maintaining a consistent naming standard across the team also makes it easier to understand each resource's purpose. It helps you identify resources belonging to a specific project or environment and avoid naming collisions when there is a large team working on the same projects.
While Terraform is a powerful tool, it’s not without its challenges. Here are some common issues you may encounter and how to address them:
Implementing IaC will be difficult at first. Remember your first time learning to code?
The syntax seemed strange, and the ideas were hard to grasp. Algorithms didn’t make sense.
But your confidence grew with every line of code you wrote and every bug you fixed.
Learning Terraform is going to be quite similar. It's just another way to interact with your infrastructure and like learning any language, you’ll get better as you write more code. But, this will take time for you, as well as everyone, who will be interacting with infrastructure on your team.
What if you could implement IaC without the difficulty of learning it from scratch? That is where Facets comes in.
Facets acts like an expert you can access anytime to guide you through the cloud. You can easily model your architecture, launch environments, and handle daily tasks with its no-code platform. Facets simplifies infrastructure management and frees you to focus on what's important—creating and deploying great software.
Want to experience no-code infrastructure automation to speed up your development workflows? Try Facets for free!