Auto Scaling with Elastic Load Balancing

Along with the ability to Setup Elastic Load Balancing, which I showed you how to setup in my previous post. Amazon provides the ability to auto scale your instances. Auto Scaling groups allow you to set up groups of instances that will scale up and down depending on triggers you can create. For example you can set up a scaling group to always have 2 instances in it, and to scale up another server if the CPU utilization of the servers grows over a certain threshold. This is extremely helpful when you receive unexpected traffic and you are unable to react in time to add new instances. The beauty of Auto Scaling in conjunction with Elastic Load Balancing is that it will automatically assign the new instances to the load balancer you provide.

Creating an Auto Scaling Launch Config

The first step in setting up Auto Scaling is to create a launch config. The launch config is used to determine what ec2 image, and size (small, medium, etc) will be used to setup a new instance for your Auto Scaling group. To setup a launch config you will call the as-create-launch-config. For example to create a new launch config called auto-scaling-test that would launch the image ami-12345678 of size c1.medium you would run the following command:


as-create-launch-config auto-scaling-test --image-id ami-12345678 --instance-type c1.medium

Create an Auto Scaling Group

The next step to enabling Auto Scaling is to setup an Auto Scaling Group. An Auto Scaling group tells Amazon what zones you want your instances created in, the minimum and maximum number of instances to ever launch, and which launch config to utilize. To create an Auto Scaling group you will call the as-create-auto-scaling-group command. For example if you wanted to create a new group with a name of auto-scaling-test using the availability zones of us-east-1a with a minimum number of instances being 2 and a maximum of 4 using our newly created launch config you would run:


as-create-auto-scaling-group auto-scaling-test --availability-zones us-east-1a --launch-configuration auto-scaling-test --max-size 4 --min-size 2

When this command is executed 2 new instances will be created as per the directions of the launch config. the as-create-auto-scaling-group can also take be linked to a load balancer. Thus if we wanted to have this group setup with the load balancer we created in the previous article, you would run:


as-create-auto-scaling-group auto-scaling-test --availability-zones us-east-1a --launch-configuration auto-scaling-test --max-size 4 --min-size 2 --load-balancers test-balancer

After execution this would setup 2 new instances as per the instructions of the launch config, and register these instances with the load balancer test-balancer.

Creating Auto Scaling Triggers

Triggers are used by Auto Scaling to determine whether to launch or terminate instances within an Auto Scaling Group. To setup a trigger you will use the as-create-or-update-trigger command. Here is an example using the auto scaling group we created earlier:


as-create-or-update-trigger auto-scaling-test --auto-scaling-group auto-scaling-test --measure CPUUtilization --statistic Average --period 60 --breach-duration 120 --lower-threshold 30 --lower-breach-increment"=-1" --upper-threshold 60 --upper-breach-increment 2

Lets walk through what this command is doing. Basically what this command is saying is, create a new trigger called auto-scaling-test. This trigger should use the auto-scaling group called auto-scaling-test. It should measure the average CPU utilization of the current instances in the auto scaling group every 60 seconds. If the CPU utilization goes over 60% over the period of 120 seconds launch 2 new instances. Alternatively if the CPU utilization drops below 30% over the period of 120 seconds terminate 1 of the instances. Remember that the trigger will never terminate more instances than the minimum number of instances and it will not launch more instances than the maximum number of instances as defined in the Auto Scaling Group.

Shutting Down an Auto Scaling Group

Initially shutting down an Auto Scaling group can be a bit tricky as you cannot delete an Auto Scaling Group until all the instances are terminated or deregistered from the group. The best way to terminate an Auto Scaling group, it’s triggers and launch config is to do the following steps:

  • Delete all triggers
  • Update the Auto Scaling group to have a minimum and maximum number of instances of 0
  • Wait for the instances registered with the Auto Scaling group to be terminated
  • Delete the Auto Scaling group
  • Delete the launch config

To do this with the examples we used above we would issue the following commands:


as-delete-trigger auto-scaling-test --auto-scaling-group auto-scaling-test

as-update-auto-scaling-group auto-scaling-test --min-size 0 -max-size 0

as-delete-auto-scaling-group auto-scaling-test

as-delete-launch-config auto-scaling-test

With those 4 commands you can easily delete your Auto Scaling group as well as any launch configs or triggers that are associated with it.

Conclusion

Auto Scaling provides an easy and efficient way to grow and shrink your hosting solution based on your current traffic. In events where you are hit with unexpected traffic Auto Scaling can provide a failsafe by automatically launching new instances and scaling up your solution to meet this new traffic. When the traffic subsides Auto Scaling will scale down your solution so that you are not wasting money by running more instances than you require.

One thing to note is that if you know before hand that you will be receiving a traffic spike at a specific time, it may be more benefitial to launch new instances manually before the spike. This will save your system from getting hammered before having the Auto Scaling launches new instances to cope with the additional load. If you rely on Auto Scaling alone in this scenario you could see many requests at the start of the heavy traffic timeout or fail as the minimum number of instances likely won’t be able to handle the traffic load.

Load Balancing with Amazon Web Services

In my previous post I talked about load balancing with HAProxy. In this post I am going to discuss load balancing with Amazon Web Services, using Elastic Load Balancing.

Elastic Load Balancing vs HAProxy

Elastic Load Balancing (ELB) was introduced by Amazon Web Services in May of 2009. Elastic Load Balancing distributes traffic across multiple EC2 instances and scales up as your traffic increases. This all sounds like a perfect solution for your load balancing. However it does present a few issues. The rate at which ELB scales up is often a little slow. This means that if your website typically does not get a lot of traffic, when it does it a giant spike it will likely take the load balancer some time to catch up to the demand of the new traffic. If your traffic increases are more gradual however, ELB appears to scale up a lot smoother. For more information on tests of Elastic Load Balancing’s performance see this article:

http://agiletesting.blogspot.com/2010/04/load-balancing-in-cloud-whitepaper-by.html

HAProxy on the other hand will handle large traffic spikes very handily. In addition HAProxy gives you the power to fine tune your load balancing, as well as additional features such as error pages, real time statistics, and the use of acl’s. However not everyone requires these features, so you will need to decide for yourself if you want to go with the easy solution, or the more robust route. I will describe how you can setup Elastic Load Balancing, as well as how to auto scale with ELB or by using HAProxy.

Setting Up Elastic Load Balancing

Setting up Elastic Load Balancing is as easy as running a single command using the Amazon API Tools. To create a new load balancer you will run the elb-create-lb command. When you run the command you will specify the name of the new load balancer, the availability zones you want to use, the incoming port and the protocol to use for it, and the port the traffic should be sent to on the instance. For example if we want to create a new load balancer called test-balancer, in the us-east-1a zone, that is listening on port 80 for http traffic, and will send traffic to port 80 on our instances we would run:


elb-create-lb test-balancer --availability-zones us-east-1a --listener "lb-port=80,instance-port=80,protocol=http"

Executing this command will return the DNS name of the new load balancer that was created. You will use this DNS name to point traffic to so that it gets distributed by your load balancing. Unfortunately the recommended way to point this traffic is via a DNS CNAME. The reason this is a problem is that you cannot use a CNAME with a root domain. For example I would not be able to point kloppmagic.ca to the load balancer. I could however point www.kloppmagic.ca. Using a sub domain appears to be the common work around people are utilizing. The other option is to do a lookup of the DNS name returned from the command and using the IP address. This approach you will constantly have to monitor the DNS name from Amazon however, as they are not utilizing static IP’s for load balancing.

Once you have load balancer setup you will need to associate running EC2 instances with the load balancer. To do this you will run the command elb-register-instances-with-lb. This command allows you to register an instance with a specific load balancer. For example if we had 2 instances with instance id’s of i-123456 and i-123457 that you wanted to associate with the test-balancer load balancer you would run:


elb-register-instances-with-lb test-balancer --instances i-123456 i-123457

In the same manor you can use the elb-deregister-instances-with-lb to remove instances from a given load balancer. Finally if you wish to view all the load balancers you currently have setup you can utilize the elb-describe-lbs

Ultimate it is that easy to setup load balancing with Amazon Web Services. If you do not require all the features of HAProxy, and want something quick and easy to setup, Elastic Load Balancing cannot be beat.

Resyncing a Slave to a Master in MySQL with Amazon Web Services

My latest blog post on Resyncing a Slave to a Master in MySQL made me think of how I could achieve the same result in the cloud using amazon web services (AWS). Of note, the previous guide would work just fine in the cloud to resync a slave and a master, however there is an alternative way using the tools the AWS provides.

Lets assume that in the cloud we had two ec2 instances setup running mysql in a master slave configuration, and that each server was using Elastic Block Storage (EBS). Essentially the procedure would be very similar, apart from the transfer of data from one machine to the other.

Amazon Web Services provides the ability to create snapshots of an EBS volume. Creating a snapshot is quick, and once it has been created, you can mount the snapshot on any of your instances. This makes the backup portion even easier.

From my previous article you would proceed with steps 1-6. Then instead of step 7 you would first create a snapshot of the slaves EBS volume. You can either do this via the firefox ElasticFox plugin or the command line tools as follows:

ec2-create-snapshot VOLUME_ID -d "Mysql snapshot for resync of slaves"

Once the snapshot is created you then need to create a new volume for the snapshot. Again in ElasticFox this is as easy as right clicking the snapshot and selecting “create a new volume from this snapshot”. From command line:

ec2-create-volume --snapshot SNAPSHOT_ID -z ZONE

Finally our last step is to attach this volume to the master MySQL instance and mount it. In ElasticFox you right click the new volume and select “attach this volume”. From command line you would run:

ec2-attach-volume VOLUME_ID -i INSTANCE_ID -d DEVICE

Once the volume is attached you can them mount it on the master server to a temporary folder, copy over all of the folders you need to the mysql directory, then proceed with step 8 of my previous guide. When everything is working correctly you can then unmount the newly created volume from the instance, and delete it.

Overall the two approaches are very similar, and both will work. File transfer between instances in the cloud is extremely quick, however so is creating new snapshots and attaching them to instances. Ultimately it is up to you to decide which route to take.