AWS Project Terraform
AWS Project Terraform
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 Four subnets are defined: two for public resources (e.g., ALB, bastion host) and
two for private instances (e.g., ASG instances).
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.
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):
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.
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.
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
provider "aws" {
region = "us-east-1"
VPC
# Define VPC
cidr_block = "192.168.0.0/16"
tags = {
Name = "Cloudkode-vpc"
Subnets
# Define Subnets
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"
vpc_id = aws_vpc.main.id
cidr_block = "192.168.3.0/24"
availability_zone = "us-east-1a"
tags = {
Name = "pub_subnet-1"
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
name = "ALB-rizk"
internal =false
load_balancer_type = "application"
security_groups = [aws_security_group.HTTP-SG.id]
enable_deletion_protection = false
tags = {
Name = "Cloudkode-rizk" }
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
load_balancer_arn = aws_lb.test.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.test.arn
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 = {
8
- Internet gateway
vpc_id = aws_vpc.main.id
tags = {
Name = "main-gateway"
- Natgateway
tags = {
Name = "nat-eip"
allocation_id = aws_eip.nat_eip.id
subnet_id = aws_subnet.subnet3.id
tags = {
Name = "nat-gateway"
9
- Route table
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"
vpc_id = aws_vpc.main.id
tags = {
Name = "private_RT"
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
subnet_id = aws_subnet.subnet1.id
route_table_id = aws_route_table.private_RT.id
subnet_id = aws_subnet.subnet2.id
route_table_id = aws_route_table.private_RT.id
subnet_id = aws_subnet.subnet3.id
route_table_id = aws_route_table.public_RT.id
subnet_id = aws_subnet.subnet4.id
route_table_id = aws_route_table.public_RT.id
S3
# Create S3 Bucket
bucket = "cloudkode-s3"
force_destroy = true
tags = {
Name = "CloudkodeS3Bucket"
}}
11
- IAM
name = "ec2_role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
Action = "sts:AssumeRole",
Effect = "Allow",
Principal = {
Service = "ec2.amazonaws.com"
})
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/*"
})
role = aws_iam_role.ec2_role.name
policy_arn = aws_iam_policy.s3_policy.arn
name = "ec2_profile"
role = aws_iam_role.ec2_role.name
13
- Auto Scaling Group
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
echo "Hello, World from ASG , $(hostname -f) " > /home/ec2-user/index.html
cd /home/ec2-user
EOF
name = "ASG"
launch_configuration = aws_launch_configuration.app.id
min_size =1
max_size =3
desired_capacity =2
tag {
key = "Name"
value = "ASG_Instance"
propagate_at_launch = true
- Security groups
vpc_id = aws_vpc.main.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"]
15
}
egress {
from_port = 0
to_port =0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
tags = {
Name = "HTTP-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
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/
17
• from the bastion host connect SSH to the private instance
18
Output
- EC2 instances
- Load balancer
19
Auto Scaling group
20
- S3
21