Salta al contenuto

Blog ·

Un agent vero, un gateway di sviluppo

Cinque tornate si sono chiuse con la stessa riserva: non provato sul filo. Chiuderla ha richiesto un agent vero, una password piantata e due misure vuote.

Di Provibr

Cinque tornate di fila hanno chiuso il proprio resoconto con una variante della stessa frase: la modifica al protocollo è additiva, i test unitari sono verdi, e nulla di tutto ciò è stato esercitato contro un agent vero. Adattatori di monitoraggio, la busta sigillata, gli aggiornamenti automatici dell’agent, un passo di automazione che attende un comando. Tutti e cinque erano corretti per quanto si potesse vedere, e tutti e cinque portavano una riserva che la tornata seguente ereditava.

Quella riserva costa poco da scrivere e si accumula. Ogni tornata ne aggiunge una, nessuno ha torto, e dopo cinque volte resta una pila di comportamenti esistiti solo dentro un banco di prova. Questa tornata è servita a togliere la pila anziché ad accrescerla: nessuna funzione, nessuna modifica al protocollo, nessuna pubblicazione. Ottantadue misure contro un agent vero.

L’allestimento, in una frase

Un vero eseguibile dell’agent, compilato per la stessa destinazione che distribuiamo, firmato con una chiave di sviluppo, in esecuzione dentro un contenitore usa e getta su una macchina che non è il portatile di nessuno, in dialogo con un gateway di sviluppo attraverso un tunnel inverso, con sette servizi usa e getta sul ciclo locale da misurare e una seconda copia dello stesso eseguibile iscritta come sonda ospitata.

Tutto in quella frase regge peso. L’eseguibile è quello distribuito e non una compilazione di prova, perché i guasti interessanti abitano la serializzazione e TLS, non la logica. Il gateway è di proposito un’istanza di sviluppo su porte diverse, perché quello di produzione ascolta su quelle ovvie, e un agent che bussasse dal lato sbagliato sarebbe un pomeriggio molto brutto. I servizi sono contenitori usa e getta con il software vero in versioni vere e non imitazioni, perché tutto il senso dell’esercizio è che le imitazioni sono proprio ciò che già avevamo.

I servizi di base dati hanno ricevuto una password canarino, e quella scelta ha reso possibile la sezione seguente.

GruppoMisureChe cosa risolve
Adattatori di monitoraggio44Sei protocolli di base dati e di directory, credenziali giuste e sbagliate, e lo stato di regola che ne segue
Aggiornamenti automatici19Pianificare, applicare, riavviare e rifiutare una compilazione manomessa
Passo di automazione11Un comando che finisce entro l’attesa e uno che non lo fa
Sonda ospitata4Lo stesso eseguibile iscritto come sonda di piattaforma anziché come agent cliente
Sorgente assente4Un agent scollegato produce uno stato proprio, mai un guasto falso

Una ricerca con un valore piantato

L’affermazione che più volevamo mettere alla prova è una negazione: un segreto di monitoraggio viaggia sigillato e non viene mai scritto nella riga del comando, nel registro eventi, nel bus dei messaggi né in alcuno dei due registri di processo.

Le negazioni sono le affermazioni che sbagliano in silenzio. Le password non erano dunque stringhe casuali la cui assenza non prova nulla; erano valori piantati, scelti perché una sola occorrenza da qualche parte risultasse inconfondibile. Poi sono stati perlustrati sette strati: i carichi di comando conservati, la tabella degli eventi, la configurazione di controllo conservata, i risultati conservati, il bus dei messaggi in testo e in forma codificata, il registro del gateway e quello dell’agent. In tutto, circa mezzo milione di caratteri di materiale.

Zero occorrenze, che è la risposta desiderata e anche quella che dà una ricerca rotta.

La stessa ricerca è stata perciò lanciata su un file che di certo conteneva la parola, e l’ha trovata. Quel controllo positivo è la differenza fra «abbiamo cercato e non c’era nulla» e «non abbiamo cercato». Costa una riga ed è la riga più preziosa dello script.

Altre due condizioni coprono lo stesso guasto dall’altro capo: l’esecuzione deve osservare almeno una dozzina di comandi di controllo veri e alcune decine di messaggi del bus prima di poter concludere alcunché. Entrambe sono state rosse a un certo punto della tornata, su passaggi che altrimenti avrebbero annunciato una spazzata pulita su assolutamente nulla. Una spazzata che non trova violazioni in un insieme vuoto non è una prova, e assomiglia esattamente a un successo.

Due modi di essere verdi senza misurare

Entrambi sono accaduti in questa tornata, in script scritti da chi conosce questa forma di guasto e ne scrive con regolarità.

Il primo: una query ha selezionato una colonna e il codice ha poi letto un’altra proprietà sulle righe del risultato. In un linguaggio tipato è un errore; qui è undefined, per sempre, in silenzio, e ogni confronto con quel valore fallisce in un modo che sembra un’asserzione che non scatta mai anziché una che è sempre vera. Il controllo ha annunciato successo perché non aveva nulla da confrontare.

Il secondo: una prova di appartenenza contro un elenco vuoto. È un’affermazione su nulla, si soddisfa banalmente, ed è lo stato finale naturale di ogni script il cui passo precedente ha prodotto in silenzio zero righe. Entrambi si coprono a poco prezzo: verificare la forma di ciò che si è recuperato e verificare che l’insieme da esaminare non sia vuoto.

Cinque nomi di colonna in quegli script erano tirati a indovinare anziché consultati. Quelli sono falliti rumorosamente, che è la variante a buon mercato dello stesso errore, ma è lo stesso errore: un comando dice come si chiama una colonna, e la versione in cui una supposizione finisce in un elenco che nessuno esegue è quella che sopravvive alla revisione.

Un agent che rifiuta di iscriversi due volte

A metà delle prove di aggiornamento l’agent ha smesso di tornare. Da fuori sembrava un ciclo di riavvio, e la prima ora è finita nel percorso di aggiornamento.

L’agent faceva esattamente la cosa giusta. L’iscrizione scrive un file di stato, e lo script di installazione generato controlla quel file e rifiuta di iscriversi di nuovo se è presente. Reiscrivere un host già iscritto sostituisce un’identità, e farlo per sbaglio è il modo in cui una macchina perde certificato e cassaforte in un solo passo. Il nostro ciclo di sorveglianza, scritto per l’occasione, non aveva quel varco, e ogni tentativo di riavvio incontrava il rifiuto proprio e corretto dell’agent.

La lezione non riguarda quel varco. Riguarda il fatto che un rifiuto corretto e un difetto hanno da lontano la stessa forma, e che a separarli è leggere ciò che l’altra parte ha davvero detto anziché ciò che il sintomo suggeriva.

Dagli stessi giorni sono venute altre tre sorprese, tutte e tre decisioni di progetto che incontrano la realtà:

Gli orari di aggiornamento pianificati vivono su una griglia di cinque minuti, imposta da un vincolo di base dati. «Fra un minuto», che è quel che vuole chi scrive una prova, non esiste. A renderlo praticabile è una finestra di recupero: un orario mancato viene comunque eseguito per un quarto d’ora dopo. È anche il motivo per cui una misura ripetuta nello stesso quarto d’ora deve scegliere un orario di griglia inutilizzato, poiché ogni orario viene rivendicato in modo unico per agent e un secondo passaggio sullo stesso viene rifiutato a ragione.

Un controllo TCP nasce con TLS attivo. Puntato su una porta in chiaro fallisce con un errore TLS, il che è corretto e si legge come un controllo rotto finché non si guarda che cosa sia un valore predefinito.

E la riga di verifica di un passo di automazione la cui attesa è scaduta si congela sullo stato che il flusso ha visto. Il comando è passato a scadenza sessanta millisecondi dopo e la riga ha continuato a dire ciò che diceva. Non è un difetto della riga, è un difetto del commento sopra di essa, che prometteva di leggervi l’esito finale. Quella promessa è stata rimossa e affrontata come si deve altrove.

Una notifica che raggruppa e un conteggio che dice zero

Il più tagliente dei piccoli reperti. Dopo un aggiornamento riuscito la piattaforma scrive una notifica. La misura ha contato le notifiche create dall’inizio dell’esecuzione e ha ottenuto zero.

Le notifiche raggruppano. Una seconda occorrenza della stessa cosa incrementa un contatore sulla riga esistente e lascia intatta la sua data di creazione, che è esattamente ciò che si vuole in un pannello: «questo agent è caduto» con un numero accanto anziché quaranta righe. È anche esattamente ciò che fa sì che un conteggio sulla data di creazione non annunci nulla mentre la notifica è lì in bella vista.

La misura sbagliava, il prodotto aveva ragione, e l’unico motivo per cui sappiamo in quale verso fosse è che qualcuno ha aperto il pannello invece di credere alla query. Ogni aggregazione ha una forma, e una prova che non la conosce mette alla prova la propria ipotesi.

Che cosa annoteremmo

  1. «Non provato sul filo» è un debito, e si accumula. Una tornata può portarlo. Cinque tornate sono una pila di comportamenti mai esistiti fuori dal banco di prova.
  2. Provare una negazione con un valore piantato e un controllo positivo. Senza di esso, zero occorrenze e una ricerca rotta sono indistinguibili.
  3. Dare a ogni spazzata un fondo. Verificare che l’ingresso non sia vuoto prima di concluderne qualsiasi cosa.
  4. Un rifiuto corretto da lontano sembra un difetto. Leggere ciò che ha detto l’altra parte prima di riscrivere la propria.
  5. Non indovinare né un nome di colonna, né un valore predefinito, né una griglia. Tutti e tre sono a un comando di distanza, e la supposizione che raggiunge un elenco è quella che non scatta mai.
  6. Conoscere la forma di ciò che si conta. Le righe raggruppate non portano la data di creazione su cui si filtra.

Per chiarezza: in questa tornata non è stato pubblicato nulla. Nessuna modifica al prodotto, nessuna modifica al protocollo, nessuna pubblicazione dell’agent. Ne è uscito che cinque riserve sono sparite e una manciata di piccoli difetti sono corretti, e la pulizia è stata ricontata anziché supposta: nessuna riga rimasta, nessun contenitore rimasto, nessun file rimasto.

Alcune cose sono rimaste non provate. Il percorso di iniezione dell’automazione è stato esercitato dal suo nucleo e non dal pannello, gli adattatori non hanno girato da una sonda ospitata, e continua a mancare una misura contro un hypervisor vero.

Dal lavoro di piattaforma su Provibr. Perché il segreto di monitoraggio viene sigillato a ogni tentativo si trova in un segreto che viaggia una volta sola, e come un aggiornamento firmato dell’agent rifiuta una compilazione manomessa in come un aggiornamento firmato dell’agent rifiuta sé stesso.

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.