Introduction to Terraform
Tags: terraform, dataops, devops, cloud
Published: 2023-09-12 23:17:00

## TL;DR

Terraform is a tool used in the field of infrastructure as code (IaC) to create and manage computer resources – servers, networks, databases, and so on. It allows us to define a desired infrastructure in a configuration file using a simple and declarative language.

Once a Terraform project is started, the state of the managed infrastructure and configuration needs to be stored somewhere - usually locally or on AWS S3. Then, that state file is used by Terraform essentially to map real-world resources to our configuration file and keep track of metadata.

Here are some important Terraform commands to know:

- `terraform plan`: Generates an execution plan, showing changes to infrastructure resources that would be made when applied
- `terraform apply`: Applies the changes defined in Terraform configuration to create or update infrastructure resources
- `terraform destroy`: Destroys and removes all resources created by Terraform for a given configuration
- `terraform show`: Displays the current state or details of Terraform-managed resources
- `terraform import`: Imports existing infrastructure resources into Terraform's state for management

---

## What is Terraform?

Before we jump into coding things out, let's go over some key concepts of Terraform.

Terraform is a tool used in the field of infrastructure as code (IaC) to create and manage computer resources – servers, networks, databases, and so on. It allows us to define a desired infrastructure in a configuration file using a simple and declarative language.

Once we have defined our infrastructure configuration, Terraform takes care of provisioning and managing the resources. It interacts with cloud providers like Amazon Web Services (AWS) to create and update infrastructure based on the configuration provided in the file.

Using Terraform enables us to treat infrastructure as code – we can version control it, collaborate with others, and easily replicate or rebuild it in a consistent and repeatable manner.

And since we're going to be provisioning infrastructure in AWS, it's also important to understand the difference between a resource, an instance, and a service.

- A resource is a logical entity that represents a piece of AWS infrastructure – an S3 bucket, an EC2 instance, an RDS database
- An instance is a specific occurrence of a resource that is created from a particular template or configuration – an  EC2 instance is a virtual server that is launched from an Amazon Machine Image (AMI). Each instance is a unique copy of the AMI, with its own IP address, storage, and other attributes
- A service is a collection of related AWS resources and API operations that work together to perform a specific function – AWS offers over 200 different services, including compute, storage, database, analytics, machine learning, and more


## Getting the environment ready

There are a few steps we need to go through in order to get our development environment ready: 

- Install [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
	- Run `aws configure` on the terminal and provide the following parameters
		- `AWS Access Key ID` 
		- `AWS Secret Access Key`
		- `Default region name`
		- `Default output format`
- Install [Terraform CLI](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)

##  Project structure

Here's the project structure we are working with:

```
my-project/
└── terraform/
    └── main.tf
```

And here's the boilerplate code we're starting with:

```terraform
# Specify AWS resource
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = "us-east-1"
}

# Define where the state will be stored
terraform {
  backend "local" {
    path = ".tfstate"
  }
}
```

To start the Terraform project, we navigate to the *my-project/terraform/* directory and run `terraform init` which essentially downloads all necessary modules and defines the backend.

## Wait, what is this backend thing?

To understand what the Terraform backend is, let's quickly cover what a Terraform state is first.

You probably saw some state-related code in the code snippet I provided earlier:

```terraform
# Define where the state will be stored
terraform {
  backend "local" {
    path = ".tfstate"
  }
}
```

Once a Terraform project is started, the state of the managed infrastructure and configuration needs to be stored somewhere, and that state is used by Terraform essentially to map real-world resources to our configuration file and keep track of metadata.

Here are some key aspects of the Terraform state:

- Its primary purpose is to store bindings between objects in a remote system (e.g. an EC2 instance) and resource instances declared in a configuration file
- It's generally saved in a file called `terraform.tfstate`
- It can be stored locally – recommended for developing purposes
- It can be stored in the cloud (e.g S3) – recommended for deployment purposes, so it can be versioned, encrypted, and securely shared

The backend simply defines where Terraform stores its state.

## How to "run" terraform code

We already have some Terraform code, can't we just run it? Kinda. Let's take a look at the following commands:

- `terraform plan`
- `terraform apply`
- `terraform destroy`
- `terraform show`
- `terraform import`

### Terraform plan

The `terraform plan` command creates a plan. It can be used to preview the planned changes to the infrastructure.

Under the hood, the command:

- Reads the current state of any remote objects to make sure that the Terraform state is up-to-date
- Compares the current configuration to the prior state and notes any differences
- Proposes a set of change actions that should, if applied, make the remote objects match the configuration

### Terraform apply

The `terraform plan` command applies the changes to the infrastructure to get to the state where the remote objects match the configuration. `terraform apply` can be run without running `terraform plan` first although it's not recommended.

### Terraform destroy

The `terraform destroy` command is used to destroy all mapped objects. `terraform plan -destroy` can be used to see what destruction will be made beforehand.

It is also worth mentioning that if the infrastructure has already been provisioned with `terraform apply`, removing objects from the Terraform code and running `terraform apply` again will also destroy them.

### Terraform show

The `terraform show` command can be used at any time to inspect the configuration of a Terraform state.

### Terraform import

The `terraform import` command can be used for bringing existing resources under Terraform management.

With that in our toolkit, it's time to get our hands dirty.