Migrate a small WordPress installation to a scalable HA deploy on AWS
Step to create and convert a single monolithic WordPress to an HA scalabale application:
- create an AWS account;
- create a security group;
- launch a standard AMI WordPress;
- divide Application layer from DB layer;
- setup an HA frontend with Load Balancing and Auto Scaling;
- migrate static content to EFS.
I wrote this for a friend, if you already have a WordPress site on AWS go to step 4!
Step 1 – Create an AWS account
Pay attention to the region you are using before start, if you don’t have already an AWS account you can create one for free, there is also a free tier of resources for new user that you can use to test this procedure.
When you have finished, you’ll have a fresh new VPC (Virtual Private Cloud).
Step 2 – Create a security group
It’s always a good idea to create a new Security Group instead of using the default, so you need to create a Security Group under EC2 service adding HTTP (80) and SSH (22) traffic, I put 0.0.0.0/0 in Source for SSH but you need to add your public IP.
Step 3 – Launch a standard AMI WordPress
In EC2 under Images you can find AMIs menu, insert wordpress and add Platform: Ubuntu, Root Device Type: EBS, Description: bitnami and Virtualization type: HVM from the dropdown menu.
In this moment, the latest for a non-multisite server, is the 4.7.2 version. Select the latest and press Launch.
Now you need to choose the instance type, to start a test the t2.micro is perfect, press Next.
Configure details and press Next.
Leave storage as is, press Next.
Add Tags and press Next.
Select Security Group and press Review and Launch.
Check if everything is ok and press Launch.
Create a new Key Pair to administer your instance, Download the Private Key and press Launch Instances.
In the EC2 Instance menu you can check the status and find, if it is running, the ip and the dns name.
Now you can connect to your instance via SSH, using the Key downloaded, bitnami is the default user or visit the blog site in HTTP.
First of all you have to change the default username and password of your WordPress (default user, bitnami), connect to the wp-login.php page and edit your profile, remember to patch WordPress and WordPress Plug-in if necessary.
After, you need to disable the bitnami banner executing from the console:
sudo /opt/bitnami/apps/wordpress/bnconfig –disable_banner 1
and patch O.S. Ubuntu with:
sudo apt-get update
sudo apt-get upgrade
To reach your blog with a simple DNS name, Add a DNS record A to your DNS zone with the instance Public IP.
Now change the default WordPress Address, find the wp-config.php:
sudo find / -name wp-config.php
change the WP_HOME and WP_SITEURL parameter with “define(‘WP_HOME’,’http://example.com’);” and “define(‘WP_SITEURL’,’http://example.com’);”.
Save, exit and restart apache:
sudo /opt/bitnami/ctlscript.sh restart apache
Ok, now everything is up and running!
Step 4 – Divide Application layer from DB layer
This step will increase performance, you’ll have 2 instance instead of only one with everything inside, availability because of the RDS multi-zone configuration and the BackUp/Snapshot jobs managed by Amazon… but also the costs, pay always attention to this point because is very simple to receive an high bill adding services on Amazon.
First of all create a snapshot from the volumes menu.
Connect to the server console and change to the directory found before, editing the file wp-config.php to read the actual DB password:
sudo nano wp-config.php
You’ll find the database name, connection username and password and the field where you can put the hostname of the DB Server that now is localhost:3306.
Close the editor and do a backup of the DB with phpMyAdmin or with the command:
mysqldump -u bn_wordpress -pDBPassword bitnami_wordpress > /home/bitnami/backup.sql
Verify the actual MySQL version:
sudo mysql –version
Create an RDS instance to move the DB away from the server using launch instance under RDS instance menu.
Choose MySQL and press Select.
Choose Production MySQL instance and press Next Step.
Choose the correct DB Engine Version, insert “wordpressdb” as DB Instance Identifier and input the other information retrieved early, press Next Step.
Insert the other parameters accordingly with your site Maintenance Windows and press Launch DB Instance.
After you have added in the security group an inbound rule for port 3306 with source address the private VPC subnet, you can upload the dump to the new service from the WordPress Console with the command:
mysql -u bn_wordpress -pDBPassword –database=bitnami_wordpress –host=RDSinstance < backup.sql
Now with the nano editor change the address of the DB server from “localhost” to your RDS Endpoint name and restart Apache:
sudo nano wp-config.php
sudo /opt/bitnami/ctlscript.sh restart apache
Now you have a two tier application with a hardware replica of the database.
Don’t forget to create a new snapshot, remove the old one and remove mysql from your Webserver.
This commands disable it:
sudo /opt/bitnami/ctlscript.sh stop mysql
sudo mv /opt/bitnami/mysql/scripts/ctl.sh /opt/bitnami/mysql/scripts/ctl.sh.disable
sudo mv /opt/bitnami/mysql /opt/bitnami/mysql-disabled
Step 5 – Setup an HA frontend with Load Balancing and Auto Scaling
Now we need to create a base AMI to use from your current Web-server, go to the EC2 instance menu, select your Web-server and from Actions menu select Image menu and click on Create Image.
It needs to reboot your instance to confirm file system integrity, plan this it in a maintenance window.
Now you have a new private AMI “Owned by me”.
Create an Elastic Load Balancer to distribute requests against Application Layer instances, under Load Balancers menu press Create Load Balancer.
Input data as described below and click Netx:Configure Security Settings.
You’ll receive a warning because you don’t have defined an HTTPS listener, click Next: Configure Security Settings.
Create a new security group with only the HTTP port from anywhere and press Next: Configure Routing.
Choose to create a new target group without registering instances and press Next: Register Tergets.
Now review all information and press Create, a confirmation page appear.
Now you can choose to launch another instance from your new AMI and connect both to the load balancer or create an auto scaling group that helps you to dynamically adjust the number of instances.
I opt for the second option, more complex but more powerful, start the wizard clicking on Create Auto Scaling group under Auto Scaling Groups menu in EC2.
Select from your AMI the WordPress-Base image created before.
Select t2.micro instance type and press Next:Configure details.
Input details and press Next: Add Storage.
Leave everything as is and click on Next: Configure Security Group.
Create a new Security Group with SSH limited to your public IP and HTTP opend to Anywhere. Press Review.
Check everything and click Create launch configuration.
Select the Key pair used to administer yor WordPress, check to confirm that you have the key and press Create launch configuration.
Insert the Group name, the Group size, the 3 subnet of your VPC, check to receive traffic from load balancers and choose the Target Group, decrease the Health Check Grace Period to 120 for the test or set accordingly with your application warm-up duration and check to monitor instances with CloudWatch. Press Next: Configure scaling policies.
Now add the policies to scale up and scale down, you need to create the topic to receive notifications, pushing on add new alarm. Input the maximum number of instances. Now click on Next: Configure Notification.
Continue adding Tags and press Review.
Review everything and press Create Auto Scaling group.
Now you can find two more instance in your VPC and you can test the application with the load balancer DNS name, if everything is ok change the DNS record to point to your load balancer.
When the DNS propagation is complete, you can terminate your original instance.
Step 6 – Migrate static content to EFS
Create a NFS FileSystem from menu under EFS service, add the AutoScaling security group and press Next Step.
From the success page you can read the use instructions witha click on Amazon EC2 mount instructions.
Now add NFS port (2049) to the Security Group.
Connect to your instance via SSH and install NFS support.
sudo apt-get install nfs-common
Create a new directory and mount the FileSystem.
sudo mkdir efs
sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 DNS name:/ efs
Copy the static content to the new shared directory, in this example we move the uploads directory.
sudo cp -a –p /opt/bitnami/apps/wordpress/htdocs/wp-content/uploads /opt/bitnami/apps/wordpress/htdocs/wp-content/efs/uploads
Modify the configuration file adding the new path.
sudo nano /opt/bitnami/apps/wordpress/htdocs/wp-config.php
Add a new line after “ABSPATH . ‘wp-settings.php’);” with:
define( ‘UPLOADS’, ‘/blog/wp-content/uploads’ );
Save, exit and your application will serve resources from the new path, as shown in this example:
sudo nano /etc/fstab
Insert this line at the end of the file:
DNS NAME:/ /opt/bitnami/apps/wordpress/htdocs/wp-content/efs nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0
Now you have to create a new base image, as you have done before, naming it WordPress-Base-EFS.
Copy the Launch Configurations from Actions menu.
Modify the AMI pressing on Edit AMI.
Select the AutoScaling Security Group and press on Review.
Close everything and change back the Auto Scaling Group parameters, change the Launch Configuration selecting the new one.
That’s all folks!
No… there are a lots of things to change to your WordPress to manage a dynamic multi frontend application, move static content to S3 bucket (with WP Offload S3 Plug-in), change plug-ins that doesn’t function properly in this configuration, change your procedure to patch and upgrade your app (take in account AWS CloudFormation to migrate the infrastructure to a new deploy), etc..
Monitor everything and if necessary change the number of instance in your target group, the size of the instances, configure DB read replica (with the necessary plug-in) to increase read performance with less interzone traffic etc.
So I hope you can find this tutorial useful 😉