The company where I work – Matillion – has been using Terraform for a little while now. Mostly in the Site Reliability Engineering (SRE) team, but more recently I’ve started to see Software Engineers – including those with more of a front-end focus – being encouraged to start learning it. I can only imagine that’s going on across the world at various companies and the interest in Terraform growing and growing.
Anyway, if you’ve heard of Terraform and aren’t sure what it is or why you might use it, let me explain the basics.
Popularity of Terraform
Sorry, I had to double-check my assumption first, and yes – it looks like Terraform is on an upwards trend in terms of popularity.
What is Terraform & what does it do?
Terraform is an open-source tool for automating the provisioning and management of your cloud infrastructure, platform and services.
If you’re looking to build a new application that requires various pieces of AWS infrastructure, for instance – a new VPC, EC2 servers, Route 53 domain routing, etc – you can provision it by defining that setup in a configuration file.
It is declarative language, meaning you don’t have to define every single step needed to achieve something, instead defining the target state. For instance, “I want 3 EC2 servers with a single AWS user with Full Access permissions to each of the servers – go make it happen!”
You do this via code, meaning Terraform can be described as an Infrastructure as Code (IaC) tool.
You can also manage existing infrastructure with Terraform, for instance to add a new server or change the permissions for a given user. As the infrastructure configuration is managed in code, it can be easily updated.
It’s also helpful for easily replicating existing infrastructure, such as moving from a development to a production environment.
A Short Story About Terraform
Terraform being declarative sounds pretty cool – and it is – but one example at work is a good reminder of why you shouldn’t take it for granted that it will always reach your target state in the best possible way.
The hosting provider of our main marketing website recommended a change to our DNS settings and so I reached out to our SRE team for support in getting those updated. We manage DNS via AWS Route 53 and the config is handled with Terraform.
So, we had the current state (how it was already) and we had the target state (an updated config file based on the new DNS settings provided by our website host). Great – good to go!
The Terraform plan was executed… and the site went down. Whoops.
What happened: my understanding is that Terraform deleted a record first before trying to add another which then caused an error and ultimately incomplete DNS settings.
What should’ve happened: I believe it should’ve either updated the record in-place or, failing that, created the new record first and then deleted the old one.
If Terraform was imperative, I imagine we could’ve and would’ve defined precisely what needed to happen and in what order, and perhaps the error wouldn’t have come about.
Terraform Architecture
Terraform has two main components; its Core and State. The Core takes two inputs; a TF-Config file and the existing State.
The config file essentially represents your target state; what is it that you want? Define it here! This relates to the earlier point of Terraform being declarative. As it’s managed in code, you also benefit from being able to version control your infrastructure.
The state represents the current state; what you have already.
Using those two inputs, the Core can work out what needs to happen in order to get from the current state to the target state.
The Core uses that input to manage Providers, such as cloud infrastructure (e.g. AWS), platforms (e.g. Kubernetes) and services (e.g. Fastly). A long list of Providers can be found here (currently over 2,000). It’s strength, however, is in managing cloud infrastructure.
Example Config File
Below is a config file taken from the AWS Get Started tutorial on the Terraform website. All it does is create a single T2 Micro sized EC2 server instance. If you’ve ever created an EC2 server via the AWS UI – or done anything in the AWS UI, really – then you’ll appreciate just how simple the code below is.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
}
}
required_version = ">= 1.2.0"
}
provider "aws" {
region = "us-west-2"
}
resource "aws_instance" "app_server" {
ami = "ami-830c94e3"
instance_type = "t2.micro"
tags = {
Name = "ExampleAppServerInstance"
}
}
Terraform Commands
You can run refresh
to get the current state from your infrastructure provider. This may be useful if it’s a new setup or if you’re checking to see if any changes have been made by someone else. This can happen when you have different people at your company with access to your cloud provider and not all of them managing it via code.
plan
is the process of determining what needs to change in your provider(s) in order to go from current state to target state.
execute
will essentially run the plan you’ve created above.
Finally, destroy
will delete all of the resources and infrastructure you have.