An introduction to Terraform for using with AWS

Abstract

Engineers around the world today who are in the Devops are looking for services and products that can integrate with multiple cloud service providers. In these aspects, Terraform which is a Infrastructure as a Code Service is of huge significance as it is not limited to be used with a single cloud service but can integrate multiple like AWS, Azure, GCP etc.

Introduction

Terraform Cloud enables infrastructure automation for provisioning, compliance, and management of any cloud, data center, and service. It is managed by HashiCorp.  Using it, there is no need for unnecessary tooling and no need for console interface when interacting with AWS. Every terraform file must be saved in .tf extension.

Options used

Provider

Providers’ role is to be responsible for understanding API interactions and exposing resources, to the cloud service anyone uses. A general syntax of how the provider is used is :

provider "aws" {
  access_key= "your access key"
  secret_key= "your secret access key"
  region= "the region you are deploying the services to"
}

access_key and secret_key are those credentials provided when an IAM user is created in an AWS account. It is not a best practice to mention credentials in the text file, so a better way is to use environment variables, to store secret keys., here's how:,

create a variables.tf file and save the following

#define variables
variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "region" {
        default = "(your default region)"
}

then create a terraform.tfvars file and sve the credentials in them

aws_access_key = "ENTER-YOUR-ACCESS-KEY-HERE"
aws_secret_key = "ENTER-YOUR-SECRET-KEY-HERE"

now the provider would be defined like this:

provider "aws" {
access_key = "${var.aws_access_key}"
secret_key = "${var.aws_secret_key}"
region     = "${var.region}"
}
Resource

The resource is used to define any AWS service in the terraform, for eg – Route 53, EC2 etc. Following is a general syntax which defines a subnet in a specific availability zone. (I have taken ap-southeast-1 as an example for a region)

resource "aws_subnet" "tf_private_subnet1" {

vpc_id= aws_vpc.vpcmain_demo.id

cidr_block= "10.1.0.0/24"

map_public_ip_on_launch = false

availability_zone= "ap-southeast-1a" 
tags = {

Name = "private_subnet_1"

}

}

Defining some basic AWS services via terraform

Defining VPC

You can use resources section in AWS to define a VPC. Following is a syntax. DNS hostnames means enabling DNS service for Route 53 to be used.

resource "aws_vpc" "vpcmain_demo" {
  cidr_block           = "10.1.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true
  tags = {
    Name = "vpcA_aws"
  }
}
Defining a route table

Route tables are defined in AWS to give a routing path to the traffic coming in/going out. For this a CIDR block is needed. Here is the route table defined (gateway_id is the id of the internet gateway resource defined). CIDR block includes a range of IP addresses, where

resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.vpcmain_demo.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw_aws.id
}
tags = {
Name = "public_RT"
}
}
Defining security group

Security groups are used to define the traffic coming in/going out of the AWS instance. It contains inbound/outbound rules defined here by ingress/egress.

resource "aws_security_group" "sg1" {

name= "VPN_SG"

description = "Allow inbound traffic from corporate"

vpc_id= aws_vpc.vpcmain_demo.id

ingress {

description = "All access"

from_port= 0

to_port= 0

protocol= "-1"

cidr_blocks = ["10.0.0.0/16","10.1.0.0/16","10.2.0.0/16"]
}
egress {

from_port= 0

to_port= 0

protocol= "-1"

cidr_blocks = ["0.0.0.0/0"]

}
tags = {

Name = "VPN_SG"
}
}
Defining Elastic Load balancer (ELBs)

ELBs are used to distribute the incoming traffic between two or more EC2 instances to have an effective application performance. The general syntax for defining ELBs is:

resource "aws_lb" "test" {

name = "myalb"
internal = true
load_balancer_type = "application"

security_groups = [aws_security_group.sg1.id]
subnets = [aws_subnet.tf_private_subnet1.id,aws_subnet.tf_private_subnet2.id]
tags = {
Environment = "production"
}
}

Some commands for running the terraform application

Following commands need to be run in series for having terraform deploy the infrastructure in AWS.

terraform init – It is used to initialize a working directory containing Terraform configuration files. This is the first command that should be run after writing a new Terraform configuration or cloning an existing one from version control, if u do any changes in the working directory make sure to run terraform init every such time.

terraform plan - creates an execution plan, which lets you preview the changes that Terraform plans to make to your infrastructure. It shows the comparison between the current configuration to the prior state and noting any differences. This command is must before running the terraform apply command.

terraform apply - executes the actions proposed in a Terraform plan, after running this the infrastructure gets created or is updated with the required changes in the AWS.

terraform destroy - Destroy previously-created infrastructure.

terraform show - Show the current state or a saved plan

Conclusion

By using Terraform, we can deploy infrastructure easily using various configuration files, rather than doing it from a console where, it involves switching between pages in the console, which can be inefficient at times. Although the commands are a little challenging to use once, you go for an advanced level configuration, so combination of IAAC plus Console would be a solution in that case.