Tárgyalás a bérgyilkosokkal

Lassan bocsánatot kell kérjek a mindent magyarítás miatti szenzációhajhász címek miatt :) Szóval az úgy kezdődött, hogy a pet projectemet egyre több és több dologgal szeretném felcicomázni, szeretném belakni az új környezetet, és eközben akadtam rá a Capistrano bonyolultságával szembehelyezkedő Vlad-ra.

Persze nézem a forrást, és látom, hogy egyszerűcske a dolog, szögletes az a karika, de aztán belenéztem a capistrano forrásába, hogy némi fícsört vigyek a vlad-ba, és azt kell mondjam, akkor már a bérgyilkos szakasz.  Nem teljesen egyértelmű a használata, de azért jól ki lehet jönni vele.

Az első, de legfontosabb probléma, hogy nincs hozzá rendes manuál. Vannak dirib-darab infómorzsák, meg arra számítottak, hogy az emberek már úgyis ismerik a capistrano-t, meg ugye a kód is nyúlfarknyi, de hát azért…

Kezdjük az elején, mit is szeretnénk tulajdonképpen elérni? Deploymentet. A deployment tulajdonképpen egy rendszeresen végrehajtandó feladat, tehát ne találjuk fel a spanyolviaszt, erre nagyon jól ott van a rake a maga struktúrájával. Erre még rádobtak egy lapáttal, és kibővítették egy újabb művelettel, aminek remote_task nevet adtak, mondván nem helyileg kell megoldani.  Van már ssh-nk parancsban, amit fel is lehet konfigurálni, meg rsync-ünk, mehet is a móka.

Ahhoz, hogy a Vlad rake task-jait tudjuk használni, először bele kell illeszteni a saját kódunkba:

lib/tasks/vlad.rake:

begin
  require 'vlad'
  Vlad.load
rescue LoadError
  # do nothing
end

Persze ez nem biztos, hogy elég, mivel van egy rakás modul, amit be lehet tölteni (és van egy másik rakás, amit meg nem érdemes), és az értékeket később hiába próbáljuk állítgatni.  Ezek:

  • :app – az alkalmazásszerver. Alapértelmezett a :mongrel (app-ként viselkedik még a :god, :nginx, :merb, :passenger, és :thin is).
  • :scm – a verziókövető rendszer, alapból :subversion (lehet még :darcs, :git, :mercurial, és :perforce).
  • :web – a webszerver. Alapból :apache, de lehet még :lighttpd vagy :nginx is.

Ezeket lehet törölni is (például nálam az alkalmazásszerver :passenger, és kösz, ne indítsa újra a webszervert, ezért a :web pedig nil), ha nincs rájuk szükség.

Érdemes kis időt szánni a kódra is, végignézni, hogy mit is csinálnak ezek a taskok:

  • apache: apachectl-en keresztül indítja-állítja a webszervert, a start/stop-ra pedig húzza magával az alkalmazásszervert is.
  • god: egy rubyban írt alkalmazásfigyelő rendszeren keresztül vezérli az appot. A legnagyobb előnye, hogy rubyban tudjuk konfigurálni is, mindenképpen megér egy próbát.
  • lighttpd: app és webszerver egyben, az app szerver eközben fastcgi.
  • merb: a merb-nek saját app szervere van (merb == mongrel + embedded ruby), ez pont azt konfigolja fel.
  • mongrel: ez a mongrel_rails-t konfigurálja fel app szervernek.
  • nginx: még egy olyan szoftver, amire érdemes odafigyelni. Bár natív mod_php támogatás nincs hozzá, nem beszélve a subversion támogatásról, de ez az orosz fejlesztés egy nagyon remek webszervert adott a világnak. Ráadásul újabban a Phusion Passenger is támogatja, tehát ideális környezet rails kiszolgálásra. A vlad modul egy működőképes webszerver konfigot, meg egy nem műküdő, látszólag slicehost-ra készült app szerveres konfigot tartalmaz. Kár, hogy direkt a /etc/init.d/nginx-et hívja meg, és BSD-n ilyen nincs.
  • passenger: az előbb említett Phusion cég Passenger-e egy újabb gyöngyszem. Prefork módszerrel készít nekünk igény szerint rails szervert, természetesen a jogosultságok megtartásával. A fájl látványosan meghúzza a bűvös kart újraindítás esetén, és ennyi.
  • thin: még egy appszerver beállítás, a mongrel és merb taskok után szabadon.
  • scm csomagok (darcs, git, mercurial, perforce, subversion): egyszerű szkriptek a különböző verziókövető rendszer műveleteire, a core modul használja.

Miután ezekkel megismerkedtünk, érdemes átírni a task betöltőt valami ilyenre:

lib/tasks/vlad.rake:

begin
  require 'vlad'
  Vlad.load :scm => :git, :app => :passenger, :web => nil
rescue LoadError
  # do nothing
end

Ezután már csak a konfig van hátra, amit a már ismert config/deploy.rb -be teszünk. Itt lehet beálítani a változókat, illetve lehet újabb taskokat is csinálni, pl. így:

config/deploy.rb:

set :application, "<app name>"
set :domain, "<user>@<ssh server>"
set :deploy_to, "/var/www/apps/#{application}"
set :repository, "<repo URL>"
namespace :vlad do
  remote_task :update do
    Rake::Task['vlad:after_update'].invoke
  end
  remote_task :after_update do
    dbyml = "#{latest_release}/config/database.yml"
    dbyml_shared = "#{deploy_to}/shared/system/database.yml"
    dbyml_template = "#{latest_release}/config/database-defaults.yml"
    run "mkdir -p #{deploy_to}/shared/system"
    run "test -d #{dbyml_shared} || cp #{dbyml_template} #{dbyml_shared}"
    run "test -e #{dbyml} || ln -s #{dbyml_shared} #{dbyml}"
  end
  remote_task :deploy => [:update, :migrate, :start_app]
end

Ez a kis konfig a főbb paraméterek betöltése után egy távol végrehajtandó feladatot ad a vlad:update-nek, amit külön is meghívhatunk vlad:after_update néven.  Ez a repóban nem szereplő adatbázis konfigot hozza létre a megosztott könyvtárban (ilyet éles rendszernél nem csinálunk, de teszt környezetek fellövésénél remekül jön).  Majd az új deployment-be belinkeli a stabil konfig változatot, ami pedig 100%, hogy jól jön minden esetben.

A harmadik, szintén távoli feladat pedig a vlad:deploy task-ot hozza létre, nevezetesen a távoli update (+after_update), migrate, valamint start_app feladatokat elindítva. Nem egy nagy ördöngősség.

Persze még lehetne cicomázni, pl. a megosztott könyvtárat (ami ugye nincs verziókontroll alatt) fel- meg lemásoló taskokkal, háttérprocessz indítással, de az már egy másik történet.

Használjatok vlad-ot!

  • http://blog.js.hu/2010/07/14/make-rails3-deployment-more-robust-with-inploy/ Jul’s blog » Make rails3 deployment more robust with inploy

    [...] never touched Capistrano, it looked like a rake spinoff. I started using Vlad instead (my post in Hungarian), but at some point, it started to be very frustrating. Deployment took too long, deployment [...]