Creating a highly available minimum viable architecture on AWS

This will be the first in a series of posts where I go through the steps of creating a highly available minimum viable architecture.

To see the results of the step by step guide in video form click here

Why

High availability is becoming more and more important. The Internet gives people the opportunity to shop/work and communicate with more flexibility than any other time in human history. Software is expected to work, and it's expected to work 100% of the time. Businesses can not afford to have the negative exposure which a service not being available brings.

I'm using this series of blog posts to increase my knowledge of Amazon Web Services and my Linux administration skills. Although I've had exposure to solving this style of project before, I want to learn and increase my skill set further, whilst sharing knowledge gained with a wider community.

All and any feedback would be greatly appreciated.

Technologies

For these blog posts I'm going to create the minimum viable architecture using the following stack.

I'll be using Amazon web services to handle the hardware management, and using many of their software products to achieve the highly available architecture.

The rest of the software stack will use Ubuntu, Node.js and Git. I'm using these technologies as they're very popular in the web development world, simple to install and have been designed to work at scale.

Design

Before delving into building the application I took a while to think about the minimum viable architecture needed to produce highly available software stack. I also wanted to design the application in a scalable fashion, taking on advice from other developers and using my own personal experiences.

Amazon Cloudfront and Route 53 are used to speed up delivery of the website, and manage DNS , which from personal experience can be tricky to get to right. I'm more than happy to pass this responsibility off to the team at Amazon.

The next level down will consist of two web servers. These web servers will handle incoming requests, communicate with web services and render the data returned.

Putting it together

Step 1: Create your EC2 instances

  1. Sign up for amazon web services http://aws.amazon.com/console/
  2. Login to aws
  3. Click on EC2
  4. Click on Launch instance
  5. Keep Classic Wizard selected and click Continue
  6. Click select next to Ubuntu server 12.04.1 LTS
  7. Keep the default options for number of instances and instance type and click Continue.
  8. Keep the advanced options the same and click Continue
  9. Keep the storage device configuration the same and click Continue
  10. Ignore setting any tags and click Continue
  11. Enter a name for your key pair, download and save to your ~/.ssh/ directory
  12. Give your security group a name and enter 80 in Port range, keep source as 0.0.0.0/0
  13. Confirm all the details and click launch
  14. Select a new region and repeat steps 4- 13

Step 2: SSH to one of the machine

On your desktop machine run the following commands

sudo chmod 600 ~/.ssh/ec2-keypairname.pem
ssh-add ec2-keypairname.pem
ssh -v ubuntu@[PublicDNSOfInstance1]

Step 3: Create a simple node.js application

sudo locale-gen en_GB.UTF-8
sudo apt-get update
sudo apt-get install git
sudo apt-get install nodejs
sudo apt-get install npm
sudo mkdir -p /var/www/frontend/
sudo chown -R ubuntu:ubuntu /var/www/frontend/
cd /var/www/frontend/
npm install express
./node_modules/express/bin/express
//Press y to destination is not empty, continue?
npm install
//Unable to open port 80 directly, use iptables to redirect port 80 traffic to port 3000
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 3000
node app &
At this point you should be able to navigate to the public DNS entry in browser and see your node app running.

Step 4: Create an upstart script for the application

mkdir /var/www/frontend/log/
sudo vi /etc/init/nodefrontendapp.conf

And paste in the following the following

description "node.js front end server"
author "kvz"

start on startup
stop on shutdown

script
export HOME="/root"

exec /usr/bin/node /var/www/frontend/app.js 2>&1 >> /var/www/frontend/log/node.log
end script
                
Save and exit vi and run the following commands
sudo chmod u+x /etc/init/nodefrontendapp.conf
sudo start nodefrontendapp

Step 5: Set up a cloned server

git init .
git add .
git commit -m "Inital Commit"
ssh-keygen -t dsa
//use default directory
cd ~/.ssh/
cat id_dsa.pub >> authorized_keys
//keep default options
exit

On your desktop machine copy the ssh key to the other instance via ssh

scp ubuntu@[PublicDNSOfInstance1:/home/ubuntu/.ssh/id_dsa .
scp id_dsa ubuntu@[PublicDNSOfInstance2]:/home/ubuntu/.ssh/id_dsa

Now we'll clone our basic application onto the second web server

ssh ubuntu@[PublicDNSOfInstance2]
sudo locale-gen en_GB.UTF-8
sudo apt-get update
sudo apt-get install git
sudo apt-get install nodejs
sudo apt-get install npm
sudo mkdir -p /var/www/frontend/
sudo chown -R ubuntu:ubuntu /var/www/frontend/
cd /var/www/frontend/
git clone ubuntu@[IpAddresOfInstance1]:/var/www/frontend/.
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 3000
Create the upstart script as mentioned in Step 4 for this server too.

Now the simple node applications are up and running on two seperate servers, the last part is getting them to work under out domain name.

Step 6: Setting up Route 53

  • Go back to the AWS console
  • Navigate to first region with a running instance
  • Click elastic IPs
  • Click Allocate New Address
  • Click Yes, Allocate
  • Click Associate Address
  • Select instance
  • Make a note of the IP address and public DNS
  • Repeat for the other region
*Note from this point on you'll have to SSH in via the elastic ip address / elastic public DNS
  • Cick Services dropdown and choose route 53
  • Click Create Hosted Zone
  • Enter the Domain name
*You'll need to set the dns entries for your domain name to point to the four domains listed under Delegation set
  • Click create record set
  • Change TYPE to A Name and enter the two elastic IP addresses above

Results

We have a very simple aws server which is redundant, I've produced a quick video to show the result. http://www.youtube.com/watch?v=uVElQXMBQQM If you're interested in following this experiment further please enter your email below.