0% found this document useful (0 votes)
14 views

AWS Project Terraform

The document outlines a scenario for deploying a highly available web application on AWS using Terraform, featuring an Application Load Balancer (ALB), Auto Scaling Group (ASG), and S3 for backup. It details the infrastructure setup, including VPC, subnets, security groups, and IAM roles, along with the configuration of the ALB and ASG. Additionally, it provides instructions for testing the deployment and connecting to the instances via a bastion host.

Uploaded by

Mejdi
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

AWS Project Terraform

The document outlines a scenario for deploying a highly available web application on AWS using Terraform, featuring an Application Load Balancer (ALB), Auto Scaling Group (ASG), and S3 for backup. It details the infrastructure setup, including VPC, subnets, security groups, and IAM roles, along with the configuration of the ALB and ASG. Additionally, it provides instructions for testing the deployment and connecting to the instances via a bastion host.

Uploaded by

Mejdi
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 21

Mohamed Rizk: Mohamed_LinkedIn

Lama almassry : Lama_LinkedIn

Don't forget to subscribe => https://www.youtube.com/@Cloud-Kode

1
Scenario: Deploying a Highly Available Web Application with Auto Scaling and S3 Backup

Objective

To deploy a highly available web application on AWS using Terraform, with an Application Load
Balancer (ALB) distributing traffic across instances in an Auto Scaling Group (ASG). The
deployment includes a bastion host for SSH access, S3 for backup storage, and secure network
configurations using public and private subnets with a NAT gateway for outbound internet
access from private instances.

Infrastructure Setup

1. AWS Provider:

o Configured for the us-east-1 region to deploy the infrastructure.

2. VPC and Subnets:

o A VPC with CIDR block 192.168.0.0/16 is created.

o Four subnets are defined: two for public resources (e.g., ALB, bastion host) and
two for private instances (e.g., ASG instances).

3. Internet Gateway & NAT Gateway:

o An Internet Gateway allows public internet access for the public subnets.

o A NAT Gateway provides outbound internet access to private instances via the
NAT gateway in the public subnet.

4. Security Groups:

o Security group for ALB and instances allows HTTP (port 80) and SSH (port 22)
traffic from the internet.

o A dedicated security group for the bastion host allows SSH access, enabling the
management of private instances through the bastion host.

5. Application Load Balancer (ALB):

o The ALB listens on port 80 and forwards traffic to an Auto Scaling Group (ASG)
through a target group. Health checks are performed on the root path to ensure
instance availability.

2
6. Auto Scaling Group (ASG):

o The ASG dynamically scales between 1 to 3 instances, ensuring high availability.


Each instance hosts a simple Python web server that serves an "Hello, World"
page.

o The ASG is configured to use an EC2 Launch Configuration, which installs


necessary software, including Python.

7. Bastion Host:

o A bastion host (EC2 instance) is deployed in the public subnet to securely SSH
into the private EC2 instances.

o Users upload an SSH key to the bastion host for connecting to private instances.

8. IAM Roles and S3 Integration:

o An IAM role is assigned to the EC2 instances, allowing them to access the S3
bucket.

o Instances can read and write to the Cloudkode-s3 S3 bucket for backups or other
file storage purposes.

9. Private Subnet EC2 Access and Internet Connectivity:

o From the bastion host, SSH access is established to instances in private subnets.

o Private instances can connect to the internet through the NAT Gateway to
download necessary software and updates.

3
The architecture

4
Provider

# Configure the AWS Provider

provider "aws" {

region = "us-east-1"

VPC

# Define VPC

resource "aws_vpc" "main" {

cidr_block = "192.168.0.0/16"

tags = {

Name = "Cloudkode-vpc"

Subnets

# Define Subnets

resource "aws_subnet" "subnet1" {

vpc_id = aws_vpc.main.id

cidr_block = "192.168.1.0/24"

availability_zone = "us-east-1a"

tags = {

Name = "priv_subnet-1"

5
resource "aws_subnet" "subnet2" {

vpc_id = aws_vpc.main.id

cidr_block = "192.168.2.0/24"

availability_zone = "us-east-1b"

tags = {

Name = "priv_subnet-2"

resource "aws_subnet" "subnet3" {

vpc_id = aws_vpc.main.id

cidr_block = "192.168.3.0/24"

availability_zone = "us-east-1a"

tags = {

Name = "pub_subnet-1"

resource "aws_subnet" "subnet4" {

vpc_id = aws_vpc.main.id

cidr_block = "192.168.4.0/24"

availability_zone = "us-east-1b"

tags = {

Name = "pub_subnet-2"

6
Load balancer

# Create Load Balancer (ALB)

resource "aws_lb" "test" {

name = "ALB-rizk"

internal =false

load_balancer_type = "application"

security_groups = [aws_security_group.HTTP-SG.id]

subnets = [aws_subnet.subnet1.id, aws_subnet.subnet2.id]

enable_deletion_protection = false

tags = {

Name = "Cloudkode-rizk" }

# Create Target Group

resource "aws_lb_target_group" "test" {

name = "TG-Cloudkode"

port = 80

protocol = "HTTP"

vpc_id = aws_vpc.main.id

health_check {

protocol = "HTTP"

path = "/"

tags = {

Name = "TG-cloudkode"

}
7
# Create Listener for ALB

resource "aws_lb_listener" "test" {

load_balancer_arn = aws_lb.test.arn

port = "80"

protocol = "HTTP"

default_action {

type = "forward"

target_group_arn = aws_lb_target_group.test.arn

bastion host (jump)

# Create EC2 Instances

resource "aws_instance" "jumper_instance" {

ami = "ami-0182f373e66f89c85 "

instance_type = "t2.micro"

subnet_id = aws_subnet.subnet3.id

vpc_security_group_ids = [aws_security_group.jumper-SG.id]

associate_public_ip_address = true

key_name = "key"

tags = {

Name = "jump server"

8
- Internet gateway

# Create Internet Gateway

resource "aws_internet_gateway" "main" {

vpc_id = aws_vpc.main.id

tags = {

Name = "main-gateway"

- Natgateway

resource "aws_eip" "nat_eip" {

tags = {

Name = "nat-eip"

resource "aws_nat_gateway" "nat_gw" {

allocation_id = aws_eip.nat_eip.id

subnet_id = aws_subnet.subnet3.id

tags = {

Name = "nat-gateway"

9
- Route table

# Create Route Table

resource "aws_route_table" "public_RT" {

vpc_id = aws_vpc.main.id

route {

cidr_block = "0.0.0.0/0"

gateway_id = aws_internet_gateway.main.id

tags = {

Name = "public_RT"

resource "aws_route_table" "private_RT" {

vpc_id = aws_vpc.main.id

tags = {

Name = "private_RT"

# Update Private Route Table to Route Traffic Through NAT Gateway

resource "aws_route" "private_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_gw.id

10
# Associate Subnets with Route Tables

resource "aws_route_table_association" "subnet1_association" {

subnet_id = aws_subnet.subnet1.id

route_table_id = aws_route_table.private_RT.id

resource "aws_route_table_association" "subnet2_association" {

subnet_id = aws_subnet.subnet2.id

route_table_id = aws_route_table.private_RT.id

resource "aws_route_table_association" "subnet3_association" {

subnet_id = aws_subnet.subnet3.id

route_table_id = aws_route_table.public_RT.id

resource "aws_route_table_association" "subnet4_association" {

subnet_id = aws_subnet.subnet4.id

route_table_id = aws_route_table.public_RT.id

S3

# Create S3 Bucket

resource "aws_s3_bucket" "Cloudkode_s3" {

bucket = "cloudkode-s3"

force_destroy = true

tags = {

Name = "CloudkodeS3Bucket"

}}

11
- IAM

# Create IAM Role and Policy

resource "aws_iam_role" "ec2_role" {

name = "ec2_role"

assume_role_policy = jsonencode({

Version = "2012-10-17",

Statement = [

Action = "sts:AssumeRole",

Effect = "Allow",

Principal = {

Service = "ec2.amazonaws.com"

})

resource "aws_iam_policy" "s3_policy" {

name = "s3_policy"

policy = jsonencode({

Version = "2012-10-17",

Statement = [

Action = [

"s3:ListBucket",

"s3:GetObject",
12
"s3:PutObject"

],

Effect = "Allow",

Resource = [

"arn:aws:s3:::cloudkode-s3",

"arn:aws:s3:::cloudkode-s3/*"

})

resource "aws_iam_role_policy_attachment" "ec2_attach" {

role = aws_iam_role.ec2_role.name

policy_arn = aws_iam_policy.s3_policy.arn

# Attach IAM Role to EC2 Instances

resource "aws_iam_instance_profile" "ec2_profile" {

name = "ec2_profile"

role = aws_iam_role.ec2_role.name

13
- Auto Scaling Group

# Create Auto Scaling Group

resource "aws_launch_configuration" "app" {

name = "app-launch-configuration"

image_id = "ami-013efd7d9f40467af"

instance_type = "t2.micro"

key_name = "key"

iam_instance_profile = aws_iam_instance_profile.ec2_profile.name

security_groups = [aws_security_group.HTTP-SG.id]

user_data = <<-EOF

#!/bin/bash

yum update -y

yum install -y python3

echo "Hello, World from ASG , $(hostname -f) " > /home/ec2-user/index.html

cd /home/ec2-user

python3 -m http.server 80 &

EOF

resource "aws_autoscaling_group" "app" {

name = "ASG"

launch_configuration = aws_launch_configuration.app.id

min_size =1

max_size =3

desired_capacity =2

vpc_zone_identifier = [aws_subnet.subnet1.id, aws_subnet.subnet2.id]


14
target_group_arns = [aws_lb_target_group.test.arn]

tag {

key = "Name"

value = "ASG_Instance"

propagate_at_launch = true

- Security groups

# Create Security Group

resource "aws_security_group" "HTTP-SG" {

vpc_id = aws_vpc.main.id

ingress {

from_port = 80

to_port = 80

protocol = "tcp"

cidr_blocks = ["0.0.0.0/0"]

# Add SSH ingress rule

ingress {

from_port = 22

to_port = 22

protocol = "tcp"

cidr_blocks = ["0.0.0.0/0"]

15
}

egress {

from_port = 0

to_port =0

protocol = "-1"

cidr_blocks = ["0.0.0.0/0"]

tags = {

Name = "HTTP-SG"

# Create Security Group

resource "aws_security_group" "jumper-SG" {

vpc_id = aws_vpc.main.id

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"]

tags = {
16
Name = "jumper-SG" }}

Testing

- upload the key to bastion host ⇒ /home/ec2-user

scp -i "C:/Users/HP/OneDrive/Desktop/Test-main/05-ASG-S3/key.pem"
"C:/Users/HP/OneDrive/Desktop/Test-main/05-ASG-S3/key.pem" ec2-
[email protected]:/home/ec2-user/

- connect to the bastion host


ssh -i "key.pem" ec2-user@publicIP_bastion

• from the bastion host connect to ALB

17
• from the bastion host connect SSH to the private instance

• from the private instance connect to the internet (outbound)

18
Output

- EC2 instances

- Load balancer

19
Auto Scaling group

20
- S3

21

You might also like