Salta al contenuto

Blog ·

Un incidente che non si chiude sul silenzio

Un incidente di monitoraggio deve aprirsi su una misurazione e chiudersi su una misurazione. Ecco cosa si rompe se l’assenza di dati vale come buona notizia.

Di Provibr

Ogni sistema di monitoraggio prima o poi affronta la stessa domanda con un costume leggermente diverso: che cosa si fa quando le misurazioni smettono di arrivare?

La risposta allettante è trattarlo come un ripristino. Non sta più fallendo nulla, la riga rossa sparisce, la dashboard è tranquilla. È anche la bugia più costosa che il sistema possa dire, perché il momento in cui si smette di poter guardare una cosa è esattamente il momento in cui non si deve sostenere che stia bene.

Questo è il progetto a cui siamo arrivati per gli incidenti, e in gran parte riguarda il tenere «abbiamo misurato che è rotto», «abbiamo misurato che è a posto» e «adesso non riusciamo a vederlo» come tre affermazioni distinte che non diventano mai in silenzio l’una l’altra.

Perché l’incidente è un oggetto

Prima di questo, un’interruzione era una serie di righe in una tabella di transizioni di stato. Basta a disegnare un grafico e non basta a dire alcunché. Tre cose esistono solo quando c’è un oggetto.

Una durata. Il messaggio di ripristino non portava alcuna durata, perché non c’era nulla con cui riempire il parametro. Un incidente ha un inizio, quindi la durata è una misurazione e non una stima.

Uno strato umano. Prendere in carico, assegnare e chiudere a mano sono cose che fanno le persone, e non devono toccare lo stato misurato. Una colonna acknowledged_at su una misurazione confonderebbe esattamente la linea su cui è costruita tutta questa funzionalità.

Deduplicazione nel tempo. Una notifica quando si apre, promemoria su un proprio orologio, al massimo una escalation. Senza un oggetto non c’è nulla a cui appendere il «te l’ho già detto», e allora ogni tick è un’altra occasione per dirglielo di nuovo.

La deduplicazione è un indice

L’unicità che impedisce l’esistenza di due incidenti per una stessa regola è un indice unico parziale sulla regola, dove la marca temporale di risoluzione è nulla. Due gateway che elaborano la stessa transizione producono un solo incidente per costruzione; il secondo riceve una violazione di unicità e tira dritto.

Il codice che controlla se ne esista già uno e poi inserisce è fatto di due istruzioni, cioè di due occasioni perché qualcosa si infili in mezzo. È la stessa forma dell’indice degli slot dello scheduler e dell’indice di occupazione dei rack altrove in questo prodotto, e per la stessa ragione.

Qui c’è stato anche un bug davvero imbarazzante, che vale la pena mettere per iscritto perché in revisione è invisibile. La chiave di deduplicazione della notifica era costruita a partire dalla regola, dal nuovo stato e dalla marca temporale corrente. Una chiave che contiene la marca temporale corrente non deduplica nulla, per costruzione, e sullo schermo sembra del tutto ragionevole. Adesso è l’identificatore dell’incidente. Misurato dopo: tre fallimenti consecutivi producono un incidente e una notifica, e altri tre non cambiano niente.

Tre modi in cui un incidente può finire, e uno solo è una misurazione

RisoluzioneChe cosa affermaChe cosa viene registrato con essa
recoveredabbiamo misurato di nuovo uno stato sanol’esito che lo ha chiuso, conservato sulla linea temporale
configuration_retiredla regola che lo ha aperto non misura piùnessuna, e nessuna viene affermata
manuallo ha chiuso una personachi, e volendo perché

Quella di mezzo è il senso dell’elenco. Una regola che venga sostituita da una revisione del modello deve chiudere i propri incidenti aperti, e deve farlo senza una falsa misurazione di ripristino. Se l’unica risoluzione disponibile fosse recovered, sostituire un modello scriverebbe in silenzio «questo è tornato su» nella storia di ogni servizio che in quel momento era giù.

Non esiste deliberatamente una risoluzione stale. Che le misurazioni abbiano smesso di arrivare non dice nulla sul bersaglio.

Quali transizioni toccano davvero un incidente

Un incidente pende da un’affermazione sul bersaglio. Perciò una transizione verso «source unavailable», cioè il nostro stesso agente è sparito, non apre nulla e, cosa più importante, non chiude nulla. Se un agente che se ne va potesse chiudere un incidente, un’interruzione in corso sparirebbe dalla vista nell’esatto istante in cui abbiamo perso la capacità di guardarla.

Una transizione verso «configuration error» si comporta allo stesso modo: la regola non descrive più nulla di misurabile, il che è un’affermazione su di noi e non sul servizio.

«Degraded» invece chiude un incidente. Il servizio risponde, la condizione conta come sana, solo la latenza è alta. Lasciarlo aperto farebbe di un servizio lento un’interruzione perennemente aperta, promemoria compresi.

Sotto tutto questo, da una tornata precedente, sta una distinzione netta fra una sorgente irraggiungibile e un bersaglio che è giù. Un controllo il cui agente non è connesso produce «source unavailable» e mai «down». Tutto quanto sopra è quella stessa regola, un livello più in alto.

La manutenzione mette a tacere le notifiche e continua a misurare

Una finestra di manutenzione sopprime le notifiche. Non sopprime la misurazione. L’incidente si apre lo stesso, la linea temporale scorre lo stesso, e solo il messaggio resta nel cassetto.

Non è un dettaglio. La domanda che le persone fanno dopo una finestra di manutenzione è «è tornato in orario», e quella domanda è senza risposta se si è smesso di misurare proprio mentre contava. C’è una casella di spunta separata ed esplicita che mette davvero in pausa i controlli, ed è disattivata per impostazione predefinita; con quella, lo scheduler salta la presa dello slot, quindi nulla diventa esigibile e nulla viene perso. Ciò che resta dopo è un unico marcatore di lacuna, come per qualunque altra lacuna. Non c’è recupero a posteriori.

La finestra in sé è conservata come intervallo assoluto con accanto un fuso orario IANA. Il cliente inserisce l’ora dell’orologio a muro e vuole rileggere la stessa ora dell’orologio a muro, anche se il pannello visualizza in un fuso fisso. Conservare invece l’ora locale più il fuso costringerebbe ogni lettore, scheduler, ingestione e schermata allo stesso modo, a rifare la conversione, e allora un passaggio all’ora legale è un’ora di disaccordo fra due di loro.

Dove due finestre si sovrappongono, vince quella che mette in pausa i controlli. Quando un cliente ha fatto esplicitamente una scelta più severa da qualche parte, quella è la scelta da onorare.

Promemoria, escalation e l’ordine di due istruzioni

Sia l’intervallo dei promemoria sia il ritardo dell’escalation vivono sulla revisione della regola e non sull’incidente, perché sono configurazione e la configurazione appartiene alla revisione che l’ha registrata. Se si cambia la politica durante un’interruzione, l’incidente in corso resta sotto la politica con cui si è aperto.

Entrambi sono disattivati per impostazione predefinita. Un valore predefinito che sveglia le persone di notte è una decisione che il cliente non ha preso.

Prendere in carico mette a tacere i promemoria, e questa è l’intera funzione della presa in carico. Chi dice «ci sto guardando» non deve essere interrotto ogni pochi minuti. La notifica di ripristino arriva comunque, perché è la risposta alla domanda che quella persona stava guardando. Anche l’orologio dei promemoria parte dall’ultimo promemoria e non dall’inizio, così un worker che recupera dopo un’ora non consegna dodici promemoria in una volta sola.

Il worker scrive prima la marca temporale e manda dopo il messaggio, e l’aggiornamento pretende che lo stato sia ancora quello che aveva letto. Se si perde quella corsa, qui non succede nulla. Nell’ordine opposto, una corsa persa produce un messaggio di cui non resta traccia, e allora il messaggio arriva di nuovo alla tornata successiva.

L’escalation avviene al massimo una volta per incidente, e il controllo che lo garantisce vive nella regola condivisa e non nel worker. Senza di esso, ogni passaggio scriverebbe un altro evento di escalation per tutta la durata dell’interruzione: trenta all’ora con un polling di due minuti.

Il flapping è l’eccezione, e si decide quando l’incidente si apre: tre incidenti sulla stessa regola nell’arco di un’ora. Un controllo in flapping per definizione non ha mai un incidente che resti aperto a lungo, quindi qualunque escalation basata sul tempo lo manca per sempre. Tre e non due, perché due volte è sfortuna e una soglia di due chiamerebbe flapping ogni normale riavvio di un servizio. Un’ora e non un giorno, perché tre interruzioni distribuite su una giornata di lavoro sono tre interruzioni.

La durata è un numero e un’unità

Il messaggio di ripristino porta con sé quanto è durata, come valore e come unità, mai come frase. Se il worker componesse da sé «1 hour 12 minutes», quel frammento inglese starebbe in mezzo a una frase tradotta in altre otto lingue. Ciò che viaggia è invece un’unità su cui la traduzione fa la sua scelta, con un plurale dentro ogni ramo.

Un’unità sola, niente composti: un composto ha bisogno di un separatore e di un ordine, e questi cambiano da lingua a lingua. Secondi sotto il minuto, minuti fino a due ore, ore fino a due giorni, giorni oltre. Novanta minuti si legge in modo più netto di due ore, e arrotondare per eccesso farebbe durare due ore un’interruzione di 89 minuti.

Due conseguenze oneste che non abbiamo risolto

«Down», ripristino e promemoria condividono una chiave di gruppo delle notifiche, perché un promemoria è letteralmente lo stesso soggetto un’altra volta e deve aggiornare la riga esistente invece di aggiungerne una a ogni scatto dell’orologio. Il costo è che un promemoria aggiorna una riga che qualcuno ha già letto, ed è quindi invisibile a quella persona. L’escalation riceve un proprio gruppo esattamente per questa ragione: il messaggio che deve arrivare più forte non deve essere quello sovrascritto per primo. Oggi le notifiche di monitoraggio non escono per posta elettronica.

Che cosa metteremmo per iscritto

  1. Non lasciare mai che l’assenza di dati chiuda qualcosa. Dare al «non riusciamo a vederlo» uno stato proprio e assicurarsi che non apra né chiuda un incidente.
  2. Dare all’incidente un oggetto non appena si vuole una durata, una presa in carico o un secondo messaggio sulla stessa cosa.
  3. Mettere la deduplicazione in un indice unico, e controllare che la chiave della notifica non contenga l’ora corrente.
  4. Enumerare i modi in cui un incidente può finire, e pretendere prove solo dove le prove vengono affermate.
  5. Sopprimere le notifiche durante la manutenzione, non le misurazioni, e fare della pausa dei controlli una scelta separata, esplicita e disattivata per impostazione predefinita.
  6. Aggiornare lo stato, poi mandare il messaggio. L’ordine opposto perde messaggi in silenzio.

Questo lavoro sta dietro un flag di rollout disattivato per impostazione predefinita, quindi niente di tutto ciò è qualcosa da acquistare oggi. È scritto come metodo e non come annuncio. Lo strato di misurazione che ci sta sotto, compreso il perché un agente irraggiungibile non sia un servizio guasto, è una storia a sé, e la domanda strettamente collegata di quando una piattaforma possa affermare un tempo sta in una barra di avanzamento che non indovina.

Dal lavoro di piattaforma di Provibr.

Inizi con un host e un agente

Crei un account, installi l’agente con un solo comando e colleghi il suo primo host Proxmox. Il periodo di prova dura 14 giorni e non chiede alcun dato di pagamento.