Set Up a Multi Tier Web Application(Java) on AWS

Set Up a Multi Tier Web Application(Java) on AWS

In this project, we are going to host and run our java application on AWS using a multi tier web application stack.

For this project we’ll be making use of the following services

EC2 instances: VMs for Tomcat, RabbitMQ, Memcache and MySQL servers.

ELB (Elastic Load Balancer): to automatically distribute incoming traffic across multiple backend servers.

S3 : to store software artifact.

Route53: for private DNS service.

Other services include Security groups, EBS volumes, Public DNS (e.g. Godaddy) etc.

Project Summary

Users will access our web application by using a domain name bought from public dns provider. The domain name URL will point to the ELB endpoint.

Users browsers will use this endpoint to connect to the load balancer by using HTTP on port 80. The ELB will be in a security group that only allows HTTP traffic on port 80.

The application load balancer will then route the request to Tomcat servers (EC2) running in a security group that accepts connection only from the load balancer on port 8080.

The backend servers (MySQL, Memcache and RabbitMQ) for our application will sit in a separate security group and they will be reachable through Route private DNS Zone entries.

Project Architecture

Project Implementation

Step 1: Create Security Groups and Key Pairs

We’ll create 3 security groups. One for the Application load balancer, one for the application server (tomcat instance), one for the backend services (memcache, rabbitmq and mysql instances)

load balancer security group

tomcat application security group

Tomcat security group

backend servers security group

Next we’ll create a login key pair for our instances

Step 2: Create four servers (EC2 Instances)

We’ll create for EC2 instances for Tomcat, Memcache, RabbitMQ and MySQL servers and place them in their appropriate security groups. We’ll provision the instances and setup the services by using user data scripts.

Create mysql server in the backend servers security group with user data and the created key pair

user data to launch mysql database during instance creation

#!/bin/bash
DATABASE_PASS='admin123'
sudo dnf update -y
sudo dnf install git zip unzip -y
sudo dnf install mariadb105-server -y
# starting & enabling mariadb-server
sudo systemctl start mariadb
sudo systemctl enable mariadb
cd /tmp/
git clone -b main https://github.com/hkhcoder/vprofile-project.git
#restore the dump file for the application
sudo mysqladmin -u root password "$DATABASE_PASS"
sudo mysql -u root -p"$DATABASE_PASS" -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$DATABASE_PASS'"
sudo mysql -u root -p"$DATABASE_PASS" -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1')"
sudo mysql -u root -p"$DATABASE_PASS" -e "DELETE FROM mysql.user WHERE User=''"
sudo mysql -u root -p"$DATABASE_PASS" -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%'"
sudo mysql -u root -p"$DATABASE_PASS" -e "FLUSH PRIVILEGES"
sudo mysql -u root -p"$DATABASE_PASS" -e "create database accounts"
sudo mysql -u root -p"$DATABASE_PASS" -e "grant all privileges on accounts.* TO 'admin'@'localhost' identified by 'admin123'"
sudo mysql -u root -p"$DATABASE_PASS" -e "grant all privileges on accounts.* TO 'admin'@'%' identified by 'admin123'"
sudo mysql -u root -p"$DATABASE_PASS" accounts < /tmp/vprofile-project/src/main/resources/db_backup.sql
sudo mysql -u root -p"$DATABASE_PASS" -e "FLUSH PRIVILEGES"

confirm the required database services are running on db01 server

Create memcache server in the backend servers security group with user data and the created key pair

user data to launch memcache service during instance creation

#!/bin/bash
sudo dnf install memcached -y
sudo systemctl start memcached
sudo systemctl enable memcached
sudo systemctl status memcached
sed -i 's/127.0.0.1/0.0.0.0/g' /etc/sysconfig/memcached
sudo systemctl restart memcached
sudo memcached -p 11211 -U 11111 -u memcached -d

confirm memcache service is running

Create rabbitmq server in the backend servers security group with user data and the created key pair

user data to launch rabbitmq service during instance creation

#!/bin/bash
## primary RabbitMQ signing key
rpm --import 'https://github.com/rabbitmq/signing-keys/releases/download/3.0/rabbitmq-release-signing-key.asc'
## modern Erlang repository
rpm --import 'https://github.com/rabbitmq/signing-keys/releases/download/3.0/cloudsmith.rabbitmq-erlang.E495BB49CC4BBE5B.key'
## RabbitMQ server repository
rpm --import 'https://github.com/rabbitmq/signing-keys/releases/download/3.0/cloudsmith.rabbitmq-server.9F4587F226208342.key'
curl -o /etc/yum.repos.d/rabbitmq.repo https://raw.githubusercontent.com/hkhcoder/vprofile-project/aws-LiftAndShift/al2023rmq.repo
dnf update -y
## install these dependencies from standard OS repositories
dnf install socat logrotate -y
## install RabbitMQ and zero dependency Erlang
dnf install -y erlang rabbitmq-server
systemctl enable rabbitmq-server
systemctl start rabbitmq-server
sudo sh -c 'echo "[{rabbit, [{loopback_users, []}]}]." > /etc/rabbitmq/rabbitmq.config'
sudo rabbitmqctl add_user test test
sudo rabbitmqctl set_user_tags test administrator
rabbitmqctl set_permissions -p / test ".*" ".*" ".*"

sudo systemctl restart rabbitmq-server

confirm rabbitmq service is running

Create tomcat server in the tomcat servers security group with user data and the created key pair

user data to launch tomcat service during instance creation

#!/bin/bash
sudo apt update
sudo apt upgrade -y
sudo apt install openjdk-17-jdk -y
sudo apt install tomcat10 tomcat10-admin tomcat10-docs tomcat10-common git -y

confirm status of tomcat service

successfully created the four servers

Step 3: Setup private DNS (Route 53)

We’ll create a private DNS service to resolve internally the server names to IPs so we can conveniently give the names in the application configuration file.

Create hosted zone

Create records in the created hosted zone

create A record type for each of the servers using their private ip addresses

Confirm DNS resolution works

Step 4: Build and Deploy Artifact

In this step, we are going to build the artifact from the source code on our computer using maven then we are going to push it to S3 bucket. On the tomcat instance (app01), we are going to fetch the artifact from S3 and deploy it on the tomcat server

Create S3 bucket

Create IAM access keys for S3

IAM access keys are needed to interact with Amazon S3 via the AWS CLI. The CLI requires the access keys to authenticate and authorise our actions in AWS.

Generate the access keys by creating an s3-admin user, attach s3 full access policy to the user and generate access keys

Create IAM role

Create an s3-admin IAM role and apply it to the tomcat server to allow our tomcat server pull artifact from S3

apply the role to the tomcat server (app01)

Build the artifact

First we need to make sure the backend services information in the source code is correct by editing the application.properties file to match the route 53 records.

Build the application by running “mvn install”

Push the artifact from our CLI to S3

Confirm the artifact (build) has been pushed to S3

Login to tomcat server (app01) and fetch the artifact from S3 to /tmp directory on the tomcat server

Deploy the artifact

Step 5: Setup Load Balancer and DNS

Create a target group

Create the Load Balancer

Add Load balancer URL to our DNS record

Step 6: Validate the deployment

Voila! QED!