Download pdf - Hosting Ruby Web Apps

Transcript
Page 1: Hosting Ruby Web Apps

Hosting Ruby Web Apps

Lessons learned from 8 years of

Page 2: Hosting Ruby Web Apps

Overview

• System architecture

• Initial setup & deploy

• Keep it running and moving forward

Page 3: Hosting Ruby Web Apps

Michael Reinsch

[email protected] @mreinsch

Page 4: Hosting Ruby Web Apps

Next Weekend! startupweekend.jp/swtokyo-personal-cloud/

Page 5: Hosting Ruby Web Apps

Michael Reinsch

[email protected] @mreinsch

Page 6: Hosting Ruby Web Apps

Build a community through your events.

Page 7: Hosting Ruby Web Apps
Page 8: Hosting Ruby Web Apps

DB (psql)

memcache

nginxunicorn

unicornRails App (unicorn)

job workerMTA (postfix)

Page 9: Hosting Ruby Web Apps

Contenders

Page 10: Hosting Ruby Web Apps

Contenders

Page 11: Hosting Ruby Web Apps

Contenders

Page 12: Hosting Ruby Web Apps

Contenders

Page 13: Hosting Ruby Web Apps

Contenders

Page 14: Hosting Ruby Web Apps

Please Note

• Not an exhaustive list of all hosting providers(it’s not even everyone we’ve been using)

• Moving targets

Page 15: Hosting Ruby Web Apps

Choosing Server Sizewww.flickr.com/photos/jonrb/7864016624

Page 16: Hosting Ruby Web Apps

Choosing Server Size

• good CPU performance

• choose 2GB RAM or more

Page 17: Hosting Ruby Web Apps

Choosing Server Size

• 1 ECU/core is a bit frustrating

• 2 ECU/core is OK

• >2 ECU/core is better

Page 18: Hosting Ruby Web Apps

Choosing Server Size

• 3 different sizes

• choose standard size if you don’t have specific requirements

Page 19: Hosting Ruby Web Apps

Hardware Failures

How can we make things robust?

www.flickr.com/photos/doegox/4551458930

Page 20: Hosting Ruby Web Apps

Hardware Failures“We’re trying to prevent failures, please

make backups for worst case”

!

• provides load balancer

• fault tolerant setup example:2 web instances + 2 DB instances

• need to configure DB replication and failover yourself

Page 21: Hosting Ruby Web Apps

Hardware Failures“Failures will happen, build your infrastructure

so they won’t impact you”

• provides load balancer (ELB)

• provides managed DB instances (RDS)

• replication support (not for psql yet)

• DB snapshots (can’t download though)

• fault tolerant setup example: 2 web instances + multi-AZ RDS

Page 22: Hosting Ruby Web Apps

Hardware Failures“Failures will happen, let us help you build an

infrastructure so they won’t impact you”

• HA proxy on web instances

• one-click setup for DB (mysql/psql)

• replication support

• DB snapshots (downloadable)

• fault tolerant setup example:2 web instances + 2 DB instances

Page 23: Hosting Ruby Web Apps

Hardware Failures“You don’t need to worry about failures”

!

!

• everything managed

• fault tolerant setup example: 2 dynos + premium DB (psql)

Page 24: Hosting Ruby Web Apps

Initial Setup & Deploy

www.flickr.com/photos/thedailyenglishshow/6013713229

Page 25: Hosting Ruby Web Apps

Initial Setup & Deploy

• manual setup feasible:

• install OS, ruby (rvm), libs, DB

• setup nginx

Page 26: Hosting Ruby Web Apps

Initial Setup & Deploy

• let’s choose Capistrano for deploying

• Capistrano config goes into source repository

• Initial deploy:

cap deploy:setup cap deploy:cold

Page 27: Hosting Ruby Web Apps

Initial Setup & Deploy

• let’s choose OpsWorks

• based on chef, provides predefined set of recipes

• more high level than Cloud Formation, more flexible than Elastic Beanstalk

Page 28: Hosting Ruby Web Apps

Initial Setup & Deploy• initial deploy:

• create stack

• define layers

• create instances

• create app

• deploy

Page 29: Hosting Ruby Web Apps

Initial Setup & Deploy

• define base layer

• assign it to all instances

• use it for any common recipes like creating swap, NewRelic, ...

Tip

Page 30: Hosting Ruby Web Apps

Initial Setup & Deploy• you need to handle asset compilation

• use deploy hook:

Tip

# deploy/before_migrate.rb !rails_env = new_resource.environment["RAILS_ENV"] Chef::Log.info("Precompiling assets for RAILS_ENV=#{rails_env}...") !execute "rake assets:precompile" do cwd release_path command "bundle exec rake assets:precompile" environment "RAILS_ENV" => rails_env end !!

Page 31: Hosting Ruby Web Apps

Initial Setup & Deploy• provides toolchain based on chef

• initial deploy:

• create an application

• select environment layout

• add plugins (NewRelic, ...)

• deploy

Page 32: Hosting Ruby Web Apps

Initial Setup & Deploy

Heroku comes with its’ own toolchain:

heroku create my-awesome-app heroku addons:add … git remote add heroku … git push heroku master

Page 33: Hosting Ruby Web Apps

What you’ll probably also need

• App configuration (for secrets and endpoints)

• Sending email

• Job queue

Page 34: Hosting Ruby Web Apps

App Configuration

• no predefined way: DIY

• put settings.yml into shared config dir

• link it into app when deploying

Page 35: Hosting Ruby Web Apps

App Configuration

• uses environment variables

heroku config:add MY_SECRET=topsecret heroku config

• in your code:

ENV[‘MY_SECRET’]

Page 36: Hosting Ruby Web Apps

Sending Email

• use an email sending service (SendGrid, AWS SNS)

• EY and Heroku provide plugins for easy installation

Page 37: Hosting Ruby Web Apps

Sending Email Yourself

• reverse IP lookup

• port 25 is restricted

• make sure your IP isn’t blacklisted

Page 38: Hosting Ruby Web Apps

Job Queue

• DIY

• define custom layer in OpsWorks, need to get 3rd party recipe

Page 39: Hosting Ruby Web Apps

Job Queue

• sample recipes are provided

• worker instances

Page 40: Hosting Ruby Web Apps

Job Queue

• provides worker dynos

• requires setup in Procfile

Page 41: Hosting Ruby Web Apps

Background mailer

• use database transaction to atomically create mailer job and related data

• rollback if something goes wrong

• reduces request response time

• job can retry sending email

Tip

Page 42: Hosting Ruby Web Apps

Up and running :-)

Page 43: Hosting Ruby Web Apps

Continuous Deployment

www.flickr.com/photos/layos/3743880081

Page 44: Hosting Ruby Web Apps

Continuous Deployment

• keep deploys cheap

• automate deploy

• easy deployment trigger

• good test coverage - use CI

• use rolling / zero downtime deploy

Page 45: Hosting Ruby Web Apps

Continuous Deployment

• deploy command:

git pull cap deploy

• unicorn for rolling deploy

Page 46: Hosting Ruby Web Apps

Continuous Deployment

• unicorn is configured for rolling deploys

• deploy command:

aws --region=‘us-east-1’ opsworks create-deployment --stack-id=‘<STACK_UUID>’ --app-id=‘<APP_UUID>’ --instance-ids=‘[“<INSTANCE_UUID>”]’ --command='{"Name": "deploy"}

Page 47: Hosting Ruby Web Apps

Continuous Deployment

gem 'aws-sdk' gem 'parseconfig' !PRODUCTION_APP_ID = "09afbde1-322b-4816-a1e9-xxxxxxxxxxxx" !config = ParseConfig.new(File.expand_path("~/.aws/config")) AWS.config( :access_key_id => config['default']['aws_access_key_id'], :secret_access_key => config['default']['aws_secret_access_key']) !@ops = AWS::OpsWorks.new.client @ops_app = @ops.describe_apps(app_ids: [PRODUCTION_APP_ID])[:apps].first @ops_stack = @ops.describe_stack_summary(stack_id: @ops_app[:stack_id])[:stack_summary] @ops_inst = @ops.describe_instances(stack_id: @ops_app[:stack_id])[:instances] @ops_inst_ids = @ops_instances.map do |instance| instance[:instance_id] if instance[:status] == 'online' end.compact !puts "Deploying #{@ops_app[:name]} to #{@ops_stack[:name]}" !deploy_options = { command: { name:' deploy' }, comment: "deploy from #{Socket.gethostname}", stack_id: @ops_app[:stack_id], app_id: @ops_app[:app_id], instance_ids: @ops_inst_ids } @ops.create_deployment deploy_options !!

or some simple ruby script:

Page 48: Hosting Ruby Web Apps

Continuous Deployment

• deploy command:

ey deploy

• in config/ey.yml:

maintenance_on_migrate: false

Page 49: Hosting Ruby Web Apps

Continuous Deployment

• deploy command:

git pull git push heroku master

• no-downtime deploys experimental:

heroku labs:enable -a myapp preboot

Page 50: Hosting Ruby Web Apps

Continuous Deployment

• “fork” in code

• on/off switch for features

• slow rollout of new features

Tip

Page 51: Hosting Ruby Web Apps

Rolling Deploys with!Database Migrations

www.flickr.com/photos/edwardshousemovers/6704586649

Page 52: Hosting Ruby Web Apps

Rolling Deploys with Database Migrations

orchestrated deployment flow:

1. copy code, keep old version

2. run migrations

3. switch to new code

➜ one-step deployments

Page 53: Hosting Ruby Web Apps

Rolling Deploys with Database Migrations

• asynchronous deployment flow

• two-step deployment

1. deploy old code + DB migrations(one instance only)

2. deploy new code(all instances)

Page 54: Hosting Ruby Web Apps

Rolling Deploys with Database Migrations

• migrations are run via:

heroku run rake db:migrate

• two-step deployment

1. deploy old code + DB migrations

2. deploy new code

Page 55: Hosting Ruby Web Apps

Down for!Maintenance

www.flickr.com/photos/metrolibraryarchive/4128611963

Page 56: Hosting Ruby Web Apps

Down for Maintenance

• Maintenance page done right:

• include contact and progress info (use 3rd party service like Twitter)

• serve page with 503 error code

• use asset host or inline all assets

Tip

Page 57: Hosting Ruby Web Apps

Down for Maintenance• add ‘capistrano-maintenance’ gem

• configure nginx

• then:

cap maintenance:enable

server { // nginx server config ! location @maintenance { rewrite ^(.*)$ /system/maintenance.html last; break; } if (-f $document_root/system/maintenance.html) { return 503; } ! error_page 503 @maintenance;

Page 58: Hosting Ruby Web Apps

Down for Maintenance

• Need custom recipe / script

• Can use similar approach as with Capistrano

• 503 won’t pass ELB health check!

• Alternative: use Route53 to fail over to instance serving maintenance page

Page 59: Hosting Ruby Web Apps

Down for Maintenance

• Part of the platform:

ey web disable

heroku maintenance:on

Page 60: Hosting Ruby Web Apps

Getting Support

Page 61: Hosting Ruby Web Apps

Getting Support

• provides ticket system for any platform related issues

• forum for anything else

Page 62: Hosting Ruby Web Apps

Getting Support

• forums for everything

• access to tickets only available if certain health checks fail

Page 63: Hosting Ruby Web Apps

Getting Support

• tickets for everything

• provides even hosting related help on application level

• “extension of your team”

Page 64: Hosting Ruby Web Apps

Conclusion• there is no silver bullet

• a lot depends on your app

• be ready to get your hands dirty

• your production environment is your app

• balance ops / dev

Page 65: Hosting Ruby Web Apps

Thank you!

Contact:

Michael [email protected] @mreinsch

Questions?More awesome events:

• ijaws.doorkeeper.jp

• Startup Weekend Tokyo Personal Cloud


Recommended