Can someone help me figure out an efficient auto scaling configuration? [closed]

This is my first time releasing a web app. I'm going to using Django with Nginx and a couple of other scripts that have been piped. I wanted to know which auto scaling strategy I can use.

Right now, I'm playing around with the free EC2 micro instance. Works well.

I'm not sure if I can afford a dedicated RDS. I'm looking for the most cost efficient configuration. I was thinking of auto scaling with micro instances that have been setup with Load balancer but I haven't figured out how to sync the database in all the instances.

I'm also thinking of other alternatives like App Engine and Heroku but I don't think it'll give me VM like freedom. Is there a PaaS where a normal VM can be auto scaled without much worry?

Also, it there some kind of chart that can approximately tell me how much traffic Micro, Small, etc instances can each withstand.

Can someone shed some light?


Solution 1:

Scaling an application is something that you must design your application to be able to do - regardless of the platform.

Some considerations include:

  • Making files (e.g. uploads, source code changes, etc) available to all nodes
  • Sharing session information between all nodes
  • Replicating your database across multiple nodes
  • Determining the health of nodes and when to bring up new nodes

I would suggest that the best approach is to first offload your database to another instance. If your databases and application run on different instances, you can scale each independently, and will have a much easier time of managing the problem. (See this article - a bit old, but no less valid).

Secondly, you want to scale up and out. With EC2, you get much better performance from the larger instance types - in terms of performance, a small instance is better than 3 micro instances. My suggestion would be to scale out to two nodes (for failover), and then start switching your nodes for larger instance types before you continue to scale out (on a more permanent basis). By all means, though, keep auto-scaling functional so that your application can handle additional load at any time.

Scale your databases separately - typically your application will require more nodes than your databases (you databases may benefit from higher memory instances). Also keep in mind that RDS does not do the scaling for you.

Amazon doesn't provide a chart of 'traffic' - because that is completely dependent on your application (a highly dynamic application that is processor intensive can serve far fewer requests than one delivering a static page on the same hardware). It does, however, provide a somewhat 'subjective' comparison here. One point worth highlighting is 'I/O Performance'. This descriptor includes network bandwidth and disk i/o. The smaller instances are more susceptible to variation in performance (especially available bandwidth). Since EBS volumes require network bandwidth, this will also affect their performance.

As for micro instances - as soon as is merited by your application, move up to a small instance. You will find that whenever you 'burst' cpu on the micro, there is a subsequent penalty in performance (indicated by the 'steal' value from top). Other instances (that you do not own) can use significant amounts of your CPU on a micro instance).

It is also worth mentioning that you can set the size of an autoscaling group to '1', which allows you to have an instance relaunched if it becomes unavailable. (The problem that arises though, is getting your current data back on that new instance, since it launches from a snapshot).

If you can use MySQL cluster (it uses a different storage engine - ndbcluster) or a NoSQL solution with sharding, you will have a much easier time auto-scaling your databases than using traditional Master-Slave replication in MySQL. (There is another solution that has reportedly seen some success, but I probably wouldn't advise at this point - using a distributed filesystem, specifically GlusterFS, to store your databases - the file system manages the file locking and distribution, and each instance accesses the databases as needed - this will run into problems as you add more instances, but may see some success with a 2 node database cluster).

A practical course of action therefore may be:

  1. Start with 1 micro instance which has both your database and application on it
    • Separate your database to a one instance and your application to a second instance
  2. Setup autoscaling on your application instance.
  3. Add a second application node
  4. Add a second database node and configure replication between your nodes (if you opt to use MySQL cluster, or NoSQL solutions, you should be able to setup autoscaling as well).
  5. Upgrade one instance at a time to larger instance sizes as demand merits it

(You should find that for most sites 2 of the bigger instances are more than enough to run your database, especially if you implement caching correctly, but adding an additional slave as needed shouldn't be too troublesome).

The above course of action addresses scaling fairly well, but it does have a single point of failure until step 4 (i.e. if you database node fails, your application goes down). A much more difficult setup, but a more resilient one, would see you have both your application and database on the same node, then setup two copies of that node with MySQL replication (and MySQL proxy to handle requests from the load balancer) - you would need to manage failover on your own (with something like Heartbeat/Pacemaker) and then go directly to 4 nodes (2 database, 2 application).