VPC Creation with Public & Private Subnets, Internet Gateway, and Route Tables

Task Overview

In this task, we will create a Virtual Private Cloud (VPC) in AWS with the following components:

Architecture Diagram

Implementation Steps

Step 1: Create the VPC

  1. Login to AWS Console
  2. Navigate to VPC > Your VPCs > Create VPC
  3. Provide:
  4. Click Create VPC

Step 2: Create Public & Private Subnets

  1. Navigate to VPC > Subnets > Create Subnet
  2. Select MyCustomVPC
  3. Create two public subnets:
  4. Create two private subnets:
  5. Click Create Subnets

Step 3: Create & Attach Internet Gateway (IGW)

  1. Navigate to VPC > Internet Gateways > Create Internet Gateway
  2. Provide:
  3. Click Create
  4. Attach IGW to VPC:

Step 4: Create Route Tables

4.1 Public Route Table

  1. Navigate to VPC > Route Tables > Create Route Table
  2. Provide:
  3. Click Create
  4. Edit Routes:
  5. Associate Public Subnets:

4.2 Private Route Table

  1. Navigate to VPC > Route Tables > Create Route Table
  2. Provide:
  3. Click Create
  4. Associate Private Subnets:

Step 5: Create & Attach Security Groups

  1. Navigate to VPC > Security Groups > Create Security Group
  2. Public SG (for Public EC2 instances):
  3. Private SG (for Private EC2 instances):

Step 6: Create a NAT Gateway for Private Subnets (Optional)

If private instances need internet access, use a NAT Gateway:.

  1. Navigate to VPC > NAT Gateways > Create NAT Gateway
  2. Choose Public Subnet: Public-Subnet-1
  3. Elastic IP: Allocate new EIP
  4. Click Create
  5. Modify Private Route Table:

Step 7: Deploy EC2 Instances for Testing

  1. Navigate to EC2 > Instances > Launch Instance
  2. Public Instance
  3. Private Instance
  4. Test Connectivity:

Final Validation

Automation using Terraform (Optional)

If you want to automate the VPC creation, you can use Terraform to provision this infrastructure.

Terraform Project Structure

terraform-vpc/
│-- main.tf          # Main Terraform configuration
│-- variables.tf     # Variables for customization
│-- outputs.tf       # Outputs for the created resources
│-- provider.tf      # AWS Provider configuration
│-- terraform.tfvars # Variable values

Step 1: Create provider.tf

This file configures the AWS provider.

provider "aws" {
  region = var.aws_region
}

Step 2: Create variables.tf

This file defines the variables.

variable "aws_region" {
  description = "AWS region"
  default     = "us-east-1"
}

variable "vpc_cidr" {
  description = "VPC CIDR block"
  default     = "10.0.0.0/16"
}

variable "public_subnet_cidrs" {
  description = "Public subnet CIDRs"
  type        = list(string)
  default     = ["10.0.1.0/24", "10.0.2.0/24"]
}

variable "private_subnet_cidrs" {
  description = "Private subnet CIDRs"
  type        = list(string)
  default     = ["10.0.3.0/24", "10.0.4.0/24"]
}

Step 3: Create main.tf

This file contains the main Terraform resources.

# Create VPC
resource "aws_vpc" "my_vpc" {
  cidr_block = var.vpc_cidr
  enable_dns_support = true
  enable_dns_hostnames = true

  tags = {
    Name = "MyCustomVPC"
  }
}

# Create Public Subnets
resource "aws_subnet" "public_subnets" {
  count = length(var.public_subnet_cidrs)

  vpc_id                  = aws_vpc.my_vpc.id
  cidr_block              = var.public_subnet_cidrs[count.index]
  map_public_ip_on_launch = true
  availability_zone       = element(["us-east-1a", "us-east-1b"], count.index)

  tags = {
    Name = "Public-Subnet-${count.index + 1}"
  }
}

# Create Private Subnets
resource "aws_subnet" "private_subnets" {
  count = length(var.private_subnet_cidrs)

  vpc_id            = aws_vpc.my_vpc.id
  cidr_block        = var.private_subnet_cidrs[count.index]
  availability_zone = element(["us-east-1a", "us-east-1b"], count.index)

  tags = {
    Name = "Private-Subnet-${count.index + 1}"
  }
}

# Create Internet Gateway
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.my_vpc.id

  tags = {
    Name = "MyInternetGateway"
  }
}

# Create Public Route Table
resource "aws_route_table" "public_rt" {
  vpc_id = aws_vpc.my_vpc.id

  tags = {
    Name = "Public-Route-Table"
  }
}

# Add Route to Internet Gateway in Public Route Table
resource "aws_route" "public_internet_route" {
  route_table_id         = aws_route_table.public_rt.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.igw.id
}

# Associate Public Subnets with Public Route Table
resource "aws_route_table_association" "public_association" {
  count = length(var.public_subnet_cidrs)

  subnet_id      = aws_subnet.public_subnets[count.index].id
  route_table_id = aws_route_table.public_rt.id
}

# Create NAT Gateway (for private subnet internet access)
resource "aws_eip" "nat_eip" {
  domain = "vpc"
}

resource "aws_nat_gateway" "nat" {
  allocation_id = aws_eip.nat_eip.id
  subnet_id     = aws_subnet.public_subnets[0].id

  tags = {
    Name = "MyNATGateway"
  }

  depends_on = [aws_internet_gateway.igw]
}

# Create Private Route Table
resource "aws_route_table" "private_rt" {
  vpc_id = aws_vpc.my_vpc.id

  tags = {
    Name = "Private-Route-Table"
  }
}

# Add Route to NAT Gateway in Private Route Table
resource "aws_route" "private_nat_route" {
  route_table_id         = aws_route_table.private_rt.id
  destination_cidr_block = "0.0.0.0/0"
  nat_gateway_id         = aws_nat_gateway.nat.id
}

# Associate Private Subnets with Private Route Table
resource "aws_route_table_association" "private_association" {
  count = length(var.private_subnet_cidrs)

  subnet_id      = aws_subnet.private_subnets[count.index].id
  route_table_id = aws_route_table.private_rt.id
}

Step 4: Create outputs.tf

This file provides output values.

output "vpc_id" {
  value = aws_vpc.my_vpc.id
}

output "public_subnet_ids" {
  value = aws_subnet.public_subnets[*].id
}

output "private_subnet_ids" {
  value = aws_subnet.private_subnets[*].id
}

output "internet_gateway_id" {
  value = aws_internet_gateway.igw.id
}

output "nat_gateway_id" {
  value = aws_nat_gateway.nat.id
}

Step 5: Create terraform.tfvars

Define variable values (optional).

aws_region = "us-east-1"
vpc_cidr = "10.0.0.0/16"
public_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24"]
private_subnet_cidrs = ["10.0.3.0/24", "10.0.4.0/24"]

Deployment Steps

Run the following commands to deploy the infrastructure:

# Initialize Terraform
terraform init

# Preview the changes
terraform plan

# Apply the configuration
terraform apply -auto-approve

Step 6: Destroy the Resources (If Needed)

If you want to remove the infrastructure:

terraform destroy -auto-approve

Validation & Testing

  1. Go to AWS Console > VPC
  2. Launch EC2 Instances

Conclusion