It almost feels like science fiction to be able to spin up a powerful VM in seconds, use it for an hour, and terminate it, spending just pennies in the process. At the same time, there are enough options and complexity with EC2 that certain facets are complicated at best, and baffling at worst. I've put together a few lessons learned for the bold folks looking to join me in an EC2 wonderland.
Community AMIs are wonderful. Ubuntu is my Linux distro of choice, but the only Amazon Machine Images offered for Linux are Redhat Enterprise, Suse Enterprise, and Amazon Linux. (Don't be confused by the Amazon Linux distro; it's a secure version of Redhat optimized for AWS.) Are we Ubuntu fans hopelessly hosed? Nope. There are also a wide variety of community AMIs (over 6000!), including official Ubuntu images. Just make sure you choose the right image; there's a lot to choose from, with images for alphas, betas, and release candidates.
Watch where your data goes. Upon launching an EC2 instance, you absolutely must check the size of your partitions. A Linux instance will typically launch with a relatively small root partition (/) of around 10GB, and then a gigantic partition mounted from an ephemeral drive. If you attempt to persist all your data under your root partition, you will run out of space very quickly. Locate your big directories accordingly; I put rapidly-expanding directories like logs, db data, and my collection of Bieber jams on the giant partition.
EBS is the only way to go. An EC2 instance can either boot from the local instance store or from an Elastic Block Storage snapshot. Simply put, I have no idea why you would want to use instance-store. EBS instances allow for vastly quicker backups and restores, they can be paused and resumed, they don't lose their instance storage on a crash (for the root partition, at least), and they scale much faster, since you can quickly spin up new instances based off a snapshot.
Internal IPs rule. Each EC2 instance has a public hostname (ec2-127-0-0-1.compute-1.amazonaws.com), a private hostname (ip-127-0-0-1.ec2.internal), and a private IP address. When instances must communicate with one another, use private IP addresses; any alternative requires either a ton of typing or an unhealthy amount of firewall rejiggering. I also find it very useful to define a bunch of my own hostname aliases inside of /etc/hosts for these private IP addresses.
Micro instances are beautiful for experimentation. I love how cheaply I can test complicated environment changes via EC2. This has become even more compelling recently, with Amazon announcing their Free Usage tier. Included in this free tier is 750 usage hours of a micro instance. Micro instances aren't too powerful, but they work very well for limited-use testing, like architecture spikes or emergency recovery scenarios. Even if you do exceed the free usage on a micro instance, the actual cost is only a couple of cents per hour.
Termination protection protect you from your own idiocy. It's easy to get carried away with creating and terminating new EC2 instances, especially if you're as excitable as I am. On more than one occasion, I've attempted to accidentally terminate the wrong instance. You can block this from occurring by enabling Termination Protection on all of your important instances.
Multiple Availability Zones protect you from the fickle nature of the Amazon gods.
With EC2, Amazon has not only given us enough rope to hang ourselves with, but they've also given us enough rope to hang innocent bystanders, pets, and various bits of shrubbery. Despite that and the sheer amount of complexity you initially face, it's an incredibly powerful tool, particularly if you're on a budget.