I am going to orient this answer as if the question was "what are the advantages of chef-solo" because that's the best way I know to cover the differences between the approaches.
My summary recommendation is in line with others: use a chef-server if you need to manage a dynamic, virtualized environment where you will be adding and removing nodes often. A chef server is also a good CMDB, if you need one. Use chef-solo if you have a less dynamic environment where the nodes won't change too often but the roles and recipes will. Size and complexity of your environment is more or less irrelevant. Both approaches scale very well.
If you deploy chef-solo, use a cronjob with rsync, 'git pull', or some other idempotent file transfer mechanism to maintain a full copy of the chef repository on each node. The cronjob should be easily configurable to (a) not run at all and (b) run, but without syncing the local repository. Add a nodes/ directory in your chef repository with a json file for each node. Your cronjob can be as sophisticated as you wish in terms of identifying the right nodefile (though I would recommend simply $(hostname -s).json. You also may want to create an opscode account and configure a client with hosted chef, if for no other reason than to be able to use knife to download community cookbooks and create skeletons.
There are several advantages to this approach, besides the obvious "not having to administer a server". Your source control will be the final arbiter of all configuration changes, the repository will include all nodes and runlists, and each server being fully independent facilitates some convenient testing scenarios.
Chef-server introduces a hole where you use the "knife upload" to update a cookbook, and you must patch this hole yourself (such as with a post-commit hook) or risk site changes being overwritten silently by someone who "knife upload"s an obsolete recipe from the outdated local repository on his laptop. This is less likely to happen with chef-solo, as all changes will be synced to servers directly from the master repository. The issue here is discipline and number of collaborators. If you're a solo developer or a very small team, uploading cookbooks via the API is not very risky. In a larger team it can be if you don't put good controls in place.
Additionally, with chef-solo you can store all your nodes' roles, custom attributes and runlists as node.json files in your main chef repository. With chef-server, roles and runlists are modified on the fly using the API. With chef-solo, you can track this information in revision control. This is where the conflict between static and dynamic environments can be clearly seen. If your list of nodes (no matter how long it might be) doesn't change often, having this data in revision control is very useful. On the other hand, if you're frequently spawning new nodes and destroying old ones (never to see their hostname or fqdn again) keeping it all in revision control is just an unnecessary hassle, and having an API to make changes is very convenient. Chef-server has a whole features geared towards managing dynamic cloud environments as well, like the name option on "knife bootstrap" which lets you replace fqdn as the default way to identify a node. But in a static environment those features are of limited value, especially compared to having the roles and runlists in revision control with everything else.
Finally, recipe test environments can be set up on the fly for almost no extra work. You can disable the cronjobs running on a server and make changes directly to its local repository. You can test the changes by running chef-solo and you will see exactly how the server will configure itself in production. Once everything is tested, you can check-in the changes and re-enable the local cronjobs. When writing recipes, though, you wouldn't be able to use the "Search" API, meaning that if you want to write dynamic recipes (eg loadbalancers) you will have to hack around this limitation, gathering the data from the json files in your nodes/ directory, which is likely to be less convenient and will lack some of the data available in the full CMDB. Once again, more dynamic environments will favor the database-driven approach, less dynamic environments will be fine with json files on local disk. In a server environment where a chef run must make API calls to a central database, you will be dependent on managing all testing environments within that database.
The last can also be used in emergencies. If you are troubleshooting a critical issue on production servers and solve it with a configuration change, you can make the change immediately on the server's repository then push it upstream to the master.
Those are the primary advantages of chef-solo. There are some others, like not having to administer a server or pay for hosted chef, but those are relatively minor concerns.
To sum up: If you are dynamic and highly virtualized, chef-server provides a number of great features (covered elsewhere) and most of the chef-solo advantages will be less noticeable. However there are some definite, often unmentioned advantages to chef-solo especially in more traditional environments. Note that being deployed on the cloud doesn't necessarily mean you have a dynamic environment. If you can't, for example, add more nodes to your system without releasing a new version of your software, you probably aren't dynamic. Finally, from a high-level perspective a CMDB can be useful for any number of things only tangentially related to system administration and configuration such as accounting and information-sharing between teams. Using chef-server might be worth it for that feature alone.
I don't use Elastic Beanstalk - but the guide you are following is for EC2 (which I can definitely help with). The first difficulty you have is that the guide you are using is for Ubuntu 9.10; Amazon's Linux is based on CentOS/RHEL - so you would have an easier time if you could find a CentOS 6 guide.
The root of your issue seems to stem from 'attaching an EBS volume'. On EC2 you can attach multiple EBS volumes to a single instance. All instances have a root volume - these can be either S3-backed or EBS-backed. By far, the preferred approach is to use an EBS backed root volume (it costs a bit more, but makes up for it in flexibility and durability). An instance with an EBS root volume will almost always have this volume attached as /dev/sda1 - on modern Linux systems, the device actually shows up as /dev/xvda1 (and it is the latter which should be passed to any commands). (Other than trying to format a mounted volume - you were trying to format your root file system with the instance running - i.e. you were trying to erase your operating system, definitely not a good idea, if it is even possible).
In this case, the suggestion is to add a second EBS volume - attach it to your instance (e.g. as /dev/sdh, but use /dev/xvdh for commands), and use that for storing your MySQL data. (Despite not using Elastic Beanstalk) I find it hard to believe that Elastic Beanstalk would not allow you to attach a second volume - as this functionality is fairly central to EC2.
You should be able to get a list of the EBS devices by running cat /proc/partitions
(or using fdisk -l
).
You will note that in step 5 of what you have done, you are actually mounting the root volume within itself (i.e. /dev/sda1 is already mounted as / and you are mounting /dev/sda1 as /ebsvol) - it is best to avoid doing that.
Also, while /etc/init.d/mysql stop
did not work, /etc/init.d/mysqld stop
probably would have worked. (Again, you can get a list of the init.d scripts by running ls /etc/init.d
- and should be able to use those paths, like you, I usually use the service
command though).
The MySQL databases should be in /var/lib/mysql - however, your mountpoints in /etc/fstab are probably incorrect (given the ebsvol within /ebsvol problem). When you cd /var/lib/mysql
you should be able to see your databases - if not your mounts haven't worked correctly. (Verify that /var/lib/mysql is mounted on a different device by mountpoint -d /var/lib/mysql
and compare the device to cat /proc/partitions
).
The basic ideas of the guide you are following are quite valid - it is common practise to put your data and databases on a different EBS volume than your root volume, as it offers numerous advantages (performance, ease of snapshotting, easier to move between instances, etc.), and the basic Linux commands haven't changed - they are just for a Ubuntu.
Undo your mounts with umount /path
- just like you normally would, of course, you will need to ensure that the device is not busy (which may not be a problem if you haven't managed to start MySQL). umount is only temporary though - so you will have to edit /etc/fstab
and remove any references to the mount points from there also. If you don't have anything of value on the instance, you might be better off starting over (not because it is difficult to unmount a few volumes, but rather because it is always easier to figure out where you went wrong when you start from a known state).
Finally, with regard to MySQL on Elastic Beanstalk: the point of Elastic Beanstalk is supposed to be that it handles provisioning of resources and scaling automatically - it is still based on the core AWS components (e.g. EC2, S3, ELB, etc) but it will do some things for you. Elastic Beanstalk usually uses RDS to handle MySQL databases. RDS is an Amazon managed version of MySQL which simplifies the provisioning and scaling of MySQL instances. Keep in mind that MySQL doesn't lend itself well to autoscaling without a lot of setup. You can't just launch a second MySQL instance and have the load split between your two instances - you need to setup replication, which may not be a simple task).
Essentially, if you are able to setup MySQL in such a way that it runs from your web server instances and can autoscale seamlessly, you'd almost certainly be better off using EC2 directly and not bothering with Elastic Beanstalk. I'd suggest therefore, the most people don't actually setup MySQL on Elastic Beanstalk (what you could do is setup a separate MySQL instance, but if you are using Beanstalk, RDS is probably a simpler approach).
Edit:
Unlike a lot of other services that operate mostly as a black box, Elastic Beanstalk does give you access to the underlying components. That said, if you are going to go through the effort of setting up your EC2 instances manually, you have negated the point of Elastic Beanstalk.
If you are using EC2, there are few approaches to PHP/MySQL:
- You can host both your webserver and database on a single instance - when you are starting out, this can be a reasonable approach, however, it doesn't scale horizontally very well (but you can still scale vertically - using larger instances). Hopefully by the time you exceed the capacity of the x-large instances, you will be in a position to setup a more complex setup. That said, it is bad for redundancy - everything is on that single instance, and a failure of any component takes down your whole setup.
- You can host your webserver on one instance, and use RDS for your database. Most well designed applications will tax the web server more than the database (and the database load will ideally be read-biased). In such a scenario, you can scale your web server instances relatively easily (e.g. by putting them behind an ELB - with just a bit of effort to ensure that all are serving the same content). RDS is MySQL managed by AWS - it isn't quite fully automatic, but it does go a long way towards autoscaling. Essentially, RDS will provision multiple read-only slaves, and a single write-master, with multiple hot-backups that can take over if you need. The downside is that you are paying for all those instances that are running (and you don't have full control over some of the intricate settings of MySQL).
- The final approach would be to use your web server cluster and your own MySQL cluster. Essentially, you can scale your web instances (as above), and then you will setup MySQL instances that will scale separately. You will need to look into MySQL replication (or perhaps use MySQL cluster if you can adapt your application to its data structures).
A few other answers on the same topic:
My perspective is usually that one click solutions aren't the best approach - I like the control that is offered by doing something manually. I find that not only do I usually end up with a more tailored and efficient end result, but I also have a much better understanding of how the system works, which makes figuring out what is wrong much easier. You can always automate your own setups once you have a good understanding of the intricacies of them.
One point to keep in mind about RDS - it is already EBS backed. RDS is MySQL - it isn't something similar, or another relational database. It is a managed instance of MySQL running on EBS backed EC2 instances. AWS will keep the software up to date, and you can do normal EBS snapshots of your data, etc. You just don't have direct access to the underlying software running on the instance.
As for the choice of operating system, I am partial to Amazon's Linux. It is well supported by AWS and uses a minimum of resources - it is fully compatible with CentOS (as a matter of fact, it includes the EPEL repository by default in the latest version). The usual viewpoint is to use whatever Linux distribution you are comfortable with, as the differences are usually minor (CentOS will work just as well as Ubuntu for the instructions you are working from - most commands (except apt-get) are the same on CentOS. Given that my own setup has the databases on a separate EBS volume using Amazon's Linux, I can assure you that it is not difficult to do).
I'd suggest that there are some main considerations:
- Comfortability with/willingness to learn Linux systems - if you don't mind setting up your own servers and want to get a better understanding of them, I'd definitely go the EC2 route. You'll end up with a better end result if you do it right and will have more versatility in the long run. I will mention though, that if you are taking this approach, you want to really understand what the commands you are running do - just following a guide will not be enough if you really want to commit to it.
- Budget - remember that with AWS everything has a price. The more AWS does for you, the more they charge you. An RDS instance costs about 30% more than an equivalent EC2 instance (and there is not micro instance) and if you want the redundancy they offer, you need to be running multiple RDS instances (and paying for each of those). Elastic Beanstalk will provision instances, load balancers, RDS instances, etc. for you - the costs add up quickly.
- Time - if you have no time, want to press a couple of buttons and have something functional, Elastic Beanstalk is probably the best approach for you.
I would advise against using Elastic Beanstalk with MySQL baked into your AMI - it will likely be quite unstable, if it works at all. (Just think about what happens when it adds and removes an instance to you cluster, or when data goes to one instance instead of the other...)
It is great to keep scalability in mind - but don't optimize things too soon, or you will never get anything done. Definitely keep it in mind, but if the cost (time, money, etc.) of making a particular component scalable is not practical at the moment, don't worry too much about it - when the time comes to scale it, you'll figure it out (most popular sites started out that way, afterall).
I'd advise that if your application is designed so that it can take advantage of some caching, it will go a long way.
Typically, on EC2 it is better to scale vertically (to larger instances) than horizontally (to more instances). To begin with however, you want to scale to two instances so that you have some redundancy and minimize your single points of failure. A possible approach, therefore, may be:
- Start with a micro instance - have both your database and application on it (you can't get any smaller than this, which makes it a good starting point).
- This is of course, quite easy to scale vertically, just keep upgrading your instance until you are using x-large instances. The problem comes down to redundancy - if there is any problem with your instance, your application is offline.
- Now, you usually want to separate of your database to another instance (since a) the database will see different load than your application and b) you can't autoscale MySQL in quite the same way as web servers), but micro instances just don't handle load well, so I'd suggest upgrading to a larger instance first, at least a small, and then, perhaps a medium (basically, the idea is that once you need larger instance types, the effect is presumably greater)
- Separate your database from your web server. This will allow you to cater to the different needs for databases (e.g. high memory) vs web servers (e.g. higher cpu) and the differences between how you scale each (Recommended reading). At this point you might decide to use RDS instead of running your own MySQL instance.
- Now that you have your application running on a dedicated instance, you can scale it and not worry about your database - setup autoscaling so that you have some redundancy. This should automatically add more application nodes as any of them fail or as load exceeds the thresholds you specify.
- 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). Everything should at this point have redundancy, and even if a node fails, you should still be online.
- Upgrade one instance at a time to larger instance sizes as demand merits it.
Best Answer
I've evaluated Elastic Beanstalk in addition to other AWS offerings while trying to improve our hand-rolled AWS instances. The reasons I chose not to use it were due to complications that would arrise migrating my existing application and not with the offering itself. The catch is that you don't have as much control about application deployment / configuration of the servers. If you are starting a new application then it may be helpful to not deal with those things right now, if you have an existing application then it is more of a challenge to fit in the Beanstalk model.
Beanstalk provides a similar offering to Heroku and other PaaS vendors but not much of a benefit to those who just want to focus on making their application. You do at least get to determine the virtualized resources to a greater degree than other PaaS vendors.
Problems that I was running into with my application(s):
Git based deployments - I love them but our repo is 1+ GB. Rather large to push on a regular basis. This repo also contains about 40 applications (which really should be split) but that would take some time. Uploading any sort of package could work but most of our applications would take a large amount of work to make it into a package.
Integration with other services - From what I've seen Beanstalk sort of assumes that anything you are connecting to is a single service. This works well if your services are behind and ELB but our were separate nodes that we hit through HAProxy running on each application server. If you are running your datastores and other services as a single endpoint, you should be fine.
In my evaluation I also included OpsWorks and CloudFormation. OpsWorks has similar integration issues with how existing automation was working for these applications. CloudFormation didn't do much more than what some Python scripts and Chef were already taking care of for us.
I wound up choosing to use AWS Autoscaling Groups instead with some automation provided by Asgard. This was the smallest change to existing configuration/application code and provided us with the benefits we were looking for, simple management of multiple servers available through the AWS API.
The restrictions put in place by Elastic Beanstalk on your application are very helpful. You will have to make sure that your application is mostly stateless, provides an endpoint for a service, and relies on other services for state. If you are trying to make reusable stand-alone services that multiple applications in Beanstalk is a great start.
If/when you get to the point of wanting more configuration OpsWorks is a great next step. The predefined roles should make the transition easy to start with and it provides an automation framework around Chef to help coordinate provisioning of multiple servers.