Il deployment è quella serie di operazioni e procedure che sono necessarie per "mettere in produzione", ovvero rendere disponibile, un sistema, una rete, un insieme di software etc. È una delle fasi finali del ciclo di vita del software, che si presenta quando viene conclusa una sessione di sviluppo (il rilascio di una nuova release ad esempio). In questa fase bisogna predisporre tutto l'ambiente (cosiddetto "ambiente di produzione") perché tutto funzioni correttamente: quindi si procede all'installazione del nuovo software e compiono operazioni come l'aggiornamento di altre applicazioni o dei database.
In questo articolo ci concentreremo sul deployment di applicazioni Ruby on Rails, analizzando le varie strategie che si possono adottare per implementare una soluzione stabile ed affidabile sulla quale far eseguire le nostre applicazioni.
Ruby on Rails (da ora in poi solo Rails) ci ha abituato ad una semplicità ed immediatezza che pochi framework riescono ad offrire, ad esempio l'avvio di un'applicazione Rails è banale, basta il comando:
# script/server
lanciato nella directory radice della nostra applicazione. L'applicazione parte con tanto di Web server integrato (webrick o mongrel se presente).
Questo è un modo molto semplice per provare le nostre applicazioni: non abbiamo bisogno di configurare alcun Web server per lo sviluppo e non abbiamo problemi di permessi. Il rovescio della medaglia in questo caso consiste nelle prestazioni scadenti, soprattutto se si utilizza webrick come Web server.
Il motivo, grossolanamente, è dato dal fatto che webrick, soprattutto se in modalità 'development', ricarica buona parte dell'applicazione ad ogni richiesta, causando un notevole calo di prestazioni.
Per ovviare a questo problema si possono intraprendere principalmente due strade:
- utilizzare mongrel (che opzionalmente può essere affiancato ad un Web server, per migliorare ulteriormente le prestazioni)
- utilizzare un Web server con fast cgi
In questo articolo utilizziamo mongrel affiancato da apache 2 (con il modulo mod_proxy_balancer
) per il bilanciamento del carico, perchè è stata adottata con soddisfazione da praticamente tutta la comunità Rails.
Nota: è stata rilasciata una versione di mod_Rails
dai ragazzi di www.phusion.nl, nel momento in cui scriviamo è ancora un esperimento, ma chissà! Magari finalmente un degno concorrente di mod_php
, visto che mod_ruby
non ha riscosso molto successo.
Installiamo mongrel
Mongrel è un Web server, sviluppato per rendere più semplice il deployment e la gestione (clustering, scalabilità, bilanciamento, etc.) delle applicazioni Web Ruby. A differenza di fast cgi, che utilizza un suo protocollo per comunicare con il Web server, mongrel utilizza direttamente il protocollo HTTP, questo gli garantisce una maggiore flessibilità. In questo modo è possibile, ad esempio, posizionare mongrel dietro un bilanciatore di traffico HTTP, un bilanciatore TCP, un Web server, un server proxy, etc. Detto questo, installiamo tutto il necessario:
# gem install -y mongrel mongrel_cluster
Nota: mongrel richiede una vesione di RubyGems >= 0.9.4
Lanciamo subito una semplice sessione di mongrel, sempre dalla root della nostra applicazione:
# script/server start
oppure
# mongrel_Rails start ** Starting Mongrel listening at 0.0.0.0:3000 ** Starting Rails with development environment... ** Rails loaded. ...
Lanciare una sola istanza di mongrel non è però una buona soluzione. Converrebbe avviarne di più anche se si ha a che fare con una singola applicazione. Il numero delle istanze da avviare, come spiegato nella documentazione di mongrel, è dato da molto fattori: ad esempio dalle risorse hardware, dal numero di richieste per secondo previste, dal tipo di applicazione etc.
Noi utilizzeremo 3 istanze, un numero accettabile per molti casi. Per gestire più istanze in modo semplice ci viene in aiuto mongrel_cluster
. Vediamo come a partire dalla configurazione.
mongrel_Rails cluster::configure -a 127.0.0.1 -p 8000 -N 3 -c /var/www/Rails-apps/test-app -e production
Questo comando scrive un file di configurazione (mongrel_cluster.yml
) nella directory config
della nostra applicazione, con tutti i parametri necessari per l'avvio delle varie istenze. In questo modo a mongrel basterà rileggere quel file di conf per avviare l'applicazione in modo corretto.
Nota: Per una maggiore sicurezza è consigliato avviare mongrel con un utente ed un gruppo appostito
Vediamo in dettaglio i parametri dello script mongrel_cluster:
parametro | significato |
---|---|
-N |
indica il numero di istanza di mongrel da avviare (3 in questo caso) |
-c |
indica la directory sulla quale spostarsi per avviare le varie istanze, di solito quella dall'applicazione stessa |
-a |
indica l'indirizzo sul quale le varie istanze si mettono in ascolto |
-p |
indica la porta iniziale delle varie istanze, ad esempio con '-p 8000 ' avremmo 3 istanze di mongrel alle porte 8000,8001,8002 |
-e |
indica l'environment usato per quella determinata applicazione |
Una volta configurato mongrel_cluster
, proviamo ad avviarlo.
# mongrel_Rails cluster::start starting port 8000 starting port 8001 starting port 8002
Adesso ci occorre solo uno script di inizializzazione che avvii le varie istanze di mongrel per tutte le nostre applicazioni. Ecco una soluzione pulita: creiamo un directory con tutte le configurazioni
# mkdir /etc/mongrel_cluster
facciamo un collegamento delle configurazioni, scritte con 'mongrel_Rails cluster::configure...
', delle applicazioni, per farle elaborare tutte comodamente da un unico percorso.
# ln -s /var/www/Rails-apps/test-app/config/mongrel_cluster.yml /etc/mongrel_cluster/test.yml
# ln -s /var/www/Rails-apps/hyperblog/config/mongrel_cluster.yml /etc/mongrel_cluster/hyperblog.yml
[...]
copiamo lo script di init e rendiamolo avviabile
# cp /PATH/DI/GEMS/mongrel_cluster/resources/mongrel_cluster /etc/init.d/ # chmod +x /etc/init.d/mongrel_cluster
eseguiamolo ad ogni avvio
(per debian, e derivate)
# update-rc.d -f mongrel_cluster defaults
(per redhat, e derivate)
# chkconfig --level 345 mongrel_cluster on
Una volta sistemato mongrel possiamo passare all'integrazione con apache 2, per il bilanciamento del carico.
Integrazione con Apache 2
Assicuriamoci di avere installati i moduli mod_proxy
, mod_proxy_balancer
, mod_rewrite
, mod_deflate
, mod_headers
di apache 2. Dovrebbero tutti essere nell'installazione standard di apache 2.
Ecco una configurazione semplice:
<VirtualHost *:80>
ServerName test.com
DocumentRoot /var/www/Rails-apps/test-app/current/public
<Directory "/var/www/Rails-apps/test-app/current/public">
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory>
<Proxy balancer://mongrel_cluster>
BalancerMember http://127.0.0.1:8000
BalancerMember http://127.0.0.1:8001
BalancerMember http://127.0.0.1:8002
</Proxy>
ErrorLog logs/myapp_errors_log
CustomLog logs/myapp_log combined
</VirtualHost>
La sezione che ci interessa è rappresentata dal 'proxy balancer
' che fa in modo che apache distribuisca equamente il carico tra le diverse istanze di mongrel.
Opzionalmente possiamo pure monitorare il modo in cui vengono gestite le richieste, con un semplice front-end che apache 2 ci mette a disposizione:
Listen 8080 <VirtualHost *:8080> <Location> SetHandler balancer-manager Deny from all Allow from localhost </Location> </VirtualHost>
Abbiamo così terminato tutta la fase iniziale di deployment di un'applicazione Rails. Ma non è finita qui. Rails ci viene, infatti, in aiuto con Capistrano, un potente strumento per l'automazione di tutte le operazioni ripetitive come l'aggiunta di una nuova applicazione, l'aggiornamento, il monitoraggio etc. Ne faremo la conoscenza in uno dei prossimi articoli