Scaling out Web Servers to Amazon EC2

This use case illustrates how to deploy an elastic web application using a virtual infrastructure managed by OpenNebula. In order to achieve this we will deploy a load balancer that acts as a master node of this elastic web application. Behind the load balancer there are slave nodes configured with a copy of the web application, for the requests to be redirected (proxyed) to them. The capacity (requests per second) of the elastic web application can be dynamically increased or decreased by respectively booting or shutting-down virtual instances that act as nodes of the web application load balancer.

As part of this use case, it will be shown how to use remote (EC2) nodes to attend requests whenever the local infrastructure (virtualized using XEN) saturates.

Architecture

To deploy this virtual infrastructure we will use the following components:

  • A Nginx Server configured as load balancer, to spread the requests among the web servers.
  • Nginx Servers configured as web servers (nodes of the load balancer), executed on virtual machines. These servers will provide the capacity for this use case.

and the following outstanding characteristics:

  • The virtual machines running the web servers can be either local (running atop Xen hypervisor in the local infrastructure) or remote (running as EC2 instances).
  • The management (monitorization, deployment, migration, etc) of the virtual machines is done through OpenNebula.

The graphic above shows:

  • green arrows for the web requests made by the clients to the load balancer
  • red arrows for the proxyed requests from the load balancer to the web servers
  • orange arrows for the monitorization and management actions executed by the virtual machine manager (OpenNebula).

This infrastructure has failure tolerance, high availability and elasticity provided by the dynamic deployment of new virtual web servers added to the load balancer. It is effectively a virtual infrastructure that can be resized on demand thanks to OpenNebula, which simplifies the management of two different virtualization technologies (Xen and EC2), by, for example, allowing the administrator to get information related to the consumption of physical resources of both remote and local instances.

Configuration

First we need to install and configure OpenNebula for the deployment of this virtual infrastructure. Also, we need Nginx installed on the machines that will be the load balancer and the web servers. In order to get this working, our advice is to follow the steps described in the following installation and configuration document

To configure the load balancer follow the above same steps, but use the following configuration file instead, where we define which is the host that is going to perform the load balancing and what selection method we have chosen (round-robin or weighted).

lgonzalez@machine:one$ vim nginx.conf

user www-data;
worker_processes  1;
error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    access_log  /var/log/nginx/access.log;
    sendfile        on;
    keepalive_timeout  65;
    tcp_nodelay        on;
    gzip  on;
    server {
        listen       80;
        server_name  localhost;
        access_log  /var/log/nginx/localhost.access.log;
        location / {
            proxy_pass http://one_loadbalancer;
        }
    }
    upstream one_loadbalancer {
            server 10.1.1.11:80 ;
            server 10.1.1.22:80 ;
            server 10.1.1.33:80 ;
            server 10.1.1.44:80 ;
   }
}

The section upstream of this configuration file defines the nodes that will be used to load balance all the requests being made, so you need to change this according to the number of virtual web servers that you want included into the elastic web application. In our use case, the local web server nodes have the following IPs : 10.1.1.11, 10.1.1.22, 10.1.1.33 and 10.1.1.44. So we can just add four local nodes, but just adding more IP addresses to the upstream list and cloning and configuring the local images will get us pass this limit.

Please note that the load balancer (which is also the front-end for the web application) has:

  • one private IP address (10.1.1.99 in our case) to communicate with the nodes in the private network, and
  • one public IP address to communicate with the web clients and with the EC2 instances.

The EC2 instances have public IPs addresses and communicate with OpenNebula and the load balancer over the internet.

To configure OpenNebula to interface EC2 and to be able to deploy the instances with Nginx the next steps should be followed:

Now we have to create the templates for both local and remote machines. For the load balancer we use this template:

lgonzalez@machine:one$ cat xen.loadbalancer
CPU      = 0.5
MEMORY   = 128
OS       = [kernel="/boot/vmlinuz",initrd= "/boot/initrd",root="sda1" ]
DISK     = [source="/images/loadbalancer.disk",target="sda",readonly="no"]

and a similar template for local machines:

lgonzalez@machine:one$ cat xen.local01
CPU      = 0.5
MEMORY   = 128
OS       = [kernel="/boot/vmlinuz",initrd= "/boot/initrd",root="sda1" ]
DISK     = [source="/images/local01.disk",target="sda",readonly="no"]

Change paths to images and kernel accordingly. We can clone the images and create as many local nodes as we need.

This template is used for remote machines (on EC2):

lgonzalez@machine:one$ cat ec2.template

CPU=1
MEMORY=1700
EC2=[ 
        AMI="ami-yao044b1", 
        KEYPAIR="gsg-keypair", 
        INSTANCETYPE="m1.small", 
        AUTHORIZED_PORTS="22-25" 
    ]
REQUIREMENTS = 'HOSTNAME = "ec2"'

You should change AMI identifier, key-pair, memory, etc accordingly.

Deploying and Testing

Let's initialize the virtual cluster. We first initiate the OpenNebula daemon, and add one host to its list of resources afterwards, by means of the onehost command.

lgonzalez@machine:one$ one start
oned and scheduler started
lgonzalez@machine:one$ onehost create ec2 im_ec2 vmm_ec2
lgonzalez@machine:one$ onehost create ursa03 im_xen vmm_xen

Then we submit the virtual machines using the load balancer template and the desired amount of local web sever and ec2 templates, using the onevm command as in:

lgonzalez@machine:one$ onevm create xen.loadbalancer
ID: 0
lgonzalez@machine:one$ onevm create xen.local01
ID: 1
lgonzalez@machine:one$ onevm create xen.local02
ID: 2
lgonzalez@machine:one$ onevm create xen.local03
ID: 3
lgonzalez@machine:one$ onevm create xen.local04
ID: 4

lgonzalez@machine:one$ onevm create ec2.template
ID: 5
lgonzalez@machine:one$ onevm create ec2.template
ID: 6
lgonzalez@machine:one$ onevm create ec2.template
ID: 7
lgonzalez@machine:one$ onevm create ec2.template
ID: 8

Now we check the status of all the instances with the onevm command:

lgonzalez@machine:one$ onevm list
  ID     NAME STAT CPU     MEM        HOSTNAME        TIME
   0    one-0 runn  12     512          ursa03 00 00:01:15
   1    one-1 runn   8     512          ursa03 00 00:01:11
   2    one-2 runn  10     512          ursa03 00 00:01:10
   3    one-3 runn  11     512          ursa03 00 00:01:02
   4    one-4 runn  23     512          ursa03 00 00:00:51
   5    one-5 runn   0     512             ec2 00 00:00:48
   6    one-6 runn   0     512             ec2 00 00:00:48
   7    one-7 runn   0     512             ec2 00 00:00:45
   8    one-7 runn   0     512             ec2 00 00:00:43

Once we have all the machines running, our load balancer is almost ready to start serving content. First we need to add the IP address of all the machines to its /etc/nginx/nginx.conf, which is the configuration file that tells the Nginx load balancer software which machines (identified by their IP addresses) are prepared to act as nodes, serving the same web application. Creating a script that updates this file automatically according to the instances currently running with OpenNebula is a nearly trivial task.

At any time we could add more capacity to this elastic web application by submitting more local or EC2 nodes by simply sending the xen.localXX or the ec2.template to OpenNebula, and updating the loadbalancer configuration file. A Service Manager could be developed to automatically add new nodes to the virtual cluster in order to meet specific Service Level Objectives.