Terraform AWS: Beginner’s Guide

Welcome back to our series on Terraform, where we break down must-know topics. This particular blog will focus on the basics of Terraform AWS, and how to easily spin up a server.

JAN 8, 2021 | ABHISHEK HUGAR
undefined

Welcome back to our series on Terraform, where we break down must-know topics. This particular blog will focus on the basics you should know in order to spin up your infrastructure on Amazon Web Services (AWS).

If you’re visiting this post, we’re assuming you’re already aware of Terraform basics, and how you can utilize it to create templates to write your configurations. If not, we have a series of Terraform tutorials that can get you up to speed.

In this blog on Terraform AWS, we’ll go over the foundations, as well as how to create a template. Stay tuned for our next series of posts, where we’ll dive deeper into common problems on Terraform AWS and how to solve them.

Looking to connect with other Terraform learners, as well as experts? Join our InfraCode Slack community to stay up-to-date on the latest news and receive one-on-one help on your Terraform project.


Terraform AWS: An Introduction

Amazon Web Services, also commonly abbreviated as AWS, is a cloud platform offering cloud-based products such as storage, analytics, networking, etc, with pay-as-you-go pricing. This means that AWS will provide you with a platform and required features to set up your infrastructure, but you will still need a tool to write your Infrastructure as Code and then spin it up on AWS. That’s where Terraform comes in.

Source: Terraform on AWS

Before taking a look at how to create a Terraform AWS template, let’s look at some of the prerequisites:

1. You’ll need to install Terraform

2. Sign up for an AWS Account, and preferably have AWS CLI installed too.

3. When you set up an AWS account, you receive the root-user credentials. A root user is a user who has access to all features. Move on to the Identity and Access Management console (IAM) to set up users with more restricted access. Once this user is set up, you’ll receive an AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

4. After you have your keys, you can either use the “aws configure” command in the AWS CLI to configure or save these credentials as “Environment Variables”.

After you’ve set up these basic steps, you’ll be ready to write the Terraform AWS configuration.

Creating a Template for Terraform AWS

A Terraform template is a collection of files that, together define the state of your infrastructure. There are usually three main basic files in every module of your template:

  • main.tf
  • variables.tf
  • outputs.tf

Remember that all the files will be coded in block structure, and you may write your configurations using any text editor, such as Visual Studio, Atom, Sublime Text, etc.

To create a Terraform AWS template, first create a main.tf file. In this particular file, we’ll describe the provider that we’ll be using to set up our infrastructure, and also the resources related to that particular provider. We’ll first define the “terraform” block inside which includes the “required_providers” block.

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "3.22.0"
    }
  }
}

Here, we’ve specified that we’ll be using the AWS provider, defined the version that Terraform should download or use, and also defined the source to download from.

For the version argument, you may also assign the value containing a tilde followed by greater than sign, "~>" means either: use the version number mentioned or any other greater version.
Example usage: version= “~> 3.3.0”.

Now that we’ve defined the “required_providers” block, we can move onto defining the “provider” block for our Terraform AWS template. In this block, we’ll write the configurations for the provider. This block acts as a plugin and is responsible for all the interactions and inclusion of the resources. Your provider block will usually contain a “profile” argument and a “region” argument. If you’ve saved your credentials as environment variables, you don’t have to bother using the “profile” argument. If you’ve used the “aws configure” command and configured the credentials manually, then you’ll have to set the argument “profile” to “default”. Since the resources in AWS vary from region to region, you’ll have to select the right region to match your requirements.

The provider block when you’ve used the “aws configure” command to set up the AWS CLI:

provider "aws" {
  profile = "default"
  region = "us-east-1"
}

The provider block when you’ve added the user credentials as environment variables:

provider "aws" {
  region = "us-east-1"
}

Once we have the provider block ready in our main.tf file, we define the “resource” block. This block will begin with the keyword resource followed by the type of provider. In this case, we’ll use “aws_instance” and then give a local name to the block (“sample” in the case below).

Inside the block, we’ll write the configurations--“ami” stands for Amazon Machine Image which can be run on your particular EC2 instance. These may be selected from the Amazon marketplace based on your needs. Next, “instance_type” specifies the EC2 instance type, and this will determine the amount of memory space that will be allocated. “T2.micro” means 1 virtual CPU, 1 GB of memory, and low network performance. Finally, the “tags” block will contain an argument “name”, which will give the instance a name of your choice.

resource "aws_instance" "sample" {
  ami           = "ami-0ff8a91507f77f867"
  instance_type = "t2.micro"

  tags = {
    Name = "aws-blog"
  }
}

Once you’re comfortable with Terraform AWS, you can spin up any number of servers and their associated resources--and even create dependencies. However, for the purposes of this guide, we’ll stick to a simple single server and get more advanced in the future.

Terraform AWS: How to Allow for HTTP Traffic

Up until this point, we’ve seen how to create a simple single server. However, the EC2 instance created by us does not allow for HTTP traffic. Let’s see how we can allow HTTP traffic when setting up the server as a web server for Terraform AWS.

First, we’ll have a tfvars file named “vars.tf” with a Terraform variable called “sample_port” in order to mention which port we need to allow the traffic in from. Below is a snippet of what the tfvars file looks like:

variable "sample_port" {
  description = "Sample port that will be used for HTTP requests"
  type        = number
  default     = 80
}

The “variable” block will start with the variable keyword followed by a local name given to the variable. The block will contain a description and the type. It’s good to know that the “default” value is not mandatory. If we don’t use it, then we’ll be prompted on the CLI to enter a value. Using the “default” argument avoids this hassle altogether. We’ve set the default port to 80.

Now that we have the tfvars file ready, we’ll move back to our main.tf file to define the resource block.

resource "aws_security_group" "webb-security-group" {
  name        = "web-sg"
  description = "Used in the terraform"

  ingress {
    from_port   = var.sample_port
    to_port     = var.sample_port
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

We’ll write a resource for the EC2 “security group”, in order to allow incoming traffic from port 80. The block will contain a name argument, with the name value of your choice. You may also have an optional argument called “description”. We then write the ingress block and specify that traffic should be allowed on port 80. To specify the IP address range, we’ll use the CIDR block. We assigned it the value of “0.0.0.0/0” so that all possible IP addresses are allowed.

It’s important to remember that we’ll also have to add another argument to our EC2 instance resource block to ensure that this works correctly. This is the vpc_security_group_ids, to which we assign the id of the security group. The initial resource block for Terraform AWS will now look like:

resource "aws_instance" "sample" {
  ami           = "ami-0ff8a91507f77f867"
  instance_type = "t2.micro"
  vpc_security_group_ids = [aws_security_group.web-security-group.id]

  tags = {
    Name = "aws-blog"
  }
}

Adding the “vpc_security_group_ids” argument here (to which the value assigned) is a reference to a different resource block that brings together the dependency of resources. In simple terms, we’ve written that “aws_security_group” is created first and then the EC2 instance is created.

You may write some simple web script code after the argument “vpc_security_group_ids” as “user data” or use some tool to have your web server installed with your AMI.

Once all these are done, you may also add the “output variables” block. This block can be used to display any output on your console after you’ve used the “terraform apply” command.

output "public_ip" {
  value = aws_instance.sample.public_ip
}


For example, in this case, we’ve defined an output variable to display the IP address of our server.

Finally, we have a “main.tf” file with resources and output values. We have a tfvars file with our variables.

We’ll have to use the following commands to spin up our Terraform AWS server:


We hope that you enjoyed our blog on Terraform AWS basics, and found it to be informative. Stay tuned for our upcoming blogs on the topic, and much more DevOps content.

If you’re looking to learn more, or still have questions about Terraform AWS, join our InfraCode Slack and get hands-on help from experts.