What is Terraform ? -Create EC2 Instance with Terraform

Büşra Erkoç
5 min readJan 24, 2021

In my previous post I explained how to create infrastructure with AWS console. This post will walk you through that how you can create the infrastructure on AWS EC2 instance using Terraform.

All of the codes used in this article available at :

https://github.com/busraerkoc/BookLibrary/tree/master/tf

What is Terraform ?

Terraform is a IaC (Infrastructure as a code ) tool. It allows build, change and create a version infrastructure. Terraform uses the HashiCorp Configuration Language ( HCL) and it is declarative. It’s multiplatform, so it can be install on Linux, Mac, Windows. It is multi-vendor. It provides the use of same language to deploy on a multitude of cloud providers such as AWS, Azure and Google.

For each vendor, instead of learning the IaC tool of that vendor, you can learn a single multi-vendor tool(Terraform).

How to install Terraform ?

  1. Download Terraform package for your operating system type. Terraform is distributed as a single binary. You can also download older versions of Terraform from the releases service. I installed Terraform v0.12.29.
$ curl -O https://releases.hashicorp.com/terraform/0.12.29/terraform_0.12.29_linux_amd64.zip

2. Unzip the downloaded package to a directory of your choosing.

$ sudo apt install unzip
$ sudo unzip terraform_0.12.29_linux_amd64.zip -d /usr/local/bin/

Common commands :

Configuring the AWS CLI

AWS CLI is a tool which is using to manage AWS services.

To install AWS CLI on Ubuntu 20.04 LST :

$ sudo apt-get install awscli

To configure your profile with your AWS account credentials :

$ aws configure
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]:
Default output format [None]:

Create a infrastructure with Terrafform

  1. Configure Network
  2. Create a key-pair
  3. Create EC2 instance

The syntax of Terraform :

<BLOCK-TYPE> "<BLOCK-LABEL" {
<IDENTIFIER> = <EXPRESSION>
}

First step is configure provider. We create a infrastructure for AWS. So our provider is aws. To configure provider, you need to use provider block. If you are not configure your AWS profile with aws configure, you can configure in provider block.

main.tf

provider "aws" {
region = var.region
}

You can define region manually ( region = “eu-central-1” )or dynamically with variable ( region = var.region). Input variables are used to simplify management and create a reusable configuration files. You can access the whole variables.tf file from the github repo.

variable.tf

variable "region" {
type = string
description = "Region of EC2 instance"
default = "eu-central-1"
}

Initialize Terraform

Terraform needs to provider’s plugins and initialize the working directory containing Terraform configuration files. Terraform provides them with

$ terraform init command.

This is the first command that should be run after writing a new Terraform configuration or cloning an existing one from version control.

Configure network

Create a VPC (Virtual Private Network). We want to our instance communicate with the internet. If a subnet have a route to the internet gateway that subnet is a public subnet. So we will create public subnet, internet gateway and route table.

network.tf

resource "aws_vpc" "myvpc" {
cidr_block = var.vpc_cidr
}
resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.myvpc.id
cidr_block = var.public_sb_cidr
map_public_ip_on_launch = true
tags = {
"Name" = "FlaskApp Subnet"
}
}
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.myvpc.id
tags = {
"Name" = "igw"
}
}
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.myvpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
}
resource "aws_route_table_association" "public_rt_assoc" {
route_table_id = aws_route_table.public_rt.id
subnet_id = aws_subnet.public_subnet.id
}

Primary network configuration created.

Security groups allows control incoming and outgoing traffic to instance. Define inbound rules for ssh and http with ingress blocks. Allow incoming traffic on port 22 and 80.

security_group.tf

resource "aws_security_group" "sg_flaskapp" {
name = "sg_flaskapp"
vpc_id = aws_vpc.myvpc.id
ingress {
cidr_blocks = ["0.0.0.0/0"]
from_port = 22
protocol = "tcp"
to_port = 22
}
ingress {
cidr_blocks = ["0.0.0.0/0"]
from_port = 80
protocol = "tcp"
to_port = 80
}
egress {
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
protocol = "-1"
to_port = 0
}
}

Create a key pair

We need key pair to connect our instance with ssh. Create a new key pair and locate it as a local file.

key_pair.tf

resource "tls_private_key" "pk" {
algorithm = "RSA"
}
resource "aws_key_pair" "kpair" {
key_name = var.key_name
public_key = tls_private_key.pk.public_key_openssh
}
resource "local_file" "private_key" {
content = tls_private_key.pk.private_key_pem
filename = "${path.module}/${var.key_name}.pem"
file_permission = "0400"
}

Create EC2 instance

Now we can define our EC2 instance. You can use “aws_instance” resource to define AWS EC2 instance. You can configure AMI ID in 2 ways.

  • In aws_instance resource, giving AMI ID to ami argument.
  • Defining the AMI ID dynamically. Get the ID of registered AMI with aws_aim data source.

When new AMI created, it’s id will change. Therefore, the best practice of defining AMI ID is to do it dynamically.

ami.tf

data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"]
}

Now we can create aws_instance resource :

compute.tf

resource "aws_instance" "flaskapp" {
count = var.count_flaskapp
ami = data.aws_ami.ubuntu.id
instance_type = var.flaskapp_instance_type
subnet_id = aws_subnet.public_subnet.id
key_name = aws_key_pair.kpair.key_name
vpc_security_group_ids = [ "${aws_security_group.sg_flaskapp.id}" ]
tags = {
"Name" = "flaskapp-${count.index+1}"
}
}

We complete our erraform configuration files. Now we can run them.

Terraform allows us check our configuration with $ terraform plan command. If you want to run configuration, you can use $ terraform apply command. You can use $ terraform destroy to destroy a created infrastructure.

$ terraform plan
$ terraform apply
$ terraform destroy

Congratulations! You created EC2 instance using Terraform. Also you can check it from AWS console.

check instance from AWS Console

--

--