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.

Found this page Googling for help? You’ll probably want to jump straight to the step by step guide.

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, Postgresql 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.

The stack will be split into two sections, a dumb side will take care of rendering and displaying the data to user, and a clever side which will take of performing complex data manipulation.

My first attempt at designing the architecture is as follows:

This diagram is subject to change and I’d love to get feedback on improvements or other suggestions.

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

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

One step further down and we’re into the clever parts of the application, these consist of a collection of web services. These can either be stand alone instances or several combined applications running on one instance, the important part is that during deployment the web services are kept in synchronization across zones.

The final part of the application are the database servers which will be split across zones and keep in synchronization via Postgresqls built in replication.

Putting the dumb part together

This section will be a quick step by step guide on how I put the dumb side of this highly available architecture 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

Paste the following

description “node.js front end server”
author “kvz”

start on startup
stop on shutdown

script
# We found $HOME is needed. Without it, we ran into problems
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

*If you get an unknown job error here check the ” have been pasted correctly.

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 redunant, I’ve produced a quick screencast to show the result.

If you’re interested in following this experiment further please enter your email below.


Feedback / comments / suggestions / improvements are always welcomed.

Posted

by & filed under AWS, SysOps

Leave a Reply

(will not be published)