Per una tranquillità mentale

By abell on 2009-04-18-15:39:52 | In monitoraggio nagios mon

Lo sviluppatore, se responsabile dell'installazione dei suoi programmi o della gestione dei sistemi, si porta dietro una croce. E' al mare, panza all'aria, cappello di paglia a coprirgli il viso, e in un angolo della mente, a livello appena cosciente, un'inquietudine bisbiglia. Chissà se sarà tutto a posto. Chissà se si sarà riempito un disco, se qualche processo si sarà bloccato, un server spento, un sito caduto. Ogni telefonata potrebbe essere un cliente che chiama per un'emergenza, l'indomani a lavoro potrebbe scoprire che un giorno di log è andato perso. E se i sistemi che gestisce sono vitali e ogni downtime può costare caro, a metà mattinata il nostro si infilerà le infradito e, asciugamano sulla spalla e cappello di paglia in testa, farà una capatina a casa per collegarsi in rete col portatilino e controllare la situazione.

E' per questo che sono nati software di monitoraggio. Un programma tipo nagios viene configurato con i servizi da tenere sotto controllo e in caso di problemi manda degli alert, via email o cellulare. Finché c'è campo e non arrivano SMS, il nostro sviluppatore/amministratore di sistema può stare tranquillo perché (probabilmente) va tutto bene.

Il (mio) sistema di monitoraggio ideale

Esiste uno spettro ampissimo di sistemi di monitoraggio. Si arriva fino ai mostri aziendali, che richiedono team di operatori per l'esercizio e mesi di studio per capirne il funzionamento. Ma si può partire da versioni minimaliste, come la seguente (in bash, da lanciare ogni quarto d'ora via cron):
if ( ping -c 1 my.server.ext | grep time= );
then
  echo ok;
else
  echo "Server non raggiungibile" | mail -s "Problem with my.server.ext" administrator@my.domain.ext;
fi
Quale può essere il giusto mezzo in cui trovare il sistema di monitoraggio campione di virtù? Lo vogliamo potente, ma non troppo complesso da amministrare. Estendibile secondo un protocollo semplice. Capace di comportamenti complessi, ma con default ragionevoli.

La configurazione sarà contenuta in uno o più file testuali. Questo permette facilmente di tenerla sotto controllo di versione, spostarla su altri host e generarla programmaticamente. Possiamo considerare il sistema di monitoraggio come un sistema programmabile, in cui la configurazione è il programma. Vediamo quali tipi di comandi vogliamo che sia in grado di gestire, usando un'ipotesi di linguaggio.

Primo stadio: controlla e segnala ...

Il sistema deve essere in grado di effettuare i controlli standard. Ad esempio, il controllo sulla raggiungibilità di un server:
pings 123.123.123.123
e il controllo sulla raggiungibilità di una pagina web:
webstatus "http://my.home.page/" 200
Il sistema deve essere versatile e permettere la creazione di nuovi tipi di controllo, sotto forma di programmi esterni. Il sistema può rilevare automaticamente tutti i file presenti in una directory (ad esempio /usr/lib/mymon/plugins) e renderli disponibili come comandi. Questi plugin dovranno usare un protocollo che permetta al sistema di interpretare i loro output. Ad esempio, il plugin raidcheck potrebbe effettuare un ssh su un server e controllare che una certa unità raid non presenti problemi.
command raidcheck "user@hostname" "md1"
L'output di raidcheck potrebbe essere OK in caso di controllo riuscito oppure ERR: messaggio d'errore se il controllo non è andato a buon fine.

Ogni qualvolta si verificano errori, viene attivato l'invio di un messaggio, via SMS e/o email. Deve essere possibile configurare i meccanismi di invio

alert sms "123/123456789"
alert email "administrator@my.domain.ext"
Ma cosa verrà inviato esattamente? Il messaggio deve essere il più esplicativo possibile e includere almeno quale dei controlli è andato male e possibilmente tutti i dati diagnostici a disposizione, ma l'sms ha delle limitazioni di lunghezza. Il report generato dai controlli non può essere una semplice stringa, ma deve essere un dato strutturato, da cui i vari meccanismi di alert possano estrarre informazioni del formato e della lunghezza desiderati. Una possibilità è quella di etichettare ogni controllo con uno o più modelli di messaggio e lasciare che ogni sistema di alert scelga quello della lunghezza adatta.
label "p:123.123.123.123" # Versione corta
label "ping 123.123.123.123: %stack" # Versione lunga
pings 123.123.123.123

label "w:my.h.p" # Versione cortissima
label "web:my.home.page" # Versione corta
label "web( http://my.home.page ): %stack" # Versione lunga
webstatus "http://my.home.page/" 200
Se malauguratamente entrambi i controlli dovessero fallire, via SMS potremmo ricevere p:123.123.123.123 web:my.home.page e via email invece il messaggio più esteso, con l'elenco completo dei messaggi d'errore restituiti dai vari controlli.

Secondo stadio: ... ma non esagerare

Già così, il nostro programma di monitoraggio, opportunamente configurato, potrà segnalarci eventuali problemi. Visto che i controlli sono generici e possiamo crearne nuovi tipi, adatti alle nostre esigenze, con script di poche righe, l'unico limite è la nostra fantasia (o paranoia).

Con che frequenza verranno effettuati i controlli? Li vogliamo molto frequenti, chiaramente. Non sia mai detto che perdiamo uno dei potenziali visitatori del nostro blog per un errore di configurazione di Apache. Diciamo, per non volere esagerare, un check ogni 5 minuti. E visto che tutte le pagine del nostro blog sono egualmente importanti, vogliamo che il controllo non ne tralasci nessuna. E poi abbiamo il sito aziendale del nostro cliente da tenere d'occhio, e tre o quattro server sparsi qua e là, e vogliamo verificare che la casella spam non contenga messaggi di nostri amici (già abbiamo perso un paio di feste per colpa di un antispam troppo aggressivo). Quindi, ogni 5 minuti il nostro sistema di monitoraggio dovrebbe scaricare decine o centinaia di pagine web, effettuare scansioni di directory potenzialmente voluminose, collegarsi in ssh a più server su cui lanciare processi vari. Il sistema che dovrebbe garantire la nostra tranquillità potrebbe diventare uno strumento di auto-denial-of-service.

Vogliamo limitare i controlli a uno ogni mezz'ora? Naaaa... Semplicemente, rendiamo il nostro programma abbastanza versatile da gestire i casi d'uso che abbiamo ventilato in maniera intelligente:

frequency "every 2 minutes" ( pings 123.123.123.123 )

limit "blog page" "every 5 minutes"
consumes "blog page" ( webstatus "http://my.interesting.blog/post1" 200 )
consumes "blog page" ( webstatus "http://my.interesting.blog/post2" 200 )
consumes "blog page" ( webstatus "http://my.interesting.blog/post3" 200 )

frequency "daily" ( command checkspammailbox )
Impostiamo frequenze diverse per i ping (ogni 2 minuti) e per il controllo della casella email (una volta al giorno). Inoltre definiamo una risorsa "blog page" che può essere consumata ogni 5 minuti e la associamo alle richieste della varie pagine del blog.

Un'altra cosa che può sfuggire di controllo è la quantità di alert. Se un servizio è offline e per qualche motivo non possiamo porvi rimedio, c'è il rischio di ricevere 12 messaggi l'ora (sms e/o mail) per 24 ore per un totale di 288 messaggi in un giorno. C'è da farsi venire voglia di disattivare il sistema di monitoraggio e tornare ai controlli manuali fatti una volta ogni tanto, secondo l'estro del momento, o ad aspettare le telefonate di clienti furiosi nel momento in cui l'emergenza è ormai arrivata al pettine.

Nagios risolve la questione con una logica delle segnalazioni abbastanza complessa, la distinzione tra vari tipi di errori, downtime programmato, flapping (cioè alternanza rapida tra stati normali e di errore). Giusto e sacrosanto, ma per i miei gusti, rispetto al giusto mezzo che andiamo cercando, tende un po' sul complesso.

Un'alternativa più semplice può essere quella di ripetere l'invio degli alert a intervalli sempre crescenti. E' lo stesso algoritmo che usa ad esempio Postfix per inoltrare le mail in caso di problemi. I controlli vengono effettuati comunque, ma se un servizio è andato giù il secondo alert viene spedito dopo 5 minuti, il seguente dopo altri 10, poi se ne aspettano 20 e così via. In questo caso, per una giornata di downtime i messaggi ricevuti sono 24 contro i 288 dell'approccio ingenuo. Una volta che l'intervallo abbia raggiunto una soglia ragionevolmente lunga (diciamo 12 o 24 ore) si può mantenere costante. Non verrà voglia di disattivare il sistema di monitoraggio, ma si continueranno a ricevere segnalazioni che qualcosa non va. Lo stato di un controllo va memorizzato finché non matura l'invio di alert seguente. Se memorizziamo il numero di successi del controllo, oltre agli errori, abbiamo un'indicazione anche degli stati di flapping. Ad esempio, se sugli ultimi 5 controlli abbiamo avuto 3 errori, possiamo ricevere SMS del tipo

p:123.123.123.123 3/5
oppure, indicando anche l'ordine, qualcosa del tipo
p:123.123.123.123 XOXXO

Allarghiamoci!

Una volta che ci siamo fatti un'idea di come vorremmo fosse il nostro sistema di monitoraggio e ci siamo messi a testa bassa a implementarlo nel linguaggio di nostra scelta, ci verranno in mente mille possibili estensioni, funzionalità, casi d'uso per realtà più grandi. Immagineremo di farlo adottare a grandi società, di mettere su un business di consulenza che ci farà ricchi, aggiungere un'interfaccia web interattiva, spostarlo su cloud. Gli spunti per miglioramenti sono numerosi. A me ne vengono in mente alcuni:

Controlli distribuiti: alcuni controlli potrebbero essere eseguiti su più macchine. Nell'esempio del ping, il programma potrebbe lanciare un controllo locale e poi collegarsi in ssh su un'altro host e lanciare lo stesso controllo da lì, combinando poi i risultati.

pings 123.123.123.123
remotely user@remote.host ( pings 123.123.123.123 )

Controlli di variazione: un tipo di controllo potrebbe essere della forma

nochange ( web "http://my.home.page" )
Si verifica che il contenuto della pagina web non sia cambiato. Alla prima invocazione e ad ogni successiva variazione, l'utente potrebbe avere la possibilità di reimpostare il valore di controllo.

Ma in sostanza

Più o meno sofisticato che sia, fatto in casa o bello e pronto, quello che conta davvero è che il sistema di monitoraggio non scoraggi l'utente dall'usarlo, per complessità di gestione, invadenza degli alert o quantità di falsi allarmi. Come è scritto in una presentazione su mon:
If it failed twice before, write a monitor
Se è già fallito due volte, scrivi un controllo
Meglio sarebbe scrivere dei controlli anche per eventi che ancora non hanno mai dato problemi, ma la procedura per farlo deve essere il più indolore possibile. Come per i backup, le soluzioni tecnologiche sono tantissime. L'importante è sceglierne una e convincersi a usarla con diligenza.