Upgrade to Pro — share decks privately, control downloads, hide ads and more …

URUG Foreman Presentation

URUG Foreman Presentation

Discussion about managing multi-process applications with foreman.

BJ Neilsen

August 14, 2012
Tweet

Other Decks in Programming

Transcript

  1. single-process apps Application process management boils down to 3 questions:

    How do I... - start my app? - stop my app? - restart my app? In a single-process app, this is pretty easy.
  2. Managing a single process app unicorn -c ./config/unicorn.rb -E production

    ./config.ru Start app Stop app kill -QUIT $(cat ./tmp/pids/unicorn.pid) Restart app kill -USR2 $(cat ./tmp/pids/unicorn.pid)
  3. Application process complexity can grow in a number of ways:

    • Add server nodes • Add more process types to app • Add/remove developers to the project "I can't remember how to start unicorn!" Wait, how do you use this hammer?
  4. Just put it in capistrano namespace :deploy do task :start

    do run "unicorn -c #{current_path}/config/unicorn -E production #{current_path}/config.ru" end task :restart do run "kill -USR2 $(cat #{shared_path}/pids/unicorn. pid)" end task :stop do run "kill -QUIT $(cat #{shared_path}/pids/unicorn. pid)" end end $ cap deploy:restart
  5. or, init scripts FTW! ... start) sig 0 && echo

    >&2 "Already running" && exit 0 echo "Starting" $CMD ;; stop) sig QUIT && echo "Stopping" && exit 0 echo >&2 "Not running" ;; force-stop) sig TERM && echo "Forcing a stop" && exit 0 echo >&2 "Not running" ;; restart|reload) sig USR2 && sleep 5 && oldsig QUIT && echo "Killing old master" `cat $OLD_PID` && exit 0 echo >&2 "Couldn't reload, starting '$CMD' instead" $CMD ;; upgrade) sig USR2 && echo Upgraded && exit 0 echo >&2 "Couldn't upgrade, starting '$CMD' instead" $CMD ;; rotate) sig USR1 && echo rotated logs OK && exit 0 echo >&2 "Couldn't rotate logs" && exit 1 ... $ sudo /etc/init.d/myapp start
  6. multiple processes with capistrano? task :start do run "... start

    unicorn ... " run "... start resque ... " run "... start rabbit subscribers ... " run "... start rpc ..." end task :restart do run "... restart unicorn ... " run "... restart resque ... " run "... restart rabbit subscribers ... " run "... restart rpc ..." end ...
  7. ... or with init.d? sudo /etc/init.d/myapp-unicorn start sudo /etc/init.d/myapp-resque-worker1 start

    sudo /etc/init.d/myapp-resque-worker2 start sudo /etc/init.d/myapp-resque-worker3 start sudo /etc/init.d/myapp-resque-worker4 start sudo /etc/init.d/myapp-resque-worker5 start sudo /etc/init.d/myapp-subscribers start sudo /etc/init.d/myapp-rpc start
  8. Why foreman solves these problems Foreman solves these problems with

    a series of capabilities: • Procfile to denote processes and commands. • Concurrency/Environment configuration. • Local runtime for all processes. • Export to server process manager of choice.
  9. Procfile lists your app's process dependencies rpc: rpc_server --env=$APP_ENV --host=$APP_HOST

    --port=$PORT ./config/environment.rb web: unicorn -c ./config/unicorn.rb -E $APP_ENV worker: rake resque:work scheduler: rake resque:scheduler subscriber: babou start process name start command
  10. Process concurrency and environment config .foreman file .env file app:

    myapp concurrency: rpc=1,web=1,worker=10, scheduler=1,subscriber=1 log: ./log APP_HOST=myapp.myhost.com RAILS_ENV=production QUEUE=myapp_high,myapp_mid,myapp_low APP_NAME=myapp SOME_OTHER_PARAM=123
  11. foreman start, run commands Start application processes with foreman foreman

    start [process] • Runs on top • Log to STDOUT • Color-coded output per process • Can also specify a single process name to run foreman run <command> • Run arbitrary command with the foreman configuration/env.
  12. foreman export Export your multi-proc setup to popular process management

    configurations on linux. • bluepill • inittab • runit • upstart
  13. Control via Russian doll-style nesting $ cat tmp/abacus-worker-1.conf start on

    starting abacus-worker stop on stopping abacus-worker respawn exec su - bj -c 'cd /path/to/abacus; export PORT=5100; bundle exec rake resque:work >> ./log/worker-1.log 2>&1' $ sudo start abacus-worker # start all workers $ sudo stop abacus-worker-3 # stop the 3rd worker $ sudo restart abacus-rpc-1 # restart rpc 1 # restart all processes "owned" by abacus $ sudo restart abacus
  14. Wire it up to cap for maximum awesome Add foreman:export

    task to capistrano recipe and setup an after hook on deploy to re-export configuration.