Our Thinking / Learn Terraform Installation and how to write an AWS Terraform Script
Infrastructure As Code

Learn Terraform Installation and how to write an AWS Terraform Script

Krishna Teja
K8s Expert @ TYNYBAY
Jan 21st, 2022
Timer Icon
Timer Icon
8
 m Read

Before diving into the terraform installation and template of creating AWS resources & setting up the network. We will have a brief about, What is Infrastructure as code? What is Terraform?

What is Infrastructure as Code (IaC)?

Infrastructure as code templates all infrastructure like virtual machines, networks, data centers, storage. Launching all the resources using template script skipping all the manual installation process.

Terraform is open-sourced infrastructure as a code software tool. It supports all the major cloud providers (AWS, Azure, Google Cloud, Kubernetes, Oracle Cloud, and Alibaba Cloud. Developers can plan, create and destroy all cloud resources using a terraform script.

How to install a Terraform and create a VPC connection and attach it to an EC2 Instance?

Step 1: Installing Terraform

1. Update the system packages.


sudo apt-get update

2. And make sure gnupg, software-properties-common, and curl packages are installed.


sudo apt-get install -y gnupg software-properties-common curl

3. Add the HashiCorp GPG key. Once steps 1 & 2 are done.


curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -

4. Add the official HashiCorp Linux repository.


sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"

5. Update the system again to add the repository


sudo apt-get update

6. Run the terraform install


sudo apt-get install terraform

7. Verify the installation by checking the terraform version


terraform version

Step 2: Creating a VPC connection and attaching it to an EC2 Instance using Terraform

1. Creating a directory and creating a .tf file


mkdir terraform-aws-vpc  (You can name the folder any)

For VPC


sudo vi terraform-aws-vpc.tf   (You can name the file any)

For VPC


mkdir terraform-aws-ec2  (You can name the folder any)

For EC2


sudo vi terraform-aws-ec2  (You can name the file any)

2.  AWS terraform script file

check-in-to the file, we will start adding the VPC connection required resource's snippet in the file


sudo vi terraform-aws-vpc/terraform-aws-vpc.tf
a. AWS virtual Private Cloud.

i. Virtual Private cloudAWS Virtual Private Cloud is a virtual network isolated to your AWS account where AWS resources can be launched in that virtual network.

VPC lets having complete control over virtual networking environment, including selecting own IP address ranges. If VPC wants to work, it needs to create some other couple of components like subnets, gateways, and route tables.

Terraform AWS VPC resource creation Declare your cidr_block address where you want to create your VPC connection.


resource "aws_vpc" "tf-vpc" {
    cidr_block       = "10.0.0.0/16"
    enable_dns_support = "true"
    enable_dns_hostnames = "true"
    enable_classiclink = "false"
    instance_tenancy = "default"
    tags = {
      Name = "tf-vpc"
    }
  }

ii. SubnetA subnet is a concept that divides an extensive network into sub-networks. Subnet leverage in launching multiple instances in multiple sub-networks or subnets. And dividing two or more networks is called subnetting.

AWS provides two types of subnetting: public, which allows the internet to access the machine, and private, which is hidden from the internet.

In this example, we will create one public and one private subnet.

To differentiate whether the subnet is public or private. Do not miss adding this config.

It makes this a public subnet. Default it will be like a private subnet.


map_public_ip_on_launch = “true”

Declare different cidr_block addresses for public and private subnets. If it is the same then it will cause an issue.

And attach the VPC id for which you want to create the subnet.

Terraform AWS Subnet creation.


resource "aws_subnet" "tf-public" {
     vpc_id     = aws_vpc.tf-vpc.id
    cidr_block = "10.0.1.0/24"
    map_public_ip_on_launch = "true"
    tags = {
      Name = "tf-public"
    }
  }

resource "aws_subnet" "tf-private" {
     vpc_id     = aws_vpc.tf-vpc.id
    cidr_block = "10.0.3.0/24"
    tags = {
      Name = "tf-private"
    }
  }

iii. Internet Gateway

An Internet Gateway (IGW) is a logical connection between an Amazon VPC and the internet. Without having an Internet Gateway in our VPC, we can not access the resources from the internet which are present in that VPC.

Attach the VPC id for which you want to create the subnet

Terraform AWS Internet Gateway.


resource "aws_internet_gateway" "tf-igw" {
      vpc_id = aws_vpc.tf-vpc.id
   
      tags = {
        Name = "tf-igw"
      }
    }

iv. Elastic IP

An Elastic IP address is a public static IPv4 address reachable from the internet. AWS uses elastic IP addresses to manage its dynamic cloud computing services.

When launching an EC2 instance, the public IP address will be generated by which that instance is reachable from the internet. Once stopping that instance and restarting it, a new public IP address will generate for the same instance.

So it is a problem to connect instances from the internet for not having a static IP. We attach an Elastic IP to an Instance that does not change after stopping/starting the instance to overcome this problem.

A static IP address is useful in many situations such as DNS    configurations, load balancing, failover, etc.

Terraform AWS Elastic IP


resource "aws_eip" "tf-eip" {
    vpc      = true
  
    tags = {
      Name = "tf-eip"
    }
  }

v. Network Address Translation (NAT) Gateway

NAT gateway enables instances present in a private subnet to help connect to the internet or AWS services.

Attach the elastic IP address and private subnet id created above.

Terraform AWS NAT Gateway


resource "aws_nat_gateway" "tf-ngw" {
    allocation_id = aws_eip.tf-eip.id
    subnet_id     = aws_subnet.tf-private.id
  
    tags = {
      Name = "tf-ngw"
    }
  }

vi. Route Table

A Route Table contains information that determines where the network traffic of a subnet or gateway will direct.

Each VPC has a default route table connected to each subnet. On the other hand, we can create our route table to define traffic flow within VPC.

We will create a Route Table for the VPC and attach one route table to an Internet gateway and another Route table to NAT Gateway.

Attach the VPC, internet gateway, and NAT gateway which created. Moreover, keep the cidr_block "0.0.0.0/0" to access from the internet anywhere.

Terraform AWS Route Table


resource "aws_route_table" "tf-rt-1" {
  vpc_id = aws_vpc.tf-vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.tf-igw.id
  }

  tags = {
    Name = "tf-rt-1"
  }
}

resource "aws_route_table" "tf-rt-2" {
    vpc_id = aws_vpc.tf-vpc.id
    route {
      cidr_block = "0.0.0.0/0"
      gateway_id = aws_nat_gateway.tf-ngw.id
    }
  
    tags = {
      Name = "tf-rt-2"
    }
}

vii. Route Table Association

Route table association creates an association between a Route table and a subnet, internet gateway, or virtual private gateway.

For attaching the Route table to a subnet, we will create a route table association.


resource "aws_route_table_association" "tf-rta-1" {
    subnet_id      = aws_subnet.tf-public.id
    route_table_id = aws_route_table.tf-rt-1.id
}

resource "aws_route_table_association" "tf-rta-2" {
    subnet_id      = aws_subnet.tf-private.id
    route_table_id = aws_route_table.tf-rt-2.id
}

viii. Security Group

A security group is a route traffic rule table for EC2 instances to control inbound and outbound traffic.

Security group and Route table are both used to create traffic rules, but Route tables are used in VPC for traffic direction at a subnet level, while SG is for instance level.

In the Ingress block, you can define your own traffic rules as per your requirement and attach the VPC id..


resource "aws_security_group" "tf-sg" {
    name        = "terraform-securtiy-group"
    description = "Allow terraform-securtiy-group inbound traffic"
    vpc_id      = aws_vpc.tf-vpc.id
   
    ingress {
      description      = "TLS from VPC"
          from_port        = 22
          to_port          = 22
      protocol         = "ssh"
      cidr_blocks      = [aws_vpc.tf-vpc.cidr_block]
    }
   
    egress {
          from_port        = 0
          to_port          = 0  
      protocol         = "-1"
      cidr_blocks      = ["0.0.0.0/0"]
    }
   
    tags = {
      Name = "tf-sg"
    }
}

We are done with configuring the VPC connection. We will now create an ec2 instance with a key pair and attach the created VPC connection.

b. EC2 Instance

Check-in to the file, we will start adding the EC2 connection required resource's snippet in the file.


sudo vi terraform-aws-ec2/terraform-aws-ec2.tf

i. Key Pair Generation

Key pair generation can be done on the local machine itself. Just run ssh-keygen, and it should prompt details on where to create the key.

Note: If you run the above command on your local machine, it will generate both the public key and the private key. Use the generated public key pair.


resource "aws_key_pair" "tf-first-key-pair" {
  key_name   = "tf-first-key-pair"
  public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8giupGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKVHO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwWdhXmXSrbX8ZbabVohBK41 email@example.com"
}

ii. EC2 instance creation

An Amazon EC2 is a feature where it provides virtual machines. Using EC2 instance, we can run applications on the AWS infrastructure. In AWS, virtual machines/servers are named as an instance. An instance creation can be done by configuring the memory, storage, availability zone where it should be available, and a lot more can be configured.

Use the AWS AMI id, which is suitable for the requirement.


resource "aws_instance" "tf-web" {
  ami           = aws_ami.ubuntu.id
  instance_type = "t2.micro"
    subnet_id = "${aws_subnet.tf-public.id}"
    vpc_security_group_ids = ["${aws_security_group.tf-sg.id}"]
    key_name = "${aws_key_pair.tf-first-key-pair.id}"
    
  tags = {
    Name = "Terraform-web"
  }
}

3. Intializing a Terraform

The terraform init command initializes the terraform configuration files in the working directory.

Terraform must initialize the provider before it can be used. Initialization downloads and installs the provider's plugin to later be executed.

Check into the directory of the VPC and run the terraform init command to download all required plugins of the provider & resources.

Repeat step 1 for the ec2 folder as well.

4. Doing a dry-run of the terraform script

Run the  terraform validate command before the plan. It validates script format and attributes are correct or not.

Run  terraform plan  now, which is used to create an execution plan. It will not modify things in infrastructure. It just helps in understanding what resources are going to create.

Check into the directory of the VPC and run the terraform validate and plan command to validate and see the resources that will create.


terraform validate terraform-aws-vpc/terraform-aws-vpc.tf

terraform plan terraform-aws-vpc/terraform-aws-vpc.tf

Repeat step 1 for the ec2 folder as well.


terraform validate terraform-aws-ec2/terraform-aws-ec2.tf

terraform plan terraform-aws-ec2/terraform-aws-ec2.tf

5. Applying the terraform script.

The terraform apply the command is used to apply the changes required to reach the desired state of the configuration.

From steps 3 & 4, We made sure configured .tf files, initialized & validated.

Now we are one step away from creating the resources.

Now run the VPC .tf file first.


terraform apply terraform-aws-vpc/terraform-aws-vpc.tf

Once all VPC resources are created successfully. Copy-paste id values of the VPC and public subnet id; otherwise, using the dynamic variables, we can get the values of the other to terraform script-generated value. Run the apply command for EC2 terraform file as well.


terraform apply terraform-aws-ec2/terraform-aws-ec2.tf

Finally, created an ec2 instance in a virtual private cloud defining our own CIDR-blocks, route table & security group as well.

Deployment Models & Multi-Cloud with Terraform

Next Blog

Related Articles