Progetto

Generale

Profilo

SupervisorPerDjango » Cronologia » Versione 2

Versione 1 (Mark Caglienzi, 13-12-2013 17:47) → Versione 2/3 (Simone Piccardi, 11-12-2014 18:21)

h1. Uso di Supervisor per controllare più istanze di Django 

 "Supervisor":http://supervisord.org è presente in Debian, e permette il controllo (avvio, stop, riavvio automatico, logging, eccetera) di programmi che devono essere monitorati nel loro funzionamento. In questa guida si avvieranno e si gestiranno quattro istanze del devserver di un'applicazione Django in locale. 

 Per ogni approfondimento riguardo a supervisor, si rimanda alla "documentazione ufficiale":http://supervisord.org. 

 *NB*: Supervisor "non funziona con Python 3":http://supervisord.org/introduction.html#platform-requirements. 

 h2. Prerequisiti 

 * @# apt-get install supervisor@ 
 * Progetto django in @/home/utente/projects/django/@ 

 h2. Configurazione di supervisor 

 Debian installa supervisor e avvia il demone @supervisord@ con il file @/etc/supervisor/supervisord.conf@ che contiene queste direttive: 

 <pre> 
 ; supervisor config file 

 [unix_http_server] 
 file=/var/run/supervisor.sock     ; (the path to the socket file) 
 chmod=0700                         ; sockef file mode (default 0700) 

 [supervisord] 
 logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log) 
 pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) 
 childlogdir=/var/log/supervisor              ; ('AUTO' child log dir, default $TEMP) 

 ; the below section must remain in the config file for RPC 
 ; (supervisorctl/web interface) to work, additional interfaces may be 
 ; added by defining them in separate rpcinterface: sections 
 [rpcinterface:supervisor] 
 supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 

 [supervisorctl] 
 serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL    for a unix socket 

 ; The [include] section can just contain the "files" setting.    This 
 ; setting can list multiple files (separated by whitespace or 
 ; newlines).    It can also contain wildcards.    The filenames are 
 ; interpreted as relative to this file.    Included files *cannot* 
 ; include files themselves. 

 [include] 
 files = /etc/supervisor/conf.d/*.conf 
 </pre> 

 e come si vede il demone risponde alla unix socket @/var/run/supervisor.sock@, e @supervisorctl@ (software che presenta una shell di controllo) usa questa socket per inviare comandi al demone (che serviranno per monitorare, avviare, riavviare, fermare i servizi configurati). 

 Grazie alla direttiva @[include]@ supervisor carica file di configurazione aggiuntivi dalla directory @/etc/supervisor/conf.d/@, quindi questo file può essere lasciato così (a meno di aver bisogno di settaggi particolari). 

 h3. Creazione del file @django.conf@ 

 Come si vedrà, i file di configurazione di supervisor supportano la sintassi python per fare output di valori come se si scrivesse in una stringa ("qui":http://supervisord.org/configuration.html?highlight=python#configuration-file la pagina che spiega approfonditamente, con esempi, questa funzionalità). 
 Si crei il file @/etc/supervisor/conf.d/django.conf@ per la gestione delle istanze di django (in questo esempio si useranno i devserver): 

 <pre> 
 [program:django] 
 numprocs=4 
 directory=/home/utente/projects/django 
 command=python manage.py runserver 80%(process_num)02d 
 process_name=%(program_name)s_%(process_num)02d 
 user=utente 
 redirect_stderr=true 
 stdout_logfile=/home/utente/projects/django/supervisor_stdout_%(process_num)02d.log 
 stopsignal=KILL 
 stopasgroup=true 
 killasgroup=true 
 </pre> 

 La sezione @[program:django]@ contiene quindi le impostazioni di base per gestire 4 istanze di django. Le singole righe significano: 

 * Numero di processi da avviare. 
 * Directory in cui entrare prima di eseguire il comando. 
 * Comando da eseguire per ogni processo avviato (dato che @numprocs@ è stato specificato, ed è diverso da 1, bisogna che in @command@ sia presente @%(process_num)02d@ per differenziare le righe di comando). In questo esempio, con @numprocs@ che va da 0 a 3, verranno avviati 4 processi alle porte @8000@, @8001@, @8002@, @8003@. 
 * Nome del processo i-esimo. In questo esempio si chiameranno @django_00@, @django_01@, @django_02@, @django_03@. 
 * Utente da usare per lanciare i comandi. In questo esempio @supervisord@ tenta di passare all'utente @utente@, in modo da non lanciare i comandi come utente di @supervisord@ (che potrebbe essere @root@). Se questo tentativo fallisce, il comando non viene eseguito. 
 * Redirigere gli @stderr@ dei processi creati nei rispettivi @stdout@. 
 * File in cui loggare @stdout@. 
 * Le ultime tre righe sono necessarie per far sì che @supervisord@ riesca a killare correttamente i devserver di django senza lasciare processi orfani né bloccare le porte in caso di riavvio di un'istanza. 

 Di default i processi vengono avviati all'avvio di @supervisord@, ma si può impedire (@autostart=false@), si può richiedere che i processi siano sempre riavviati in caso di segnali di @KILL@ (@autorestart@), si possono configurare i timeout di attesa quando un processo cambia stato, il tipi di exit code attesi per discriminare quando un processo esce correttamente o per qualche errore/malfunzionamento (@exit_codes@), eccetera.... 

 h2. Uso di @supervisorctl@ 

 Questo è un programma che può essere usato per inviare comandi una tantum: 

 <pre> 
 # supervisorctl start all 
 </pre> 

 oppure avviato senza parametri perché fornisca una shell da cui poter interrogare @supervisord@: 

 <pre> 
 # supervisorctl  
 django:django_00                     RUNNING      pid 9633, uptime 0:41:34 
 django:django_01                     RUNNING      pid 9634, uptime 0:41:34 
 django:django_02                     RUNNING      pid 9648, uptime 0:41:33 
 django:django_03                     RUNNING      pid 9659, uptime 0:41:32 
 supervisor> help 

 default commands (type help <topic>): 
 ===================================== 
 add      clear    fg          open    quit      remove    restart     start     stop    update  
 avail    exit     maintail    pid     reload    reread    shutdown    status    tail    version 

 supervisor> stop all 
 django_00: stopped 
 django_01: stopped 
 django_02: stopped 
 django_03: stopped 
 supervisor> start all 
 django_00: started 
 django_01: started 
 django_02: started 
 django_03: started 
 </pre> 

 Come si vede qui è possibile interrogare il demone e vedere i processi attivi, fermarli, avviarli, ed è anche presente un help in linea. 

 Se @supervisord@ è stato avviato da @root@, e nel file @supervisord.conf@ il setting @chmod@ è 0700, ovviamente un utente non privilegiato non potrà accedere alla socket di interrogazione, e @supervisorctl@ andrà lanciato da @root@ (come nell'esempio qui sopra). 


 h2. Impostazione di invio di email di avviso e di allarme via supervisor.  

 Il pacchetto @superlance@ consente agganciare a @supervisor@ degli utili script che consentono di osservarne gli eventi per eseguire opportune azioni. Due di questi sono particolarmente utili, il primo per notificare crash di un servizio osservato, il secondo per avvisare di un servizio fermo per un fallimento fatale. Per poterlo utilizzare è anzitutto necessario installare il relativo pacchetto python con: 

 <pre> 
 easy_install superlance 
 </pre>  

 che instellerà tutto il necessario, compresi gli script che ci interessano che verranno posti sotto @/usr/local/bin/@. 

 A questo punto basterà registrare sull'eventlistner di @supervisor@ i due script che ci interessano; il primo è @crashmail@, che spedisce una email tutte le volte che un servizio esce inaspettatamente con un errore, contenente il nome del servizio e le relative informazioni, per questo basta aggiungere a @/etc/supervisor/supervisord.conf@ qualcosa del tipo: 

 <pre> 
 [eventlistener:crashmail] 
 command=/usr/local/bin/crashmail -a -m piccardi@truelite.it 
 events=PROCESS_STATE 
 </pre> 

 in questo caso in genere il servizio viene riavviato automaticamente da @supervisor@. 

 Il secondo script, @fatalmailbatch@, tiene invece sotto ossevazione gli eventi ed invia una email di allarme (su un periodo di un minuto) quando rileva che un servizio si ferma nello stato @FATAL@, segno che @supervisor@ ha fallito nel tentativo di farlo ripartire, in questo caso occorre aggiungere a @/etc/supervisor/supervisord.conf@ qualcosa del tipo: 

 <pre> 
 [eventlistener:fatalmailbatch] 
 command=/usr/local/bin/fatalmailbatch --toEmail="piccardi@truelite.it" --fromEmail="supervisor@truelite.it" --subject="Alarm for a fatal crash" 
 events=PROCESS_STATE,TICK_60 
 </pre> 

 Si possono ovviamente attivare entrambe le notifiche aggiungendo entrambe le sezioni indicate.