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.
To deploy this virtual infrastructure we will use the following components:
and the following outstanding characteristics:
The graphic above shows:
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.
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:
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.
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.