29
Deploying Rails Applications on EC2 With help from Capistrano/Rubber

Deploying Rails on EC2 using Rubber (Slides and Notes)

Embed Size (px)

DESCRIPTION

My presentation on deploying rails applications with rubber on ec2 - Boston Ruby Group, 7/8/08

Citation preview

Page 1: Deploying Rails on EC2 using Rubber (Slides and Notes)

Deploying Rails Applications on EC2

With help from Capistrano/Rubber

Page 2: Deploying Rails on EC2 using Rubber (Slides and Notes)

About Me

• Matthew Conway

• Director of Engineering at SnapMyLife

• email: [email protected]

• twitter: mattconway

• github: wr0ngway

Page 3: Deploying Rails on EC2 using Rubber (Slides and Notes)

About SnapMyLife

• Mobile Photo Sharing Site

• http://snapmylife.com

• Deploys to EC2 with rubber/capistrano

• Approximately 10m pageviews/month

Page 4: Deploying Rails on EC2 using Rubber (Slides and Notes)

Those that went to RailsConf probably recognize my ploy to garner your affection.For the rest, this was a tip from Joel Spolsky’s keynote at RailsConfClaims that showing a pic of Angelina Jolie improves his presentation approval rating.

Page 5: Deploying Rails on EC2 using Rubber (Slides and Notes)

Rubyists turn me on!

Those that went to RailsConf probably recognize my ploy to garner your affection.For the rest, this was a tip from Joel Spolsky’s keynote at RailsConfClaims that showing a pic of Angelina Jolie improves his presentation approval rating.

Page 6: Deploying Rails on EC2 using Rubber (Slides and Notes)

Amazon Elastic Compute Cloud (EC2)• Hardware (virtual) as a service

• Scriptable cloud computing

• Have to assume all instances are transient (this has benefits!)

• Easy ami bundling for custom servers, support for static IPs, security groups

Page 7: Deploying Rails on EC2 using Rubber (Slides and Notes)

EC2 Problems

• Transient

• Redundancy

• Backups!

• Scripted instance construction for short downtimes while rebuilding

An instance could go away at any point in timeSolve this with redundant instancesTransience is a bug not a feature forces one to treat failures as imminent, which is a good assumption to make for a deployment scenarioWe’ve only had a single instance soft fail since Dec we were notified we probably should kill it as the H/W it was running on was badMention Availability zones lets one create a new instance with some guarantee that its not going to fail at the same time as some other group of instances.

Page 8: Deploying Rails on EC2 using Rubber (Slides and Notes)

EC2 Problems (cont.)

• DNS Issue

• Use elastic (static) ips for web/mail roles

• DNS round robin with a short TTL

• Monitor web instances from each other, remove from round robin if a failure

Even with redundancy, backups, we have some issuesWe haven’t done this yet, I’ll add it to rubber when I do Basically a monit script that firs off a request to nettica when the server is down

Page 9: Deploying Rails on EC2 using Rubber (Slides and Notes)

EC2 Problems (cont.)

• Not good for sending email

• SPAM central

• IPs are blacklisted

• Use something like authsmtp.com or smtp.com, or host your mail server elsewhere

Ok, for utility emails (e.g. monit/munin), since recipient list small (i.e. the recipients can whitelist)Ok for emails you don’t mind getting shoved into a spam folder.Mention google for your domain for small email quantities.

Page 10: Deploying Rails on EC2 using Rubber (Slides and Notes)

Our Deployment Needs

• Configure multiple instances as easily as one

• Easy bootstrapping and extension - didn't want to force need for a custom image at start

Page 11: Deploying Rails on EC2 using Rubber (Slides and Notes)

Rubber

• Free and open sourced

• http://github.com/wr0ngway/rubber/wikis

• Makes it easy to get up and running on ec2 with a single instance

• Allows one to add in instances to scale as needed on a role by role basis

Page 12: Deploying Rails on EC2 using Rubber (Slides and Notes)

Start Demo

• Create a simple rails app

• Setup a single instance to host it

• Lifted from quickstart on rubber wiki: http://github.com/wr0ngway/rubber/wikis

Longer when building instance from scratch, but I built from scratch last night and used rubber to bundle so that the builds today would be quicker.

Create your rails app

rm -rf rubbertest; rails rubbertest; cd rubbertest./script/generate scaffold post title:string body:text

vi app/views/posts/index.html.erb:<%= `hostname` %> <br /><%= ObjectSpace.each_object(Mongrel::HttpServer) { |i| @port = i.port }; @port %> <br /><%= `hostname -i` %> <br /><%= require 'open-uri'; open("http://169.254.169.254/latest/meta-data/public-ipv4").read() %> <br />

Install rubber

./script/plugin install git://github.com/wr0ngway/rubber.git

./script/generate vulcanize complete_mysql# slow network so manual copy# cp -R ../rubber vendor/plugins

Configure rubber

cp ~/.ec2-matt/rubber-secret.yml config/rubber/

Create a single instance with all roles

cap rubber:create# use alias: production# use roles: app,memcached,mysql_master,web,web_munin

Page 13: Deploying Rails on EC2 using Rubber (Slides and Notes)

Demo - create rails app

rails rubbertest; cd rubbertest./script/generate scaffold post title:string body:text

Add to app/views/posts/index.html.erb :<%= `hostname` %> <br /><%= ObjectSpace.each_object(Mongrel::HttpServer) {

|i| @port = i.port};@port %> <br />

<%= `hostname -i` %> <br /><%= require 'open-uri' open("http://169.254.169.254/latest/meta-data/public-ipv4").read() %> <br />

Page 14: Deploying Rails on EC2 using Rubber (Slides and Notes)

Demo - Install rubber./script/plugin install git://github.com/wr0ngway/rubber.git./script/generate vulcanize complete_mysql

edit config/rubber/rubber.yml:

aws_access_key: ****aws_secret_access_key: ****aws_account: ****ec2_key_name: ec2_key_file:staging_roles: app,memcached,mysql_master,web,web_munin

Page 15: Deploying Rails on EC2 using Rubber (Slides and Notes)

Demo - create instancecap rubber:create# use alias: production# use roles: app,memcached,mysql_master,web,web_munincap rubber:bootstrapcap deploy:setupcap rubber:monit:stopcap deploy:cold

Or use convenience task to do all the above:cap rubber:create_staging

Page 16: Deploying Rails on EC2 using Rubber (Slides and Notes)

Demo - view results

• Uses /etc/hosts for demo

• site: http://production.foo.com

• munin: http://production.foo.com:8080

Mention nettica/dyndns - if you set it up, the act of creating an instance also sets up the CNAME in nettica. Nettica preferred due to full SOAP api.LAN screwy? /etc/hosts normally works fine, but something about the LAN setup here causes OS X to ignore my /etc/hosts so using IPs (anyone know why?)

Page 17: Deploying Rails on EC2 using Rubber (Slides and Notes)

Rubber (cont.)

• My attempt at getting people to share deployment recipes

• Uses rails generators, so you can customize your config as you grow

• ec2 conveniences such as easy ami bundling, support for static IPs, security groups

Talk about templates rubber just copies file out of generator template tree, so adding a new template is easyBy making the templates generators, you can tweak them in place in your project re-running the generator with newer versions of rubber, you can see which files need updating, and show the diffs, etc.EC2 has a lot of features I’ve tried to wrap some of these features to make them easier to use - e.g. static_ips.

Page 18: Deploying Rails on EC2 using Rubber (Slides and Notes)

Rubber Features

• Capistrano rocks! rubber is a capistrano plugin

• DRY configuration

• Role and/or host based configuration of instances

All cap features available, some cap annoyances fixed e.g. ROLES/HOST runs all tasks for those hosts Vs FILTER runs just the tasks for that serverrubber*.yml files I tried to split out into different files per module. You should look in these files to figure out what variables you can tweak. For more substantial tweaks, you can edit the config files yourself Send me any settings you make declarative that others might find useful (code in conf, var in yml)deploy*.rb - custom tasks per moduleInstances are commodities whats important is how you define what runs in those instances. By setting up roles to contain chunks of your deployment scenario, you have a lot of flexibility when it comes time to run those roles on concrete instances. That is, you can define your role ONCE and use it for many instances.

Page 19: Deploying Rails on EC2 using Rubber (Slides and Notes)

Rubber Configuration System

• All configuration for your instances lives in your project's source tree and gets applied on deploy

• Configuration system uses ERB templates for config files

• Configuration system handles dynamically adding instances

Configuration is the heart of rubberBased on current host config is getting generated for (Global Settings -> Roles Settings -> Host settings) * Config file -> specific config file

Page 20: Deploying Rails on EC2 using Rubber (Slides and Notes)

Config templatemunin host config

<% rubber_instances.each do |i| %>[<%= i.full_name %>] address <%= i.internal_ip %> use_node_name yes<% end %>

Part of the munin config file Adds an entry responsible for polling each server in our deployment config. Dynamically expands when we add new servers to the mix.

Page 21: Deploying Rails on EC2 using Rubber (Slides and Notes)

Configuration (cont.)

• Configuration templates for sharing deployment scenarios (vulcanize generator)

• Start with a single instance and add more up as needed - no configuration edits needed

• Use whatever AMIs you want (so long as they are debian based :)

Page 22: Deploying Rails on EC2 using Rubber (Slides and Notes)

Rubber Features (cont.)

• Use /etc/hosts or updates dynamic dns entries automatically

• Easily/quickly create standalone staging/dev/loadtest instances that mirror production setup

Page 23: Deploying Rails on EC2 using Rubber (Slides and Notes)

Anti-Features

• Initial experience is fairly turnkey, but you will need some expertise as you grow

• Tied to Rails, shouldn’t be hard to divorce

• Not (yet) a gem

• Many other TODOs, feel free to contribute

• No dynamic instances (like poolparty) - you create them all statically. Works for us.

Mention TODO file in project

Page 24: Deploying Rails on EC2 using Rubber (Slides and Notes)

Demo +1 app serverALIAS=app01 ROLES=app,memcached cap rubber:createcap rubber:bootstrapcap deploy:setupcap deploy... check load balancing at http://production.foo.com/postsALIAS=app01 cap rubber:destroy... check load balancing at http://production.foo.com/posts

Add in another app server

ALIAS=app01 ROLES=app,memcached cap rubber:createcap rubber:bootstrap # if paranoid, FILTER=app01cap deploy:setupcap deploy

Hit url, show load balancingremove app01, show load balancing

ALIAS=app01 cap rubber:destroy

Page 25: Deploying Rails on EC2 using Rubber (Slides and Notes)

Individual Staging Servers

• Incredibly valuable, you know it works before you deploy for real

• Quick and easy

• cp config/environments/production.rb config/environments/matt.rb

• RAILS_ENV=matt cap rubber:create_staging

• Mimics production

Every engineer deploys their branch to their own on demand staging server

cp config/environments/production.rb config/environments/matt.rbRAILS_ENV=matt cap rubber:create_staging

Page 26: Deploying Rails on EC2 using Rubber (Slides and Notes)

Complex setup

ALIAS=web01 ROLES=web,internal_web cap rubber:createALIAS=app01 ROLES=app cap rubber:createALIAS=app02 ROLES=app cap rubber:createALIAS=db01 ROLES=mysql_master cap rubber:createALIAS=db02 ROLES=mysql_slave cap rubber:createcap rubber:bootstrapcap deploy:setupcap deploy:cold

Note the mysql_slave bootstrap sets up master -> slave replication for youThere is also a mysql_cluster generator template

Page 27: Deploying Rails on EC2 using Rubber (Slides and Notes)

Mysql cluster setup./script generate mysql_clusterALIAS=data01 ROLES=mysql_data cap rubber:createALIAS=data02 ROLES=mysql_data cap rubber:createALIAS=data03 ROLES=mysql_data cap rubber:createALIAS=sql01 ROLES=mysql_sql cap rubber:createALIAS=sql02 ROLES=mysql_sql cap rubber:createALIAS=mgm01 ROLES=mysql_mgm cap rubber:createcap rubber:bootstrapcap deploy:setupcap deploy:cold

Still to do - sqlrelay on localhost to load balance between sql nodes

Page 28: Deploying Rails on EC2 using Rubber (Slides and Notes)

Bring it all Down

• cap rubber:destroy_all

• Elapsed cost, a few cents

• No idle hardware

• No obsolete hardware

• We can do it all again without any additional effort

Page 29: Deploying Rails on EC2 using Rubber (Slides and Notes)

Questions?

• Alternatives listed in FAQ in rubber github wiki