3. Vagrant
+
• Created by Mitchell Hashimoto
• http://vagrantup.com
• Ruby DSL for provisioning VirtualBox VMs
4. Vagrant::Config.run do |config|
config.vm.box = 'dealz-ubuntu-lucid'
config.vm.forward_port('web', 80, 4567)
config.vm.host_name('dealz')
config.vm.network('13.37.33.30')
config.vm.customize do |vm|
vm.name = 'dealz'
end
end
5. config.network(‘13.37.33.33’)
$ ping 13.37.33.31
PING 13.37.33.31 (13.37.33.31): 56 data bytes
64 bytes from 13.37.33.31: icmp_seq=0 ttl=64 time=0.337 ms
64 bytes from 13.37.33.31: icmp_seq=1 ttl=64 time=0.290 ms
64 bytes from 13.37.33.31: icmp_seq=2 ttl=64 time=0.320 ms
8. Vagrant::Config.run do |config|
config.vm.define :web do |web_config|
web_config.vm.box = 'dealz-ubuntu-lucid'
web_config.vm.host_name = 'dealz-web'
web_config.vm.network('13.37.33.31')
web_config.vm.customize do |vm|
vm.name = 'dealz-web'
end
end
config.vm.define :app do |app_config|
app_config.vm.box = 'dealz-ubuntu-lucid'
app_config.vm.host_name = 'dealz-app'
app_config.vm.network('13.37.33.32')
app_config.vm.customize do |vm|
vm.name = 'dealz-app'
end
end
config.vm.define :db do |db_config|
db_config.vm.box = 'dealz-ubuntu-lucid'
db_config.vm.host_name = 'dealz-db'
db_config.vm.network('13.37.33.33')
db_config.vm.customize do |vm|
vm.name = 'dealz-db'
end
end
end
13. Deploying with
RVM
• Created by Wayne Seguin
• http://rvm.beginrescueend.com
• Easy to have multiple Rubies
• Not just for development
14. Deploying with
RVM
$:.unshift File.expand_path(ENV[‘RVM_PATH’])
require ‘rvm/capistrano’
set :rvm_ruby_string, ‘ruby-1.9.2-p180’
set :rvm_type, :system
17. Speeding up with Git
• Technique published by Chris Wanstrath in
2009
• https://github.com/blog/470-deployment-
script-spring-cleaning
• Replacement for Capistrano’s deployment
strategies
18. Speeding up with Git
• Technique published by Chris Wanstrath in
2009
• https://github.com/blog/470-deployment-
script-spring-cleaning
• Replacement for Capistrano’s deployment
strategies
19. desc "Set up the current stage for Git-based deployment"
task :setup, :except => { :no_release => true } do
setup_command = ["rm -fr #{current_path}"]
setup_command << "git clone #{repository} #{current_path}"
setup_command << shared_children.map { |dir| "mkdir -p
#{shared_path}/#{dir}" }
setup_command << "rvm rvmrc trust #{current_path}"
setup_command << "gem install bundler --no-rdoc --no-ri"
run setup_command.join(' && ')
end
20. desc "Update the current stage to the latest revision"
task :update_code, :except => { :no_release => true } do
update_command = ["git fetch origin && git reset --hard
#{branch}"]
update_command << "echo #{branch} > #{current_path}/BRANCH"
update_command << "git rev-parse --verify HEAD --short >
#{current_path}/REVISION"
run "cd #{current_path} && #{update_command.join(' && ')}"
end
21. namespace :rollback do
task :default do
code
end
task :code, :except => { :no_release => true } do
set :branch, 'HEAD^'
deploy
end
end
22. Speeding up
symlinks
• Capistrano defaults to using separate runs
for each symlink
• Each run is a separate SSH connection
• Consolidate symlinks for a speed boost
27. config/deploy.rb
require 'capistrano/ext/multistage'
set :default_stage, 'qa'
set :application, 'dealz'
set :user, 'dealz'
set :group, 'dealz'
set :use_sudo, false
set :scm, :git
set :repository, 'git@github.com:dirtyalpaca/dealz.git'
set :deploy_to, "/var/#{application}"
set :deploy_via, :remote_cache
36. exception_notification
• Free and open source
• https://github.com/rails/exception_notification
• Simple email notification
• Modifiable to put in database or message
queue
• Flood of emails
40. Capturing Output
namespace :log do
task :head, :roles => [:app] do
capture(“tail -n 100 #{shared_path}/log/
#{stage}.log”)
end
task :tail, :roles => [:app] do
stream(“tail -f #{shared_path}/log/#{stage}.log”)
end
end
44. task :update_code, :except => { :no_release => true } do
on_rollback { run "rm -rf #{release_path}; true" }
[...]
end
45. task :symlink, :except => { :no_release => true } do
on_rollback do
if previous_release
run "rm ‐f #{current_path}; ln ‐s #{previous_release} #{current_path}; true"
[ ... ]
end
[...]
end
[...]
end
57. Capistrano + Unicorn
set :unicorn_command, 'bundle exec unicorn'
set :unicorn_config, "#{current_path}/config/unicorn.rb"
set :unicorn_pid, "#{current_path}/tmp/pids/unicorn.pid"
namespace :deploy do
task :start, :roles => :app, :except => { :no_release => true } do
run "cd #{current_path} && #{unicorn_command} -c #{unicorn_config} -E
#{rails_env} -D"
end
task :stop, :roles => :app, :except => { :no_release => true } do
run "kill `cat #{unicorn_pid}`"
end
task :graceful_stop, :roles => :app, :except => { :no_release => true } do
run "kill -s QUIT `cat #{unicorn_pid}`"
end
task :reload, :roles => :app, :except => { :no_release => true } do
run "kill -s USR2 `cat #{unicorn_pid}`"
end
task :restart, :roles => :app, :except => { :no_release => true } do
stop
start
end
end
58. Managing Your Schedule
with Whenever
• Written by Javan Makhmali
• http://github.com/javan/whenever
• Ruby DSL for specifying cron jobs
• Integrates nicely with Capistrano
61. Managing Your Schedule
with Whenever
every 3.hours do
runner "MyModel.some_process"
rake "my:rake:task"
command "/usr/bin/my_great_command"
end
every 1.day, :at => '4:30 am' do
runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
end
every :hour do # Many shortcuts
available: :hour, :day, :month, :year, :reboot
runner "SomeModel.ladeeda"
end
every :sunday, :at => '12pm' do # Use any day of the week
or :weekend, :weekday
runner "Task.do_something_great"
end
every '0 0 27-31 * *' do
command "echo 'you can use raw cron sytax too'"
end
(from the GitHub wiki)
62. Managing Your Schedule
with Whenever
set :whenever_command, ‘bundle exec whenever’
require ‘whenever/capistrano’
(from the GitHub wiki)
tunnel from port 4567 to port 80 on the VM\ntunnel from port 2222 to port 22 on the VM\nfolder in which vagrantfile exists is shared\n
tunnel from port 4567 to port 80 on the VM\ntunnel from port 2222 to port 22 on the VM\nfolder in which vagrantfile exists is shared\n
\n
- Use case for testing system configuration\n- Provisioning script development (Puppet, Chef, etc.)\n- Networked so they can talk\n
\n
\n
lib/deploy/\nhooks in config/deploy.rb\n\n\n
\n
submodule or gem? 50/50, maybe submodule\n
\n
\n
many servers, only one accepting connections\n
cap 2.6.0 released may 4\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
deploy to multiple environments\nintegration/qa/production\n
\n
\n
\n
\n
\n
\n
if you have qa/performance blocks in your gemfile, set :bundle_without\n
if you have qa/performance blocks in your gemfile, set :bundle_without\n
- show of hands - who's using hoptoad?\n - exception_notifier - pros: easy, simple, can modify to put in DB or on msg queue cons: flood o' email\n - can use new relic - pros: good display, no email flood, (? how does dev get notified?) cons: some delay, $$\n - hoptoad\n
\n
\n
\n
\n
\n
individual accounts: logs get wrong permissions, daemons get started as wrong users, you need a generic account for init scripts anyway\ngoal is to avoid situation where people have to ssh in\n
when task fails, capistrano checks for rollback hooks\n
&#x201C;cap deploy&#x201D; consists of update and restart\nupdate has two subtasks which it runs in a txn\n
so you can see how you can write your own tasks that use txns and clean up after themselves\n
so you can see how you can write your own tasks that use txns and clean up after themselves\n
tinder - campfire notify, but don&#x2019;t notify to &#x2018;human&#x2019; chatrooms\ncap_gun - email, includes diff\n\n\n
\n
can also set : newrelic_revision, :newrelic_changelog\non the newrelic site appears as a line in the graph, also a list of recent deployments\n
\n
\n
\n
not just because of size, but also sensitive data\nautomate it\ndump from slave, normalize sensitive data (passwords)\ndecrease size by keeping recent or by partitioning\n
apache-specific\n
can use either time interval or size\nwith nginx, mv log, kill -USR1 4242, sleep 5, zip log or whatever\n
monitoring passenger memory usage\n
\n
\n
\n
\n
\n
\n
\n
private keys with passphrases without hassle\nlaunchd - org.openbsd.ssh-agent.plist\n&#x201C;ForwardAgent yes&#x201D; in your .ssh/config\n
too many keys in ssh-agent results in server rejection (MaxAuthTries 6, maximum number of authentication attempts permitted per connection)\nssh-add -l to list, ssh-add -d filename to remove\n