Deploy infrastructure to AWS using Terraform

By Mateo Spak Jenbergsen
Published on 2023-03-16 (Last modified: 2023-09-16)

...

Terraform is one of the most useful and important tools for provisioning and managing infrastructure in the cloud. In this article, I will show you how you can deploy infrastructure to AWS using Terraform. This article already assumes you have an AWS account up and running. If not, please visit AWS documentation to learn how to set up an AWS account.

 

What is Terraform?

Terraform is a tool to build infrastructure as code created by HashiCorp. It allows us to build and maintain infrastructure in the cloud and for on-premise environments. The three main components of a Terraform workflow is, write, plan and apply. Write stage consists of writing our infrastructure as code (iac). Plan gives us a overview of how the changes made in the code base will affect the current state of the infrastructure. Here, Terraform will tell us what will be created, updated or destroyed in the current state. Terraform plan will also give us feedback on changes made outside of Terraform. The final stage is apply. Apply executes the changes provided in the code base. Terraform automatically updates changes and resources in the correct order to avoid any dependency issues.

Terraform uses a state file to track the current state of any infrastructure, meaning the state file reflects the real-world configurations. Whenever we want to make changes to our resources, Terraform first checks the state file to give us feedback about what changes will occur. Then, after running terraform apply the state file updates to match the new configuration. This might raise an issue when working with many developers on the same project. One developer might have a different state file version than another developer. To solve this, Terraform offers a service called Terraform Cloud which makes handling the state file easy. I will not go into how to set up Terraform Cloud in this article, but I will write an article on how to use Terraform Cloud sometime in the near future.

Terraform provides us with something called providers. Providers are plugins that are used to create and manage resources on different platforms. Using these providers gives Terraform access to the platforms API and can create and deploy infrastructure using API calls. AWS is one of many providers supported by Terraform. Other popular providers are Azure, Google Cloud Platform and Kubernetes. 

 

Using Terraform for AWS

Now, let's look at how we can provision AWS infrastructure using Terraform. In order for Terraform to makes change in AWS, it requires an IAM user. I have created an IAM user with programmatic access with the necessary permissions needed. The IAM user does not need any permissions specific to Terraform, but will need the required permissions to create whatever infrastructure you provisioning. 

First, I need to download the Terraform software. For MacOS I use Homebrew to install Terraform.

$ brew tap hashicorp/tap
$ brew install hashicorp/tap/terraform
$ brew update

 

I can verify that Terraform was successfully downloaded by running,

$ terraform -help

For more information about downloading Terraform on Windows and Linux, see Terraform documentation. 

I'll create a directory called my-first-terraform-project and create 2 files, provider.tf and main.tf

provider.tf

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}
  
provider "aws" {
  region     = "eu-north-1"
  access_key = "XXXXXXX"
  secret_key = "XXXXXXX"
}

Here, I configure my Terraform settings within the terraform {} block. I specify which provider and what version I want to use. Terraform recommends specifying the version to avoid errors that might occur if Terraform installs a new updated version that does not work with the configuration you use. I then specify the required parameters to connect to AWS in the provider "aws" {} block. Remember to use the correct region for your use case.

NOTE! It is not recommended to put AWS IAM user credentials directly into your provider configuration file. If this code is shared, the user credentials might be compromised. I would only suggest doing this while testing.

 

The recommended way for Terraform to authenticate with AWS is using AWS CLI. Using AWS CLI we can set the required parameters as environment variable locally on our computer as such.

$ export AWS_REGION = "my-region"
$ export AWS_ACCESS_KEY_ID = "XXXXXXX"
$ export AWS_SECRET_ACCESS_KEY = "XXXXXX"

 

Now, Terraform will automatically read from the local environment variables and will not require any parameters set in the provider block we created earlier.

provider "aws" {
  # No parameters needs to be set.
}

 

Next, I'll insert the following into main.tf.

module "vpc" {
  source = "terraform-aws-modules/vpc/aws"
  version = "3.0.0"

  name = "my-terraformed-vpc"
  cidr = "10.0.0.0/16"

  azs             = ["eu-north-1a", "eu-north-1b", "eu-north-1c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  enable_ipv6 = true

  enable_nat_gateway = false
  single_nat_gateway = true

  tags = {
    Terraform = "true"
  }

  vpc_tags = {
    Name = "my-terraformed-vpc"
  }
}

This creates a simple VPC with public and private subnets, a NAT Gateway and route tables associated with the subnets. I also tag my resource with "Terraform = true". This makes it easy to later identity which resources are Terraformed and which that are not in the AWS console.

 

I'll run the command,

$ terraform init

This needs to be run the first time we use Terraform in a project to initiate the configuration and download the AWS provider.

 

Next, I'll run,

$ terraform validate

This command will validate the code to make sure the code is syntactically valid. It is recommend to run this before deploying infrastructure.

 

Now, I want to see what changes will be made to my AWS configuration when I apply this code. I run the command,

$ terraform plan

This command, as explained earlier, will check the current state file against my code base and output what changes will be made to my AWS configuration after apply.

 

Finally, after reviewing the output from the last command to make sure the changes are what I expect, I can run apply.

$ terraform apply

Now, Terraform will again output the changes that are scheduled to take place and I will be prompted with an confirmation to apply the changes. Type yes and hit enter. Tip! Adding -auto-approve after terraform apply bypasses the confirmation required.

After some time, I should get a apply complete message and the infrastructure should be provisioned to my AWS configuration.

 

If I want to remove my newly created infrastructure, all I need to do is run,

$ terraform destroy

This will also prompt me with an confirmation. Type yes and hit enter. Now, Terraform destroys the infrastructure I just created. NOTE! I recommend always running terraform apply before running terraform destroy. This makes sure that the code base and state is up-to date. When destroying infrastructure, Terraform will use the state file to know what resource to destroy.

 

Summary

In this article, I've briefly explained how Terraform works. I've also showed how to deploy infrastructure to AWS using Terraform and given some advice on best practices around deploying, securing and destroying AWS configurations with Terraform. 




About the author



Mateo Spak Jenbergsen

Mateo is a Devops at Spak Consultants, with strong focus on AWS, Terraform and container technologies. He has a strong passion for pushing the limits when it comes to building software on cloud platforms.

Comments