AWS CloudFormation: BeanStalk with custom stacks
aws.amazon.com
aws.amazon.com
tl;dr - "price is in the same order of magnitude, but performance is two to three orders of magnitude different."
It's easier to design for scale-out than one might think; a great resource to get started is http://highscalability.com.
Regarding EBS, I haven't seen the hangup issue you've described. Any data?
As for low inter-node latencies, Amazon has an offering that specifically addresses that need: http://aws.amazon.com/ec2/hpc-applications/
Overall, I think Amazon is making a lot of inroads in areas with specific hardware demands. They just launched GPU compute options, and I expect we'll even see SSDs soon.
I'm the sysadmin (not the dba) for a website that does 30K http req/s at the edge, and our mysql cluster does about 3000 req/s during mid-day with most queries in the 1 - 5ms range.
Highscalability is a terrible place to get started, its a great place to share notes but if you get started there you will waste insane amounts of time on architecture astronaut nonsense.
I agree with nethergoat in that if you need low latency communication between ec2 instances that you should be using their hpc instances with faster/optomized ethernet.
I however disagree with nethergoat and agree with cagenut and think that the vast-majority of applications still currently depend more on a scale up paradigm. That is slowly moving towards scale out as people/businesses see its benefits and AWS is catering to this trend.
"UserData" : { "Fn::Base64" : { "Fn::Join" : [ "\n", [ { "Fn::Join" : [ "=", [ "dbName", { "Ref" : "WordPressDBName" } ] ] }, { "Fn::Join" : [ "=", [ "dbUser", { "Ref" : "WordPressUser" } ] ] }, { "Fn::Join" : [ "=", [ "dbPassword", { "Ref" : "WordPressPwd" } ] ] }, { "Fn::Join" : [ "=", [ "dbHost", { "Fn::GetAtt" : [ "WordPressDB" , "Endpoint.Address" ] } ] ] }, { "Fn::Join" : [ "=", [ "dnsName", { "Fn::GetAtt" : [ "WordPressELB" , "DNSName" ] } ] ] } ] ] } }
Certainly not the nicest syntax, but I guess it gets the job done.
UserData: Base64("dbName=$WordPressDBName\ndbUser=$WordPressUser\n...")
I'll give Amazon the benefit of the doubt and assume they just didn't want to impose a syntax, not that they think humans should be writing JSON like that.https://s3.amazonaws.com/cloudformation-templates/CloudForma...
Amazon guys trying to reinvent JS in JSON:
"WordPressLaunchConfig" : {
"Type" : "AWS::AutoScaling::LaunchConfiguration",
"Properties" : {
"ImageId" : "ami-16668c7f",
"SecurityGroups" : [ { "Ref" : "WordPressEC2Security" } ],
"UserData" : { "Fn::Base64" : { "Fn::Join" : [ "\n", [ { "Fn::Join" : [ "=", [ "dbName", { "Ref" : "WordPressDBName" } ] ] }, { "Fn::Join" : [ "=", [ "dbUser", { "Ref" : "WordPressUser" } ] ] }, { "Fn::Join" : [ "=", [ "dbPassword", { "Ref" : "WordPressPwd" } ] ] }, { "Fn::Join" : [ "=", [ "dbHost", { "Fn::GetAtt" : [ "WordPressDB" , "Endpoint.Address" ] } ] ] }, { "Fn::Join" : [ "=", [ "dnsName", { "Fn::GetAtt" : [ "WordPressELB" , "DNSName" ] } ] ] } ] ] } },
"InstanceType" : { "Ref" : "InstanceType" }
}
},
After some identation cleanup: { "Fn::Base64" :
{ "Fn::Join" :
[ "\n", [
{ "Fn::Join" : [ "=", [ "dbName", { "Ref" : "WordPressDBName" } ] ] },
{ "Fn::Join" : [ "=", [ "dbUser", { "Ref" : "WordPressUser" } ] ] },
{ "Fn::Join" : [ "=", [ "dbPassword", { "Ref" : "WordPressPwd" } ] ] },
{ "Fn::Join" : [ "=", [ "dbHost", { "Fn::GetAtt" : [ "WordPressDB" , "Endpoint.Address" ] } ] ] },
{ "Fn::Join" : [ "=", [ "dnsName", { "Fn::GetAtt" : [ "WordPressELB" , "DNSName" ] } ] ] }
] ]
}
}
DSL like this would be much more readable and maintainable: base64(<<<USERDATA
dbName=$WordPressDBName
dbUser=$WordPressUser
dbPassword=$WordPressPwd
dbHost=${GetAtt("WordPressDB","Endpoint.Address")}
dnsName=${GetAtt("WordPressELB","DNSName")}
USERDATA)
And this just a small example, I wander how complex this JSON will be for real-life cases.
Instead of reinventing Javascrict in JSON, they should have added some simple shell-like parameter substitution DSL (simple sigils) or allow some sand-boxed sanitized Javascript.Now I understand why tools like Chef/OpsCode using Ruby for this.
I've been using CloudFormation in conjunction with Chef - they're complementary tools, really.
Knife, a Chef management and interaction tool, provides several bootstrap scripts you could use as a starting point: https://github.com/opscode/chef/tree/master/chef/lib/chef/kn...
Let's use the Ubuntu 10.04 gem bootstrap script as an example (https://github.com/opscode/chef/blob/master/chef/lib/chef/kn...). The basic steps to use this with Chef would be:
(Note that this assumes you have a Chef server or are using the Opscode Platform. There's also a server-less option called "chef-solo" that you can use)
1. Create an appropriate first-boot.json to be used by the node(s). This will probably just be a "run_list" with entries like "role[app_server]" (function) and "role[production]" (environment).
2. Replace line 42 of the bootstrap script with your first-boot.json. Since this bootstrap script is actually a template, make sure to replace all other .erb stuff ("<%= %>") as appropriate.
3. JSON-encode the bootstrap script (handy tool: http://artur.ejsmont.org/blog/content/ultimate-web-encoder-d...)
4. Build your CF template, placing the JSON-encoded script in the "user data" section of your instance/auto-scaling group(s).
5. Instantiate your CF stack
If you'd like to use Chef for the entire lifecycle of your instances, just include a Chef recipe for running chef-client via cron every, say, 5 minutes. This allows changes to be propagated automatically in a pull style.
Done right, the end result is a complete, Chef-managed environment provisioned from bare metal using just one command.
CloudFormation might be a better way. Instead of having Puppet maintain the system, why not just update the CF template and spool up a new instance to replace the old, outdated one? I guess it just depends on how much you can stick in a template. If you can specify specific versions of packages (Ruby 1.9.2) it might just work.