Unfortunately, things fail from time to time, including our applications’ servers. A connectivity problem at the datacenter, a natural disaster or a hardware issue can render our blog offline. Since we cannot predict the future nor prevent failures from happening, we are leveraging the power of the cloud in order to save ourselves from them and keep our services working despite them: we’re designing our infrastructure with failure in mind so nothing fails.
It’s important that our platform isn’t dependant on any specific component in order to work or else service will be interrupted should that component fail. We have to identify our platform’s components and isolate them as much as possible: if our front web servers depend on some specific database server, then everything in our application depends on it and it becomes a dreadful single point of failure. On the other hand, if we design in a way in which we don’t depend on specific machines, we can have more than one of them serving each of our application’s layers and we won’t see any issues as a result of a single machine failing.
Even if we had multiple instances, a failure on the datacenter’s behalf would render all of them offline. AWS tries to prevent that by designing it’s global infrastructure as a set of regions composed by availability zones. Regions are service points completely isolated from one another, both in terms of connectivity and geographical placement, while availability zones in a region are interconnected and are placed much closer, but still far enough so a single disaster can’t affect them all at the same time. Since AZs in a region are connected directly to each other, it’s possible for us to deploy our infrastructure on multiple AZs at the same time making sure that, should one zone fail, traffic will be redirected to the others without service interruption.
Some important considerations regarding storage
WordPress stores data in two locations: database and the local file system. On the database, WordPress stores the data it generates from normal usage, such as blog entries and comments, the site’s configuration or the users and passwords list. On the file system, it stores the files that contain the PHP code that conforms WordPress and it’s plugins. As a result of this, once the database is moved to RDS, there’s no issue in serving the content from multiple instances but we’ll have to find a solution for those times when WordPress’ code changes (for example, when plugins are added, updated or removed or when WordPress itself is updated).
Unfortunately, we can’t attach a single EBS volume to more than one instance, so we’ll have to find some way to keep all instance’s file systems in sync. Let’s see some of the possibilities we have:
Using custom AMIs
If we rarely make changes to our installation, we can create an image of an instance containing our working model of WordPress and then starting instances based on that image. In AWS terminology, these images are called AMIs and can be stated as a parameter at instance creation time.
This method is very easy to use because we only need to create the base instance, set it up with WordPress and the desired plugins and right-click on it in the EC2 Console then choosing the “Create AMI” option. From that point on, when we are launching a new instance we’ll see our AMI available under the “My AMIs” tab or, if we’re using AutoScaling, we can pass it as a parameter when creating our launch configuration.
As a backside to this approach, this method doesn’t allow us to use WordPress’ administrative interface to make changes such as updating WP or installing plugins, since we’d be making changes on a single instance only, thus desynchronizing it from the others. We’ll need to create a new AMI and replace all our instances with new ones based on the most recent AMI.
GlusterFS is a distributed file system that, among other features, allows us to replicate a volume or a part of it across a number of servers (We already commented on GlusterFS usage in AWS). We can use it to replicate the WordPress’ directory across all our instances, thus being able to install plugins from the native administrative interface without issues.
On the other hand, GlusterFS’s set up is slightly more complicated than other options and it’s not very AutoScaling friendly because all instances need to know each other instances they share the file system with, which means that adding or removing an instance implies somehow updating the remaining instances’ information. It’s also important to keep in mind that file system performance decreases the more instances are added.
With S3FS we can mount an S3 bucket as if it was a traditional file system. With it, writing on the mounted directory will actually be done on the bucket and changes will be seen across all instances that are mounting it, this allowing us to use WordPress administration interface as usual with the assurance that changes will be propagated.
This solution allows us to autoscale without trouble since files are actually stored on S3 and any future instances would just mount the bucket. On the other hand, performance may be affected, specially when reading an object for the first time and when writing. Because of this, a correct cache configuration is critical and performance benchmarking is recommended to make sure S3FS fits our needs.
Elastic Beanstalk is the Platform as a Service component of AWS which easies application deployment conforming to a series of previously configured options. By using GIT versioning, we can upload our app’s source code and Elastic Beanstalk will handle the deployment of our latest revision (or the one we choose).
When using this method, we need to create an isolated private instance which will contain our code and modifications to it (which can be done using the WordPress administration panel) and then uploading it to Beanstalk and deploying.
It’s worth mentioning that, since it’s not a part of the WordPress’s code, this method doesn’t take care of the contents of the database, so we’ll need to implement some custom solution in order to upload our changes to our production RDS server.
Designing the platform
In posts to come, we’ll transform our example blog into a highly available one by relying on the follownng AWS’s services. Please note that we’ll propose a possible solution but, as we’ve just seen, there are many ways to achieve high availability, each one of them with it’s own pros and drawbacks.
WordPress’s PHP code will be executed and served from an EC2 instances group, scattered through multiple availability zones. These instances will be equivalent to one another and our visitors won’t be able to tell them apart. Since they will be hosted in multiple AZs we’ll be safe from an eventual zone failure because, as we’ll see next, the load balancer will take care of sending incoming traffic to available instances only. As a bonus, more instances mean we’ll have more horsepower, hence being able to process more requests.
In order to distribute the load among our instances, we’ll set up an Elastic Load Balancer that will become our visitors’ entry point to our blog. By pointing our domain name to the ELB instead of pointing it to an instance, AWS will redirect our users to an available and healthy instance while discarding those that are not responding for whatever reason.
It’s noteworthy that ELB is an inherently highly available service: it exists in every single zone in which we have instances associated to it.
Our database will be hosted on RDS, this way isolating it from the instances and giving us the possibility of running it in Multi-AZ mode. In this mode, we’ll have a standby RDS instance in another AZ that will kick in should anything happen to the active database instance.
In addition to this, we can set up a series of read replica instances if we feel that we need more read capacity, but this approach means we’ll have to modify WordPress.
S3 and CloudFront
We’ll store our static content on S3 as well as some of the WordPress’ file system in order to synchronize our WP installation across all instances and make sure they share the same plugins and components. And, thanks to CloudFront, our static content stored on S3 will be cached and served from edge locations near our customers, as we already showed on a prior tutorial.
Amazon EC2 Documentation: http://aws.amazon.com/…/ec2
Amazon RDS Documentation: http://aws.amazon.com/…/rds/
Amazon Elastic Load Balancing Documentation: http://aws.amazon.com/…/elasticloadbalancing/
Amazon Elastic Beanstalk Documentation: http://aws.amazon.com/…/elasticbeanstalk/
Amazon S3 Documentation: http://aws.amazon.com/…/s3/
S3FS Wiki: https://code.google.com/…/list
Tutorial: Using Elasticache with WordPress: http://blog.celingest.com/…/tutorial-using-elasticache-with-wordpress/
Tutorial: Creating a CDN for WordPress with CloudFront and S3: http://blog.celingest.com/…/tutorial-creating-cdn-wordpress-cloudfront-s3/