Creating AWS VPC using Terraform with some additional features
By: Gyanesh Sharma
Tags: AWS, Terraform

This task is inspired by TASK 3 and performed with some extra/additional features like NAT Gateway to provide the internet access to instances running in the private subnet.

Find Task 3 here : https://gyaneshsharma4.medium.com/creating-aws-vpc-using-terraform-7b40d0313e6d

Steps to understand the task better :

1. Write an Infrastructure as code using terraform, which automatically create a VPC.

2. In that VPC we have to create 2 subnets:

1. public subnet [ Accessible for Public World! ]

2. private subnet [ Restricted for Public World! ]

3. Create a public facing internet gateway for connect our VPC/Network to the internet world and attach this gateway to our VPC.

4. Create a routing table for Internet gateway so that instance can connect to outside world, update and associate it with public subnet.

5. Create a NAT gateway for connect our VPC/Network to the internet world and attach this gateway to our VPC in the public network

6. Update the routing table of the private subnet, so that to access the internet it uses the nat gateway created in the public subnet

7. Launch an ec2 instance which has Wordpress setup already having the security group allowing port 80 so that our client can connect to our wordpress site. Also attach the key to instance for further login into it.

8. Launch an ec2 instance which has MYSQL setup already with security group allowing port 3306 in private subnet so that our wordpress vm can connect with the same. Also attach the key with the same.

Tools and prerequisites for the task:

AWS Console Account AWS CLI Terraform Installed Putty or Mobaxterm

Steps to perform task:

Step 1: Defining the provider on which we have to create infrastructure. In our case is AWS.

provider "aws" {

region = “ap-south-1”

profile = “default”

}

Step 2: Creating a VPC with CIDR Block and enable DNS Hostnames to assign DNS names to instances.

resource "aws_vpc" "myvpc" {

cidr_block = "192.168.0.0/16"

instance_tenancy = "default"

enable_dns_hostnames = "true"

tags = {

Name = "myvpc"

} }

Step 3: Creating subnets [Public and Private]

(i) Public subnet

resource "aws_subnet" "publicsub" {

vpc_id = "${aws_vpc.myvpc.id}"

cidr_block = "192.168.0.0/24"

availability_zone = "ap-south-1a"

map_public_ip_on_launch = "true"

depends_on = [

aws_vpc.myvpc,

]

tags = {

Name = "publicsub"

} }

(ii) Private Subnet

resource "aws_subnet" "privatesub" {

vpc_id = "${aws_vpc.myvpc.id}"

cidr_block = "192.168.1.0/24"

availability_zone = "ap-south-1b"

map_public_ip_on_launch = "false"

depends_on = [

aws_vpc.myvpc,

]

tags = {

Name = "privatesub"

}

}

Step 4: Create a public facing internet gateway for connecting VPC/Network with the internet world and also attach gateway to VPC.

resource "aws_internet_gateway" "nicrogg" {

vpc_id = "${aws_vpc.myvpc.id}"

depends_on = [

aws_vpc.myvpc,

]

tags = {

Name = "nicrogg"

} }

Step 5: Write a Terraform code to Create a routing table for Internet gateway so that instance can connect to outside world, update and associate it with public subnet.

resource "aws_route_table" "nicrotab1" {

vpc_id = aws_vpc.myvpc.id



route {

cidr_block = "0.0.0.0/0"

gateway_id = aws_internet_gateway.nicrogg.id

}

depends_on = [

aws_vpc.myvpc,

]

tags = {

Name = "nicro"

} }

Association with subnet

resource "aws_route_table_association" "associate_1" {

subnet_id = aws_subnet.publicsub.id

route_table_id = aws_route_table.nicrotab1.id

depends_on = [

aws_subnet.publicsub,

]

}

Step 6: Creating a Elastic IP for the AWS VPC.

resource “aws_eip” “nicro_eip”{

vpc = true

}

Step 7: Creating a NAT gateway and allocate the elastic IP to it and put it in public subnet.

resource “aws_nat_gateway” “nicronat1”{

allocation_id = aws_eip.nicro_eip.id

subnet_id = aws_subnet.publicsub.id tags = {

Name = “nicronat1”



} }

Step 8: Creating a Route Table with CIDR block 0.0.0.0/0 to connect any IP and attaching it to NAT Gateway.

resource "aws_route_table" "nicrotab2"{

vpc_id = aws_vpc.myvpc.id route { cidr_block = "0.0.0.0/0"

nat_gateway_id = aws_nat_gateway.nicronat1.id

} depends_on = [

aws_vpc.myvpc

] tags = {

Name = "nicrotab2"

}

}

Step 9: Now create Associate route table in PRIVATE SUBNET.

resource “aws_route_table_association” “associate_2”{

subnet_id = aws_subnet.privatesub.id

route_table_id = aws_route_table.nicrotab2.id

depends_on = [

aws_subnet.privatesub,

]

}

Step 10: Creating a Security Group which allows port 80 for http and 22 for SSH in inbound rule and allows all port in outbound rule.

resource "aws_security_group" "task4" {

name = "task4"

description = "Allow inbound traffic"

vpc_id = aws_vpc.myvpc.id

ingress {

from_port = 80

to_port = 80

protocol = "tcp"

cidr_blocks = ["0.0.0.0/0"]

}

ingress {

from_port = 22

to_port = 22

protocol = "tcp"

cidr_blocks = ["0.0.0.0/0"]

}

egress {

from_port = 0

to_port = 0

protocol = "-1"

cidr_blocks = ["0.0.0.0/0"]

}

depends_on = [

aws_vpc.myvpc,

] tags = {

Name = "task_4"

}

}

Step 11: Write a terraform code to Launch an ec2 instance which has Wordpress setup.

resource "aws_instance" "wordpressOS" {

ami = "ami-004a955bfb611bf13"

instance_type = "t2.micro"

associate_public_ip_address = true

key_name = "keycloud"

subnet_id = aws_subnet.publicsub.id

vpc_security_group_ids = [ aws_security_group.mywpsg.id ]

tags = {

Name = "wordpressOS"



}

}

Step 12: Creating security group for MySql

resource "aws_security_group" "mysqlsg" {

name = "basic"

description = "Allow TLS inbound traffic"

vpc_id = "aws_vpc.mvpc.id"

ingress {

description = "mysql"

from_port = 3306

to_port = 3306

protocol = "tcp"

cidr_blocks = ["0.0.0.0/0"]

}

depends_on = [

aws_vpc.myvpc,

]

tags = {

Name = "mysqlsg"

} }

Step 13: Write a terraform code to Launch an ec2 instance which has MySql setup.

resource "aws_instance" "mysqlOS" {

ami = "ami-08706cb5f68222d09"

instance_type = "t2.micro"

key_name = "keycloud"

subnet_id = aws_subnet.privatesub.id

vpc_security_group_ids = [ "aws_security_group.mysqlsg.id" ]

tags = {

Name = "mysqlOS"

} }

To use our terraform code first we have to initialize it by using this command:

terraform init

After that run this command and the terraform will perform the task.

terraform apply --auto-approve

After that we can destroy the whole environment.