In this runbook, we will implement the PHP Mailing deployment with multi-tier architecture on AWS. We will be using the Amazon EC2 service on AWS for Webservers and Appservers. For the Mysql database, we will use the RDS service. We'll also see how to connect the Webserver to the Appservers and the Appservers with the Database to achieve a multi-tier application architecture deployment.
- Name:
Prod-VPC
- CidirBlock:
10.0.0.0/16
- NAT/ALB Subnet 1
- Name:
Prod-NAT-ALB-Subnet-1
- CidirBlock:
10.0.5.0/28
- Availability Zone:
us-west-1a
- NAT/ALB Subnet 2
- Name:
Prod-NAT-ALB-Subnet-2
- CidirBlock:
10.0.10.0/28
- Availability Zone:
us-west-1c
- Webserver Subnet 1
- Name:
Prod-Webserver-Subnet-1
- CidirBlock:
10.0.15.0
- Availability Zone:
us-west-1a
- Webserver Subnet 2
- Name:
Prod-Webserver-Subnet-2
- CidirBlock:
10.0.20.0
- Availability Zone:
us-west-1c
- Appserver Subnet 1
- Name:
Prod-Appserver-Subnet-1
- CidirBlock:
10.0.25.0
- Availability Zone:
us-west-1a
- Appserver Subnet 2
- Name:
Prod-Appserver-Subnet-2
- CidirBlock:
10.0.30.0
- Availability Zone:
us-west-1c
- Database Subnet 1
- Name:
Prod-db-Subnet-1
- CidirBlock:
10.0.35.0
- Availability Zone:
us-west-1a
- Database Subnet 2
- Name:
Prod-db-Subnet-2
- CidirBlock:
10.0.40.0
- Availability Zone:
us-west-1c
STEP 2: Create 4 Public Route Rable and 4 Private Route Tables (Because of NAT Redundancy Implementation)
- See AWS Doc: https://www.shorturl.at/HSU18
- Name:
Prod-NAT-ALB-Public-RT-1
- VPC: Select the
Prod-VPC
- Name:
Prod-NAT-ALB-Public-RT-2
- VPC: Select the
Prod-VPC
- Name:
Prod-Webserver-RT-1
- VPC: Select the
Prod-VPC
- Name:
Prod-Webserver-RT-2
- VPC: Select the
Prod-VPC
- Name:
Prod-Appserver-RT-1
- VPC: Select the
Prod-VPC
- Name:
Prod-Appserver-RT-2
- VPC: Select the
Prod-VPC
- Name:
Prod-Database-RT-1
- VPC: Select the
Prod-VPC
- Name:
Prod-Database-RT-2
- VPC: Select the
Prod-VPC
- Associate
Prod-NAT-ALB-Public-RT-1
withProd-NAT-ALB-Subnet-1
- Associate
Prod-NAT-ALB-Public-RT-2
withProd-NAT-ALB-Subnet-2
- Associate
Prod-Webserver-RT-1
withProd-Webserver-Subnet-1
- Associate
Prod-Webserver-RT-2
withProd-Webserver-Subnet-2
- Associate
Prod-Appserver-RT-1
withProd-Appserver-Subnet-1
- Associate
Prod-Appserver-RT-2
withProd-Appserver-Subnet-2
- Associate
Prod-Database-RT-1
withProd-db-Subnet-1
- Associate
Prod-Database-RT-2
withProd-db-Subnet-2
- Create the Internet Gatway
- Name:
Prod-VPC-IGW
- VPC: Select the
Prod-VPC
Network
- Configure/Edit the
Prod-NAT-ALB-Public-RT-1
Route Table
- Destination:
0.0.0.0/0
- Target: Select the
Prod-VPC-IGW
SAVE
- Configure/Edit the
Prod-NAT-ALB-Public-RT-2
Route Table
- Destination:
0.0.0.0/0
- Target: Select the
Prod-VPC-IGW
SAVE
- Configure/Edit the
Prod-Webserver-RT-1
Route Table
- Destination:
0.0.0.0/0
- Target: Select the
Prod-VPC-IGW
SAVE
- Configure/Edit the
Prod-Webserver-RT-2
Route Table
- Destination:
0.0.0.0/0
- Target: Select the
Prod-VPC-IGW
SAVE
- Create the
First NAT Gateway
- Name:
Prod-NAT-Gateway-1
- Subnet: Select
Prod-NAT-ALB-Subnet-1
- Elastic IP: Clcik
Allocate Elastic IP
- Click
Create NAT gateway
- Create the
Second NAT Gateway
- Name:
Prod-NAT-Gateway-2
- Subnet: Select
Prod-NAT-ALB-Subnet-2
- Elastic IP: Clcik
Allocate Elastic IP
- Click
Create NAT gateway
C) Configure/Edit the Route Tables of Appserver subnets
and Database subnets
to Add the Nat gateway
Configs
- Select the
Prod-Appserver-RT-1
- Click on Edit and
Add route
- Destination:
0.0.0.0/0
- Target: Select
Prod-NAT-Gateway-1
- Select the
Prod-Appserver-RT-2
- Click on Edit and
Add route
- Destination:
0.0.0.0/0
- Target: Select
Prod-NAT-Gateway-2
- Select the
Prod-Database-RT-1
- Click on Edit and
Add route
- Destination:
0.0.0.0/0
- Target: Select
Prod-NAT-Gateway-1
- Select the
Prod-Database-RT-2
- Click on Edit and
Add route
- Destination:
0.0.0.0/0
- Target: Select
Prod-NAT-Gateway-2
- Click on Create Security group
- Name:
Bastion-Host-Security-Group
- Inbound:
- Ports:
22
- Source: Provide
Your IP or 0.0.0.0/0
- Ports:
- Name:
- Navigate to
Security groups
- Click on Create Security group
-
Name:
Frontend-LB-Security-Group
-
Inbound:
- Ports:
80 and 443
- Source:
0.0.0.0/0
- Ports:
-
Click
Create Security Group
-
- Click on Create Security group
- Name:
Webservers-Security-Group
- Inbound:
- Ports:
80 and 443
- Source: Provide the
Frontend-LB-Security-Group
ID
- Source: Provide the
- Ports:
22
- Source:
Bastion-Host-Security-Group
ID
- Source:
- Ports:
- Name:
- Click on Create Security group
- Name:
Backend-LB-Security-Group
- Inbound:
- Ports:
80 and 443
- Source: Provide the
Webservers-Security-Group
ID
- Ports:
- Name:
- Click on Create Security group
- Name:
Appservers-Security-Group
- Inbound:
- Ports:
80 and 443
- Source: Provide the
Backend-LB-Security-Group
ID
- Source: Provide the
- Ports:
22
- Source:
Bastion-Host-Security-Group
ID
- Source:
- Ports:
- Name:
- Click on Create Security group
- Name:
Database-Security-Group
- Inbound:
- Ports:
3306
- Source: Provide the
Appservers-Security-Group
ID
- Source: Provide the
- Ports:
3306
- Source:
Bastion-Host-Security-Group
ID
- Source:
- Ports:
- Name:
-
Listeners and routing:
- Click on
Create a target group
to createHTTP
target group- target type: select
instances
- Target group name:
Frontend-LB-HTTP-TG
- Protocol and Port:
HTTP
:80
- VPC: Select
Prod-VPC
- Protocol version:
HTTP1
- Health checks:
HTTP
- Health check path:
/VenturaMailingApp.php
- Click on
Next
- Click on
Create target group
- target type: select
- Click on
-
Navigate to
EC2/Load Balancers
and Click onCreate Load Balancer
-
Type: Choose
Application Load Balancer
-
Load balancer name:
Prod-Frontend-LB
-
Scheme:
Internet-facing
-
IP address type:
IPv4
-
Network mapping:
- VPC: Select
Prod-VPC
- Mappings: Select the
Prod-NAT-ALB-Subnet-1
andProd-NAT-ALB-Subnet-2
frontend subnets
- VPC: Select
-
Security groups: Select the
Frontend-LB-Security-Group
-
Listeners and routing:
- Protocol:
HTTP
- Listener
HTTP:80
- Select the
Frontend-LB-HTTP-TG
- Protocol:
-
Click on
Create load balancer
-
-
Listeners and routing:
- Click on
Create a target group
to createHTTP
target group- target type: select
instances
- Target group name:
Backend-LB-HTTP-TG
- Protocol and Port:
HTTP
:80
- VPC: Select
Prod-VPC
- Protocol version:
HTTP1
- Health checks:
HTTP
- Health check path:
/VenturaMailingApp.php
- Click on
Next
- Click on
Create target group
- target type: select
- Click on
-
Navigate to
EC2/Load Balancers
and Click onCreate Load Balancer
-
Type: Choose
Application Load Balancer
-
Load balancer name:
Prod-Backend-LB
-
Scheme:
Internet-facing
-
IP address type:
IPv4
-
Network mapping:
- VPC: Select
Prod-VPC
- Mappings: Select the
Prod-Webserver-Subnet-1
andProd-Webserver-Subnet-2
Webserver/Provate subnets
- VPC: Select
-
Security groups: Select the
Backend-LB-Security-Group
-
Listeners and routing:
- Protocol:
HTTP
- Listener
HTTP:80
- Select the
Backend-LB-HTTP-TG
- Protocol:
-
Click on
Create load balancer
-
- Navigate to the
RDS
Service - Click on
Subnet groups
- Click
Create DB Subnet Group
- Name:
prod-db-subnet-group
- VPC: Select
Prod-VPC
- Availability Zones: Select the two zones you used for this project. Example
us-west-1a
andus-west-1c
- Subnets: Select
Prod-db-Subnet-1
andProd-db-Subnet-2
- Click on
CREATE
- Click
- Navigate to the
RDS
Service - Click on
Databases
andCreate Database
-
Choose a database creation method: Select
Standard create
-
Engine type:
MySQL
-
Engine Version: Select the
latest
-
Templates:
Production
-
Deployment options:
Multi-AZ DB instance
-
Databse Settings:
- DB instance identifier:
prod-database
- Master username:
admin
- Master password: For example
admin12345
- NOTE: Password must be at least 8 characters, Can't contain / , ', " and @
- DB instance class: Choose
Burstable classes
- Include previous generation classes:
Enable
- Select
db.t2.micro
- Select
- DB instance identifier:
-
Storage:
- Storage type: Select
General Purpose SSD (gp3)
- Allocated storage:
30
- Storage autoscaling:
Enable
- Maximum storage threshold: Default
1000
- Storage type: Select
-
Connectivity:
- Compute resource: Select
Don’t connect to an EC2 compute resource
- Virtual private cloud (VPC):
Prod-VPC
- DB Subnet group: Select your DB Subnet group
prod-db-subnet-group
- Public access:
NO
- NOTE: To remote Programatically manually, we'll have to setup a
bastion host
- NOTE: To remote Programatically manually, we'll have to setup a
- Database authentication: Select
Password authentication
- Compute resource: Select
-
Monitoring:
- Enhanced Monitoring:
Disable
- Enhanced Monitoring:
-
Additional configuration:
- Initial database name:
phpappdatabase
- Backup:
Enable automated backups
- Encryption:
Enable encryption
- Maintenance:
Disable
- Deletion protection:
Disable
- Initial database name:
-
Click
CREATE DATABASE
-
-
Navigate to
Amazon S3
-
Click on
Create Bucket
- Name: Use naming convention
prod-proxy-app-db-config-YOUR-LAST-NAME-and-MONTH-OF-BIRTH
- AWS Region: Select your project region
(California) us-west-1
- Object Ownership:
ACLs disabled
- Block Public Access settings for this bucket:
Enable
Block all public access
- Bucket Versioning:
Enable
- Default encryption:
Enable
- Click
CREATE BUCKET
- Name: Use naming convention
-
Navigate to the GitHub Project Repository, Download the project App Stack and Upload it to the Bucket
- Click Here: https://github.com/jacodetunde/High-Availability-Architecture.git
- Make sure you're on
four-tier-mailing-app-project
branch - Click on the
ZIP file
name:app-db-configs.zip
- Click
View Raw
orDownload
to download the application configs to your local
- Make sure you're on
- Once it get's downloaded on your local
UNZIP
the File- Open your
VSCODE, ATOM
or any other Text/Code Editor of your choice and make the following changes- Update the
dbinfo.inc
with your specificDatabase Configurations
- Update the
000-default.conf
with your specificBackend Load Balancer DNS/VenturaMailingApp.php
- Update the
- Upload: All
3 files
into yours3
bucket
- Click Here: https://github.com/jacodetunde/High-Availability-Architecture.git
STEP 9: Create a Bastion Host VM For Remote Access ((SSH)) To Webservers, Appservers and MySQL Database
- Navigate to Instance in EC2
- Click on
Create Instance
- Name:
Prod-Bastion-Host
- AMI:
Ubuntu 20.04
- Instance type:
t2.micro
- Key pair name: Select/Create Key pair
- Name:
Prod-"YOUR_REGION"-Key
- Name:
- Network:
- VPC:
Prod-VPC
- Subnet: Select either
Prod-NAT-ALB-Subnet-1
orProd-NAT-ALB-Subnet-2
- Auto-assign public IP:
Enable
- Security Group:
- Select existing security group:
Bastion-Host-Security-Group
- Select existing security group:
- VPC:
- Click
LAUNCH INSTANCE
- Name:
- Navigate to IAM
- Click on Roles and
Create Role
- Select
EC2
- Click on
Next
- Permissions policies: Assign
AmazonS3ReadOnlyAccess
- Click on
Next
- Name:
EC2-AmazonS3ReadOnlyAccess
- Click
CREATE
- Select
- Once you lock into the
Bastion
, Execute the Following commands to setupSSH Agent Port Fowarding
- Login to your
Prod-Appserver
using SSH Port Fowarding and Execute the following ccommands https://github.com/jacodetunde/High-Availability-Architecture/blob/main/appservers-startup-scripts/app-automation.sh
1. Setup SSH Port Forwarding Between Your Local and Bastion Host To Point at The Web, App and DB Instance.
exec ssh-agent bash
eval 'ssh-agent -s'
ssh-agent bash
- (Once you run this command it will tell you if you have added some identities to SSH agen or not. If not run the bellow command to add identity or private key)
ssh-add -k "Absolute Path to your Private key file on your Local"
ssh-add -L
Now run the above command to check added identities or Private keys
- Now we have to use this SSH Agent Identity to login to our bastion in the public subnet then we'll be able to login to our private server
ssh -A -i "private key" USER_NAME@HostNameORipAddress
- (-A stands for AGENT FORWARDING. And once you get into the instance in the Bastion host using the SSH AGENT Identity, when you try to SSH into the instance in the private subnet now, what SSH AGENT will do is. It will make use of the Identity in your local machine to access the server. Then you'll be authenticated)
ssh USER_NAME@"Private Instance IP Address"
- (Once you run this command you will be allowed into the server. That is SSH Agent port fording. It makes use of the locally stored Identity).
- Naviagte to EC2/Launch Configuration
- Click on
Create Launch Configuration
- Switch by Clicking on
Create launch template
-
Name:
Prod-Webservers-LT
-
Template version description:
Prod-Webservers-LT Version 1
-
My AMI: Select for
Ubuntu 20.04 LTS
-
Instance type:
t2.micro
-
Key pair: Create a new key pair
california-keypair
-
Network Settings:
- Subnet: Select one of the Webserver subnets
- Security groups (Firewalls): Select the
Webservers-Security-Group
-
Expand
Advance details
-
IAM instance profile: Select
EC2-AmazonS3ReadOnlyAccess
IAM Role -
Auto-assign public IP:
ENABLE
-
Auto-assign public IP:
ENABLE
-
NOTE:
Make sure to update the LoadBalancer DNSBACKEND_LOAD_BALANCER_DNS
in https://github.com/jacodetunde/High-Availability-Architecture/blob/main/webservers-reverse-proxy-config/000-default.confbefore passing the below User Data
-
User data: provide the user data in https://github.com/jacodetunde/High-Availability-Architecture/blob/main/webservers-reverse-proxy-config/web-automation.sh
-
NOTE:
Update thewebserver-reverse-proxy-config/000-default.conf
on GitHub before passing User Data -
Click on
Create launch template
-
-
- Click on
- Naviagte to EC2/Launch Configuration
- Click on
Create Launch Configuration
- Switch by Clicking on
Create launch template
-
Name:
Prod-Appservers-LT
-
Template version description:
Prod-Appservers-LT Version 1
-
My AMI: Select
Amazon Linux 2
-
Instance type:
t2.micro
-
Key pair: Create a new key pair
california-keypair
-
Network Settings:
- Subnet: Select one of the Appserver subnets
- Security groups (Firewalls): Select the
Appservers-Security-Group
-
Expand
Advance details
- IAM instance profile: Select
EC2-AmazonS3ReadOnlyAccess
IAM Role
- User data: provide the user data in https://github.com/jacodetunde/High-Availability-Architecture/blob/main/appservers-startup-scripts/app-automation.sh
NOTE:
Update the Database Configuration filemain/appserver-database-config/wp-config.php
on GitHub before passing the User Data- Once changes have been made and user data passed
- Click on
Create launch template
- IAM instance profile: Select
-
- Click on
- Navigate to
EC2/Auto Scaling
- Click on
Create Auto Scaling Group
-
Auto Scaling group name:
prod-webservers-autoscaling-group
-
Launch template: Select the
Prod-Webservers-LT
-
Click on
NEXT
-
VPC: Select
Prod-VPC
-
Availability Zones and subnets: Select
Prod-Webserver-Subnet-1
andProd-Webserver-Subnet-2
-
Click
NEXT
-
Load balancing: Select "Attach to an existing load balancer", select
Frontend-LB-HTTP-TG
- Select
Choose from your load balancer target groups
- Existing load balancer target groups: Select the
Frontend-LB-HTTP-TG
- Select
-
Health check type: Select
EC2
andELB
-
Click on
NEXT
-
Group size:
- Desired:
2
- Min:
2
- Max:
5
- Desired:
-
Scaling policies:
- NOTE: Also Known as Dynamic Scaling. This defines the
Scale Out Policy/Action
- Select
Target tracking scaling policy
- Scaling policy name:
prod-asg-scale-out-policy
- Metric type: Select
Average VPU Utilization
- Target value:
80%
- Scaling policy name:
- Click on
NEXT
- Click on
NEXT
- Click on
NEXT
- Click on
Create Auto Scaling Group
- NOTE: Also Known as Dynamic Scaling. This defines the
-
- Click on
- Navigate to
EC2/Auto Scaling
-
Click on
Create Auto Scaling Group
-
Auto Scaling group name:
prod-appservers-autoscaling-group
-
Launch template: Select the
Prod-Appserver-LT
-
Click on
NEXT
-
VPC: Select
Prod-VPC
-
Availability Zones and subnets: Select
Prod-Appserver-Subnet-1
andProd-Appserver-Subnet-2
-
Click
NEXT
-
Load balancing: Select "Attach to an existing load balancer", select
Backend-LB-HTTP-TG
- Select
Choose from your load balancer target groups
- Existing load balancer target groups: Select the
Backend-LB-HTTP-TG
- Select
-
Health check type: Select
EC2
andELB
-
Click on
NEXT
-
Group size:
- Desired:
2
- Min:
2
- Max:
5
- Desired:
-
Scaling policies:
- NOTE: Also Known as Dynamic Scaling. This defines the
Scale Out Policy/Action
- Select
Target tracking scaling policy
- Scaling policy name:
prod-asg-scale-out-policy
- Metric type: Select
Average VPU Utilization
- Target value:
80%
- Scaling policy name:
- Click on
NEXT
- Click on
NEXT
- Click on
NEXT
- Click on
Create Auto Scaling Group
- NOTE: Also Known as Dynamic Scaling. This defines the
-
-
TEST TO MAKE SURE APPLICATION IS ACCESSIBLE
-
- Navigate to the Route 53 service
- Either
Register a Domain
if you don't have one orUse and Esisting Domain
- Click on
Hosted Zones
- Click on
Your Domain Hosted Zone
-
Click
Create Record
- Name:
PHP-Webapp-DNS-Record
- Type:
CNAME
Domain Record - Subdomain:
www
- Value: Provide
Prod-Frontend-LB
DNS - Routing policy:
Simple Routing
- Name:
-
CREATE RECORD
-
Give Rout53 between 2-4 Minutes for it to Publish The Record Configs
-
RUN A TEST: Open your browser
http://www.jjtechphp-fourtier-webapplication.com/VenturaMailingApp.php
-
-
Navigate to the Route 53 service
-
Click on
Health Checks
-
Click
Create Health Check
- Name:
Prod-Webapp-HC
- What to monitor:
Endpoint
- Specify endpoint by:
Domain Name
- Protocol:
HTTP
- Port:
80
- Path /:
VenturaMailingApp.php
- Create alarm:
yes
- Send notification to:
New SNS topic
- Topic name:
PHP-Webapp-SNS-Topic
- Recipient email addresses:
your-email@hosted-provider.com
- NOTE:
YOU HAVE TO ACCEPT THE SNS EMAIL SUBSCRIPTION REQUEST THAT WILL BE SENT TO YOUR EMAIL
- Send notification to:
CREATE
- Name:
-
Refresh
Health Check Console
to ConfirmHealthy State
- Navigate to:
www.jjtechphp-fourtier-webapplication.com/VenturaMailingApp.php
-
Add
5 Employee Entries
and Example Addresses -
Verify that these Entries are stored in the Database
phpappdatabase
Database Instance
Login to the Database
Using theBastion Host
- Login to bastion and install mysql client
sudo apt update
sudo apt install mysql-server -y
- Once you install the MySQL client go ahead and connect to the database using the below command.
- NOTE: Once you run the command it'll request you provide your DB Password then it'll log you in after it validates the password is correct
mysql -h YOUR_DATABASE_ENDPOINT -u admin -p
- You're now in the database, you can now run the below command to show all databases, and you can verify the result by visiting the "Databases" tab in Cloud SQL.
SHOW DATABASES;
- Set Database as default
USE phpappdatabase;
- List all TABLES in the
phpappdatabase
Database
SHOW TABLES;
- Show The Data In The
EMPLOYEES
Table in thephpappdatabase
Database
SELECT * FROM EMPLOYEES;
-
Navigate back to the console while you're still logged into the Database
-
Select the App Database Instance
-
Click on
Actions
-
Click on
REBOOT
- Select
Reboot With Failover?
- Click
CONFIRM
- Select
-
CONFIRM THAT THE APPLICATION IS STILL ACCESSIBLE
and -
That you are still logged into the Database from your Terminal
-
Navigate to the
Certificate Manager
Service -
Region: Confim you are in the same Region as your workloads
-
Click
Request a Certificate
-
Certificate type:
Request a public certificate
-
Click
Next
- Fully qualified domain name:
Provide Your Domain From Rout53
Example:www.jjtechphp-fourtier-webapplication.com
- Click
REQUEST
- Fully qualified domain name:
-
Give it a few Minutes for the Certificate Request to Complete
-
Refresh
the CM Console