Deploying AWS Infrastructure with Terraform: EC2, RDS, S3 and more (Part 1 of 2)


Introduction

Terraform is an infrastructure as a code tool that lets you define both cloud and on-prem resources in human-readable configuration files that you can version, reuse, and share. Terraform's benefits include:

  • Infrastructure as Code: Manage infrastructure with configuration files that can be versioned and treated as code.

  • Consistency: Ensure consistent environments by automating the provisioning process.

  • Scalability: Easily scale infrastructure up or down based on demand.

  • Provider Agnostic: Supports multiple cloud providers and services, enabling a unified workflow.

  • Collaboration: Facilitate collaboration among teams with shared configurations and state management.

know more here

AWS Services Overview

In this guide, we will be deploying the following AWS services using Terraform:

  • VPC (Virtual Private Cloud): A logically isolated network that you define in the AWS cloud.

  • EC2 (Elastic Compute Cloud): Scalable virtual servers in the cloud.

  • RDS (Relational Database Service): Managed relational database service with support for various database engines.

  • S3 (Simple Storage Service): Scalable object storage service for a wide range of use cases.

Each of these services will be configured and managed using Terraform to demonstrate the power and flexibility of infrastructure as code.

Prerequisites

Before getting started, you will need the following:

  1. An AWS account with appropriate permissions to create resources.

  2. Terraform is installed on your local machine.

  3. Basic knowledge of AWS services and Terraform concepts.

  4. A text editor for writing Terraform configuration files.

Setting Up Terraform

To begin, create a new directory for your Terraform configuration files. Inside this directory, create a new file named providers.tf with the following content:

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

provider "aws" {
  region                   = "ap-south-1"
  profile                  = "default"
  shared_credentials_files = ["~/.aws/credentials"]
}

This file defines the AWS provider and specifies the region (in this case, ap-south-1) and the AWS profile to use for authentication. Make sure to replace the region and profile values with your own. Save the file and run terraform init to initialize the provider.

Creating a VPC and other necessary resources

Next, create a new file named main.tf in the same directory with the following content:

VPC

A Virtual Private Cloud (VPC) is a logically isolated section of the AWS cloud where you can launch resources in a virtual network. Key features include:

  1. Isolation: Ensures your resources are secure from other virtual networks.

  2. Subnets: Divide your VPC into public or private segments.

  3. Security: Use security groups and network ACLs to control traffic.

  4. Customizable Network Configuration: Configure route tables, gateways, and VPN connections.

  5. Scalability: Scale to accommodate application growth.

# VPC
resource "aws_vpc" "server_vpc" {
  cidr_block         = "10.0.0.0/24"
  instance_tenancy   = "default"
  enable_dns_support = true

  tags = {
    Name = "server-vpc"
  }
}

This code block defines a new VPC with the CIDR block 10.0.0.0/24 (256 IP addresses) and enables DNS support.

Subnets

Subnets divide a VPC into smaller sections for better management. Key purposes include:

  1. Isolation and Security: Separate public-facing and private resources.

  2. Efficient IP Management: Allocate IP addresses more effectively.

  3. Network Performance: Reduce broadcast traffic.

  4. Routing Control: Customize route tables for precise traffic control.

  5. Availability Zones: Distribute resources across zones for high availability.

# Subnet
resource "aws_subnet" "server_public_subnet" {
  vpc_id                  = aws_vpc.server_vpc.id
  cidr_block              = "10.0.0.0/24"
  availability_zone       = "ap-south-1a"
  map_public_ip_on_launch = true


  tags = {
    Name = "server-public-subnet"
  }
}

This code block creates a public subnet within the VPC with the CIDR block 10.0.0.0/24 (256 IP addresses) in the ap-south-1a availability zone.

Security Group & Rules

Security groups act as virtual firewalls for your instances, controlling inbound and outbound traffic. Key features include:

  1. Stateful Filtering: Automatically allows return traffic for outbound connections.

  2. Dynamic Updates: Apply changes to security groups in real time.

  3. Rule Prioritization: Rules are evaluated in order, allowing for granular control.

  4. Instance-Level Security: Associate security groups with individual instances.

# Security Group & Rules
resource "aws_security_group" "server_sg" {
  vpc_id      = aws_vpc.server_vpc.id
  name        = "server-sg"
  depends_on  = [aws_vpc.server_vpc]
  description = "Allow inbound traffic on port 80, 22 and 443"
}

resource "aws_vpc_security_group_ingress_rule" "http_inbound" {
  security_group_id = aws_security_group.server_sg.id
  description       = "Allow inbound traffic on port 80 (HTTP) from anywhere"

  cidr_ipv4   = "0.0.0.0/0"
  from_port   = 80
  ip_protocol = "tcp"
  to_port     = 80
}

resource "aws_vpc_security_group_ingress_rule" "https_inbound" {
  security_group_id = aws_security_group.server_sg.id
  description       = "Allow inbound traffic on port 443 (HTTPS) from anywhere"

  cidr_ipv4   = "0.0.0.0/0"
  from_port   = 443
  ip_protocol = "tcp"
  to_port     = 443
}

resource "aws_vpc_security_group_ingress_rule" "ssh_inbound" {
  security_group_id = aws_security_group.server_sg.id
  description       = "Allow inbound traffic on port 22 (SSH) from anywhere"

  cidr_ipv4   = "0.0.0.0/0"
  from_port   = 22
  ip_protocol = "tcp"
  to_port     = 22
}

resource "aws_vpc_security_group_egress_rule" "all_outbound" {
  security_group_id = aws_security_group.server_sg.id
  description       = "Allow all outbound traffic from the instance"

  cidr_ipv4   = "0.0.0.0/0"
  ip_protocol = "-1"
}

This code block creates a security group named server-sg with inbound rules allowing traffic on TCP ports: 80, 22, and 443 from anywhere and an outbound rule allowing all traffic means we can access the EC2 instance in it using HTTP, HTTPS, and SSH, and the instance can access the internet.

Internet Gateway

An Internet Gateway (IGW) is a horizontally scaled, redundant, and highly available VPC component that allows communication between instances in your VPC and the Internet. It serves two main purposes:

  1. Outbound Traffic: It allows instances in your VPC to initiate outbound connections to the internet.

  2. Inbound Traffic: It allows inbound connections from the internet to reach instances in your VPC, provided the instances have public IP addresses and the appropriate security group and network ACL rules are in place.

An Internet Gateway is attached to your VPC and is required for any instances that need to communicate with the Internet.

resource "aws_internet_gateway" "server_igw" {
  vpc_id = aws_vpc.server_vpc.id

  tags = {
    Name = "server-igw"
  }
}

This code block creates an Internet Gateway and attaches it to the VPC. The Internet Gateway allows instances in the VPC to communicate with the Internet.

Route Table

A Route Table contains a set of rules, called routes, that are used to determine where network traffic is directed. Each subnet in your VPC must be associated with a route table, which controls the routing for the subnet. Key features include:

  1. Default Route: A route that directs traffic to the internet gateway for outbound traffic.

  2. Custom Routes: Additional routes for specific destinations or services.

  3. Route Prioritization: Routes are evaluated in order of priority.

  4. Route Table Association: Associate subnets with route tables for routing control.

resource "aws_route_table" "server_route_table" {
  vpc_id     = aws_vpc.server_vpc.id
  depends_on = [aws_internet_gateway.server_igw]

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.server_igw.id
  }

  tags = {
    Name = "server-route-table"
  }
}

resource "aws_route_table_association" "server_subnet_association" {
  subnet_id      = aws_subnet.server_public_subnet.id
  route_table_id = aws_route_table.server_route_table.id
}

This code block creates a route table with a default route that directs traffic to the Internet Gateway. It then associates the route table with the public subnet created earlier.

To be continued...

Upcoming in Part 2:

  • Launching EC2 Instances

  • Creating an RDS Instance

  • Setting up an S3 Bucket