Deploying High-Availability AWS Infrastructure using Terraform and Jenkins
In today's fast-paced digital environment, ensuring high availability and fault tolerance in cloud infrastructure is crucial for maintaining seamless user experiences. I'm excited to share my recent project where I implemented a high-availability infrastructure on AWS using Terraform and Jenkins. This project highlights the setup of essential AWS components like Auto Scaling Groups (ASG), Elastic Load Balancers (ELB), and more, all orchestrated through Terraform's robust infrastructure-as-code capabilities, complemented by Jenkins for continuous integration and continuous deployment (CI/CD)
Project Overview
The goal of this project was to create a resilient and highly available AWS infrastructure. By utilizing Terraform, I automated the deployment and management of several AWS resources, ensuring that they are scalable, secure, and efficient. Additionally, Jenkins was used for automating the CI/CD pipeline, enabling seamless integration and deployment of changes.
Key Features
Prerequisites
#Install terraform with below steps on ubuntu
sudo apt-get update && sudo apt-get install -y gnupg software-properties-common
wget -O- https://apt.releases.hashicorp.com/gpg | \
gpg --dearmor | \
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg > /dev/null
gpg --no-default-keyring \
--keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg \
--fingerprint
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update
sudo apt-get install terraform
Install AWS cli using below commands
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
2. Jenkins Setup:
Install Java before installing jenkins
sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc]" \
https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null
sudo apt-get update
sudo apt-get install jenkins
3. Create IAM users with required permissions
4. Configure AWS CLI using access and secret keys
aws configure
AWS Access Key ID [None]: YOUR_ACCESS_KEY_ID
AWS Secret Access Key [None]: YOUR_SECRET_ACCESS_KEY
Default region name [None]: us-east-1
Default output format [None]: json
Terraform Configuration
The Terraform configuration files with(*.tf) in this repository define the AWS resources and settings required to create the high availability infrastructure.
Providers.tf
provider "aws" {
region = "us-east-1"
}
It configures the AWS provider to manage resources in the "us-east-1" region. The provider block specifies the cloud service provider, in this case, AWS, and sets the region where Terraform will execute its operations and manage resources.
vpc.tf
resource "aws_vpc" "vpc" {
cidr_block = var.vpc-cidr-block
tags = {
Name = var.vpc-name
}
}
It creates an AWS Virtual Private Cloud (VPC) with a CIDR block defined by the variable var.vpc-cidr-block. It tags the VPC with a name specified by var.vpc-name, allowing for flexible configuration of the network range and easy identification through tagging
subnets.tf
resource "aws_subnet" "web-subnet1" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.web-subnet1-cidr
availability_zone = var.az-1
tags = {
Name = var.web-subnet1-name
}
}
resource "aws_subnet" "web-subnet2" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.web-subnet2-cidr
availability_zone = var.az-2
tags = {
Name = var.web-subnet2-name
}
}
It sets up two AWS subnets within a specified VPC. Each subnet is assigned a CIDR block to define its IP address range and is placed in a distinct availability zone to enhance redundancy and availability.
route-table.tf
resource "aws_route_table" "public-route-table" {
vpc_id = aws_vpc.vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.internet-gw.id
}
}
resource "aws_route_table_association" "pub-rt-asscociation-1" {
subnet_id = aws_subnet.web-subnet1.id
route_table_id = aws_route_table.public-route-table.id
}
resource "aws_route_table_association" "pub-rt-asscociation-2" {
subnet_id = aws_subnet.web-subnet2.id
route_table_id = aws_route_table.public-route-table.id
}
internet-gw.tf
resource "aws_internet_gateway" "internet-gw" {
vpc_id = aws_vpc.vpc.id
tags = {
Name = var.igw-name
}
}
It creates an AWS Internet Gateway and attaches it to a specified VPC identified by aws_vpc.vpc.id. The Internet Gateway enables the VPC to communicate with the public internet, allowing resources within the VPC to send and receive traffic.
load-balancer.tf
resource "aws_lb" "alb" {
name = var.alb-name
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb_security_group.id]
subnets = [aws_subnet.web-subnet1.id, aws_subnet.web-subnet2.id]
}
It creates an AWS Application Load Balancer (ALB) that is internet-facing, allowing it to route external traffic to resources. It operates at the application layer, is associated with a specified security group for traffic control, and is deployed across multiple subnets to ensure high availability.
target-group.tf
resource "aws_lb_target_group" "target-group" {
name = "tg-1"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.vpc.id
health_check {
path = "/"
port = 80
protocol = "HTTP"
matcher = 200
}
}
resource "aws_lb_listener" "alb_listener" {
load_balancer_arn = aws_lb.alb.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.target-group.arn
}
}
load-balancer-sg.tf
resource "aws_security_group" "alb_security_group" {
name = "alb_security_group"
description = "Allow inbound traffic and all outbound traffic"
vpc_id = aws_vpc.vpc.id
tags = {
Name = "alb_security_group"
}
}
resource "aws_vpc_security_group_ingress_rule" "alb_ingress_rule" {
security_group_id = aws_security_group.alb_security_group.id
cidr_ipv4 = "0.0.0.0/0"
from_port = 80
ip_protocol = "tcp"
to_port = 80
}
resource "aws_vpc_security_group_egress_rule" "alb_egress_rule" {
security_group_id = aws_security_group.alb_security_group.id
cidr_ipv4 = "0.0.0.0/0"
ip_protocol = "-1" # semantically equivalent to all ports
}
asg.tf
resource "aws_launch_template" "launch_template" {
name_prefix = "web-launchtemplate"
image_id = "ami-0e2c8caa4b6378d8c"
instance_type = "t2.micro"
key_name = "ansible-key-pair"
network_interfaces {
associate_public_ip_address = true
security_groups = [aws_security_group.alb_security_group.id]
}
tag_specifications {
resource_type = "instance"
tags = {
Name = "test"
}
}
user_data = filebase64("user-data.sh")
}
resource "aws_autoscaling_group" "asg" {
name = "asg-high-avail"
target_group_arns = [aws_lb_target_group.target-group.arn]
desired_capacity = 2
max_size = 3
min_size = 1
vpc_zone_identifier = [aws_subnet.web-subnet1.id, aws_subnet.web-subnet2.id]
launch_template {
id = aws_launch_template.launch_template.id
version = aws_launch_template.launch_template.latest_version
}
}
user-data.sh
#!/bin/bash
# Use this for your user data (script from top to bottom)
# Install Apache (Ubuntu 24.04 version)
apt update -y
apt install -y apache2
systemctl start apache2
systemctl enable apache2
echo "<h1>Hello World from $(hostname -f). changing file </h1>" > /var/www/html/index.html
This script installs and enables appache2 server in EC2 instances
variables.tf
variable "vpc-cidr-block" {
description = "CIDR Block for VPC"
}
variable "vpc-name" {
description = "Name for Virtual Private Cloud"
}
variable "igw-name" {
description = "Name for Internet Gateway"
}
variable "web-subnet1-cidr" {
description = "CIDR Block for Web-tier Subnet-1"
}
variable "web-subnet1-name" {
description = "Name for Web-tier Subnet-1"
}
variable "web-subnet2-cidr" {
description = "CIDR Block for Web-tier Subnet-2"
}
variable "web-subnet2-name" {
description = "Name for Web-tier Subnet-2"
}
variable "az-1" {
description = "Availabity Zone 1"
}
variable "az-2" {
description = "Availabity Zone 2"
}
variable "alb-name" {
description = "load balancer name"
}
This file contains all variable declarations
terraform.tfvars
vpc-cidr-block = "10.0.0.0/16"
vpc-name = "vpc-high-avail"
igw-name = "igw-high-avail"
web-subnet1-cidr = "10.0.1.0/24"
web-subnet1-name = "web-subnet-1"
web-subnet2-cidr = "10.0.2.0/24"
web-subnet2-name = "web-subnet-2"
az-1 = "us-east-1a"
az-2 = "us-east-1b"
alb-name = "alb-high-avail"
This file contains variable definitions
Application
terraform init
terraform plan
terraform apply
YAY!! High-availability one tier AWS architechture is deployed successfully
Copy the load balancer's dns to the browser and check how load balancer works
Jenkins Integration
Utilize Jenkins for continuous integration and deployment by following these steps:
This project not only showcases the power of AWS and Terraform in building scalable and reliable cloud infrastructure but also demonstrates the effectiveness of Jenkins in automating CI/CD processes.
Github Link: https://github.com/purnashanmugam/High_availability_AWS_architechture_using_terraform.git