Static to Elastic Web App
Published: 2023-08-26 15:12:39

# Overview
The Web App - Single Server to Elastic Evolution is a project created by Adrian Cantrill of https://learn.cantrill.io/ which is a popular resource for people looking to earn their AWS certifications. In this project we evolve the architecture of a WordPress web app deployed on a single EC2 instance into a scalable and resilient architecture.

#### Stage 1 - Setup the environment and manually build WordPress
I used a CloudFormation template to set up the base 3-tier architecture which was 1 VPC with 3 AZ in us-east.

Next I manually created the EC2 to hold the WordPress instance. 

Storing configuration information within the SSM Parameter store scales much better than attempting to script them in some way. In this sub-section you are going to create parameters to store the important configuration items for the platform you are building. I connected to the EC2 instance and installed WordPress. 

I mapped environment variables in the EC2 to the parameters I created above. I am doing this step manually so later when I use IaC I can feel the benefit it brings.

I ran command to update OS on the instance manually and installed MariaDB, Apache web server, wget, some libraries, and a stress test utility.

I set the DB and HTTP server to run automatically when EC2 starts and set root pw to the MariaDB as the parameters we initialized earlier.

I manually downloaded and installed WordPress. Next I created the db and initialized settings manually. I went to EC2 and copied the IPv4 and logged into WordPress and made a post to this solution working.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vdmaeexunfqfxt82gqvj.png)

Limitations of this implementation:
* App and DB configured manually
* App and DB on the same instance so they can't scale separately
* Content is also stored locally in the instance so it can't scale
* User connection is directly to the EC2 instance
IP address for WordPress from the EC2 instance is stored statically in a DB so if I stop the EC2 instance and get assigned a new public IP I lose the original connection via the old IP

End result of architecture of this section.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/68i9bvf360tqh5rjz2ti.png)

#### Stage 2 - Automate the build using a Launch Template
I created an EC2 launch template so I don't have to manually configure the steps for setting up EC2 with WordPress and the DB in part 1.
* This template can have versions which we will iterate on as time goes on
* In the User Data section I can paste all the commands I used in the manual step to have it automatically initialized on startup

Same limitations as the previous stage except we automated the build of the WordPress instance using the LT.

End result of architecture of this section.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nm3k648o47onjnep4exp.png)

#### Stage 3 - Split out the DB into RDS and Update the LT
I created a subnet group so RDS can select from a range of subnets that RDS can put it's DBs inside.
* 3 subnets over 3 AZ

Next I created the RDS instance and migrated the data from EC2 to RDS.
* To do this I connected with the session manager to the EC2 instance and exported the data from the local MariaDB

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y75xcr69027tk049ppff.png)

I restored the exported SQL file into my RDS instance and changed the endpoint to point to RDS.
* Then I ran the SQL command to import the exported SQL file into RDS
* Next I pointed the WordPress site to RDS instead of MariaDB and disable MariaDB
* I went back to EC2 and open the IPv4 address and I can see the site still hosted except now it's using RDS
  * To be clear though the media and WordPress post data are stored in separate DBs where the images are still in the local EC2 folder called wp-content while the post data has been migrated off EC2 to RDS
* Finally I updated the launch template User Data section to remove references to MariaDB and set the new template as the default

End result of architecture of this section.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xm2t18ox82a5ltggyik4.png)

#### Stage 4 - Split out the WP filesystem into EFS and Update the LT
I still have the media (uploaded images) for WordPress stored locally in folder called wp-content on the EC2 instance. Next I will migrate that data to an EFS.

I created an EFS manually and added the EFS ID to the parameter store.

I went into the running EC2 instance and installed a package needed to connect to EFS.

I added a line to fstab file to mount the EFS volume to the wp-content folder each time EC2 is started.

I rebooted the EC2 instance to see if it mounts the EFS file system to it which it did successfully.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u6wn5jr81w023z2cxu5x.png)

I migrated the images to the folder the EFS file system is mounted to and now EC2 is decoupled and can scale separately from the media or the posts.

Finally I updated the launch template to configure EFS in the User Data section to do the steps I did above automatically and set this version 3 of the LT as the default now.

End result of architecture of this section.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/68kzbms4bpoq8s2yax0w.png)

#### Stage 5 - Enable elasticity via a ASG & ALB and fix WordPress (hardcoded WPHOME)
Users can still connect directly to the EC2 instance and I don't have health checks or auto-healing capabilities and the IP address of the instance is hardcoded into the DB.

I created a load balancer will solve this. The LB DNS will be used in place of the EC2 IP address in order to map the DNS to each EC2 create a parameter for the LB DNS.

I created an ASG and attached it to an existing LB with a desired capacity of 1.
* I enable ELB health checks and metric collection with CloudWatch

I terminated the old EC2 instance I created manually and watched the ASG automatically create an instance to match the desired amount I defined earlier.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/undfgyxxidjsjajxtjop.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/961g71yscys5mev919pp.png)

I want to create a more dynamic scaling policy based on CPU
* I created a CloudWatch alarm to go off when average CPU utilization is above 40%
* I created a CloudWatch alarm to go off when average CPU utilization is below
* Now I updated the ASG to have a max capacity of 3 units

I connected to the ASG EC2 and ran the stress command to test the scaling. The ASG detected high CPU so it provisioned a new EC2 instance.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ffrx6l05g9bosxgbowt5.png)

I terminated this instance and watched the ASG detect this with health checks and it added another EC2 automatically to demonstrate self healing.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ydoqdvq6hvm68zw6zxa.png)

End result of architecture of this project.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1nykehwfp7vdaw29fxw0.png)

#### Conclusion
Overall this was another great hands on experience. It helped to reenforce VPC and subnet concepts since I split the web app into a 3 tier architecture. It demonstrated the value having a launch template to save having to manually configuring EC2 instances. It helped me learn how to migrate data from one database to another in a different subnet and how EFS is useful for serving static files to multiple EC2 instances. Finally it demonstrated the power of ASG and ALB by making the solution elastic and enabling health checks and self healing.