Torna al blog Security & Reliability

Controlli di integrità delle applicazioni self-hosted: cosa dovrebbe significare davvero “sana”?

Un quadro pratico per definire controlli di integrità che riflettano risultati reali per gli utenti, distinguano avvio, vitalità e disponibilità al traffico e tengano conto delle dipendenze senza trasformare ogni guasto esterno in un’interruzione dell’applicazione.

Diagramma che mostra controlli di avvio, vitalità, disponibilità al traffico, dipendenze e lato utente per un’applicazione self-hosted

Perché un URL raggiungibile non corrisponde necessariamente a un’applicazione sana

Il fatto che un browser raggiunga un URL HTTPS e riceva HTTP 200 è un’indicazione utile, ma non una definizione completa di integrità. Può dimostrare che una route, un proxy o un gestore dell’applicazione ha risposto a una richiesta. Non dimostra necessariamente che gli utenti possano accedere, leggere dati aggiornati, salvare modifiche, caricare file, inviare lavoro a una coda o usare un’integrazione necessaria.

È comune anche l’errore opposto: considerare una connessione non riuscita a una qualsiasi dipendenza come prova che l’intera applicazione non sia disponibile. Un’API opzionale temporaneamente irraggiungibile potrebbe influire su una funzionalità, mentre gli utenti possono comunque svolgere il loro lavoro più importante. Una progettazione utile dei controlli di integrità distingue questi casi, anziché ridurre ogni condizione a un singolo indicatore verde o rosso.

Docker rende esplicita questa distinzione: un container può essere in esecuzione mentre il server web al suo interno è bloccato e incapace di gestire nuove connessioni. Kubernetes separa analogamente le probe finalizzate a stabilire se un’applicazione si è avviata, se debba essere riavviata e se debba ricevere traffico. Questi concetti forniscono un vocabolario iniziale solido, ma i controlli corretti dipendono comunque dal comportamento documentato di ciascuna applicazione e dai flussi di lavoro che avete testato.

  • Un controllo dell’URL può stabilire la raggiungibilità esterna, non la piena capacità del servizio.
  • Un container o un processo in esecuzione è un indizio operativo, non la prova che sia pronto per gli utenti.
  • Un guasto di una dipendenza deve essere classificato in base al suo effetto sui flussi di lavoro reali.
  • La definizione migliore di sano è specifica: il lavoro previsto può essere completato entro i confini che avete scelto di monitorare.
Perché un URL raggiungibile non corrisponde necessariamente a un’applicazione sana

Ponete tre domande diverse: avvio, vitalità e disponibilità al traffico

Non chiedete a un singolo controllo di rispondere a ogni domanda operativa. Kubernetes documenta tre tipi distinti di probe. Una startup probe stabilisce se l’applicazione in un container si è avviata; quando è configurata, impedisce le probe di vitalità e disponibilità al traffico finché non ha successo. Questo è importante per le applicazioni che richiedono tempo per inizializzarsi prima che se ne possa valutare il normale funzionamento.

Un segnale di vitalità risponde alla domanda se l’applicazione in esecuzione stia ancora facendo progressi in misura tale da rendere opportuno un riavvio. Kubernetes descrive le liveness probe come un modo per decidere quando riavviare un container e cita come esempio un deadlock: il processo esiste, ma non può progredire. Poiché un controllo di vitalità difettoso può riavviare container sotto carico e contribuire a guasti a cascata, dovrebbe essere volutamente ristretto e prudente.

Un segnale di disponibilità al traffico risponde alla domanda se l’applicazione possa attualmente accettare il traffico che intendete inviarle. Kubernetes osserva che la disponibilità al traffico può riflettere guasti temporanei o sovraccarico e che una readiness probe non riuscita impedisce ai Service corrispondenti di inviare traffico al Pod interessato. In un ambiente self-hosted senza Kubernetes, i meccanismi sono diversi, ma la decisione resta utile: gli utenti o i sistemi a monte dovrebbero essere indirizzati a questa istanza proprio ora?

  • Avvio: l’inizializzazione è stata completata a sufficienza perché inizino i normali controlli?
  • Vitalità: il processo dell’applicazione sta facendo progressi o è necessario un intervento come il riavvio?
  • Disponibilità al traffico: questa istanza può ricevere in sicurezza il traffico previsto ora?
  • Disponibilità lato utente: un utente esterno può completare un’azione rappresentativa e consentita?
  • Integrità delle dipendenze: i servizi richiesti dai flussi di lavoro critici rispondono come previsto?
Ponete tre domande diverse: avvio, vitalità e disponibilità al traffico

Partite dai percorsi utente, non dagli endpoint

Il modo più affidabile per definire controlli di integrità delle applicazioni self-hosted è iniziare dai risultati di cui gli utenti hanno bisogno, anziché dall’endpoint più facile da interrogare. Elencate i percorsi che contano per l’istanza specifica. Un sito di pubblicazione può dare priorità alla distribuzione delle pagine pubbliche e agli aggiornamenti editoriali. Un CRM può dare priorità all’accesso, alla ricerca di record, alla creazione di record e alle comunicazioni in uscita. Un’applicazione di IA può richiedere accesso, richieste di recupero o al modello, ingestione di file ed elaborazione in background.

Per ogni percorso, descrivete il test sicuro più piccolo che dimostri che funziona. Un test dovrebbe evitare di modificare inutilmente dati di produzione, esporre credenziali o generare azioni esterne indesiderate. Se la documentazione dell’applicazione non definisce un endpoint, un comando o un flusso di lavoro con account di test adatto, trattatelo come un’incertezza da risolvere tramite la documentazione del fornitore e test controllati, non come un permesso di presumere che un URL generico dimostri la disponibilità al traffico.

Non tutti i percorsi devono rientrare nello stesso avviso. L’impossibilità di creare record è diversa dall’indisponibilità di un’integrazione opzionale di analisi. Lo scopo è rendere visibile questa distinzione prima che un incidente costringa chi risponde a determinarla sotto pressione.

  • Accesso: un utente autorizzato può stabilire una sessione attraverso il percorso di identità previsto?
  • Lettura dei dati: gli utenti possono recuperare i record, le pagine o i risultati di cui hanno bisogno?
  • Scritture: un utente autorizzato può creare o aggiornare un elemento rappresentativo?
  • Caricamenti e archiviazione: l’applicazione può accettare e recuperare un oggetto di test quando ciò è critico?
  • Elaborazione in background: le attività in coda o pianificate vengono completate quando il flusso di lavoro ne dipende?
  • Integrazioni: un’interazione necessaria con identità, email, pagamenti, IA o API esterna può essere completata?

Mappate i componenti dietro ogni percorso critico

Un percorso fallisce attraverso una catena, non attraverso un singolo processo applicativo. Mappate i componenti diretti che partecipano a ogni flusso di lavoro critico: processo dell’applicazione, database, cache, archiviazione persistente, coda o worker, servizio di identità, percorso email e API esterne. Il SRE Workbook di Google raccomanda di monitorare le dipendenze dirette perché possono cambiare o presentare problemi anche quando l’applicazione stessa non è cambiata.

Questa mappa rende i controlli più diagnostici. Se l’accesso pubblico non funziona ma il controllo operativo interno dell’applicazione ha successo, esaminate routing, DNS, TLS o il percorso tra utente e applicazione. Se l’applicazione è raggiungibile ma un test di scrittura non riesce, ispezionate il database, l’archiviazione, le autorizzazioni, la capacità o il percorso della coda pertinente a quella scrittura. Il segnale di integrità dovrebbe aiutare chi risponde a restringere la domanda successiva, non limitarsi ad annunciare che qualcosa non va.

Includete anche le risorse con limiti rigidi o pratici. Le linee guida SRE di Google citano RAM, disco, quota CPU, descrittori di file, thread, tempo di attesa nella coda e volume dei log. Il monitoraggio delle risorse non sostituisce i controlli dei flussi di lavoro, ma può rivelare un guasto imminente prima che un percorso critico si interrompa.

  • Per ogni flusso di lavoro, registrate le dipendenze dirette e la direzione dell’impatto.
  • Identificate se ogni dipendenza è interna, gestita da un altro team o esterna.
  • Registrate i limiti di risorsa pertinenti e come chi risponde può ispezionarli.
  • Individuate l’insieme minimo di segnali necessario per distinguere i percorsi di guasto comuni.

Scegliete controlli di vitalità superficiali e controlli di disponibilità al traffico limitati

Un controllo di vitalità dovrebbe di norma stabilire che l’applicazione stessa possa rispondere o fare progressi, senza renderla ostaggio di ogni servizio a valle. Il suo scopo non è certificare ogni funzione aziendale; è evitare di lasciare indefinitamente in esecuzione un’applicazione realmente bloccata. Quando un’applicazione pubblica un endpoint di vitalità o un comando di integrità documentato, usate la documentazione come punto di partenza e testatene il comportamento effettivo nel vostro ambiente.

La disponibilità al traffico può opportunamente essere più approfondita. Kubernetes documenta un modello per le applicazioni con dipendenze back-end rigorose: la vitalità può riguardare l’applicazione stessa, mentre la disponibilità al traffico verifica anche i servizi back-end necessari, impedendo che il traffico raggiunga istanze capaci solo di restituire errori. La parola necessario è importante. Includete una dipendenza nella disponibilità al traffico quando la sua assenza impedisce al traffico previsto di avere successo, non semplicemente perché esiste.

Mantenete delimitati i controlli approfonditi. Un controllo di disponibilità al traffico che esegue una query costosa, scrive record di produzione o chiama ogni API di terze parti può creare carico, guasti rumorosi e risultati ambigui. Preferite una verifica limitata e rappresentativa, allineata allo scopo del controllo. Se l’applicazione non offre un’interfaccia di integrità documentata, usate un controllo esterno del flusso di lavoro progettato con attenzione e documentatene i vincoli.

  • Usate endpoint o comandi di integrità dell’applicazione documentati solo dopo averne verificato la semantica per l’applicazione distribuita.
  • Mantenete la vitalità concentrata sul progresso dell’applicazione e su decisioni di riavvio sicure.
  • Aggiungete una dipendenza alla disponibilità al traffico solo quando è necessaria per il traffico ammesso.
  • Evitate test costosi, distruttivi o con ampia diramazione nei controlli frequenti.
  • Usate più segnali mirati anziché un unico endpoint di integrità sovradimensionato ogni volta che ciò produce decisioni più chiare.

Definite una policy sulle dipendenze prima che si verifichino i guasti

Per ogni dipendenza, decidete in anticipo la sua classe operativa. Una dipendenza bloccante significa che gli utenti non possono completare un flusso di lavoro critico senza di essa. Una dipendenza degradante significa che una funzionalità è compromessa, ma l’applicazione può comunque fornire il suo servizio primario. Una dipendenza solo per avviso merita attenzione, ma non dovrebbe da sola modificare lo stato di disponibilità lato utente dell’applicazione.

Questa policy evita due estremi dannosi. Il monitoraggio basato solo sulle porte non rileva un sistema che accetta connessioni ma non può svolgere un lavoro utile. D’altra parte, un controllo di disponibilità al traffico tutto-o-niente può dichiarare un’applicazione non disponibile ogni volta che un servizio opzionale è lento o temporaneamente irraggiungibile. Entrambi portano a decisioni scadenti durante gli incidenti: il primo produce falsa fiducia, mentre il secondo genera interruzioni inutili e affaticamento da avvisi.

La policy dovrebbe dichiarare la conseguenza, non solo il controllo. Se una dipendenza è bloccante, decidete se il traffico debba essere trattenuto, se la funzionalità interessata debba risultare chiaramente non disponibile o se sia necessaria un’azione di ripristino. Se è degradante, definite come utenti e addetti alla risposta riconoscono la modalità ridotta. Se è solo per avviso, identificate chi è responsabile del follow-up e perché non blocca il flusso di lavoro critico.

  • Bloccante: il guasto impedisce un flusso di lavoro critico nominato; può rendere l’istanza non pronta per il traffico previsto.
  • Degradante: il guasto interessa una funzionalità definita; avvisate e comunicate la limitazione senza dichiarare indisponibile l’intera applicazione.
  • Solo per avviso: il guasto richiede un’indagine, ma non influisce attualmente sul risultato di servizio selezionato.
  • Sconosciuta: il comportamento della dipendenza non è stato documentato o testato; non classificatela silenziosamente come opzionale.

Separate i controlli pubblici dai controlli operativi interni

I controlli esterni e interni rispondono a domande diverse. Google SRE descrive il monitoraggio black-box come il test del comportamento visibile esternamente, come lo vedrebbe un utente, mentre il monitoraggio white-box usa informazioni esposte dall’interno del sistema. Entrambi sono preziosi per le applicazioni self-hosted.

Un controllo pubblico può verificare che il dominio previsto, la route, il percorso TLS e la risposta di base dell’applicazione siano disponibili dall’esterno. Un flusso di lavoro sintetico autenticato può convalidare un percorso utente selezionato con attenzione, a condizione che credenziali, dati di test ed effetti collaterali siano gestiti in sicurezza. I controlli interni possono rivelare integrità del container, diagnostica dell’applicazione, connessioni alle dipendenze, profondità della coda o comportamento dei worker e pressione sulle risorse.

Non esponete pubblicamente endpoint operativi solo per comodità. Decidete quali strumenti diagnostici richiedono autenticazione o accesso a una rete privata ed evitate di inserire segreti in URL, log o configurazioni di monitoraggio semplicistiche. Il vostro modello di accesso, la gestione dei dati e i requisiti di governance restano responsabilità dei proprietari dell’applicazione anche quando le operazioni infrastrutturali sono gestite da un altro provider.

  • Pubblico: il punto di ingresso previsto per l’utente è raggiungibile e si comporta come previsto?
  • Esterno autenticato: un account controllato può completare un flusso di lavoro critico e sicuro?
  • Applicazione interna: l’applicazione segnala la condizione operativa prevista?
  • Dipendenze e risorse: i servizi necessari e le risorse limitate sono in una condizione che supporta il flusso di lavoro?
  • Revisione della sicurezza: endpoint di integrità, credenziali, log e dati di test sono adeguatamente protetti?

Trasformate i segnali in un piano di avviso e ripristino

Un controllo senza una decisione di risposta è solo una misurazione. Per ogni segnale, definite un responsabile, frequenza del controllo, timeout, numero di osservazioni non riuscite prima dell’avviso, canale di avviso e decisione di escalation. I controlli di integrità Docker forniscono controlli per intervallo, timeout, periodo di inizializzazione e fallimenti consecutivi; questi controlli illustrano perché una singola osservazione non riuscita non dovrebbe automaticamente avere lo stesso significato di una condizione persistente. I valori appropriati sono specifici dell’applicazione e dovrebbero essere scelti in base al comportamento osservato, non copiati come soglie universali.

Rendete altrettanto esplicito il percorso di ripristino. Registrate cosa dovrebbe ispezionare per primo chi risponde, quali azioni sono sicure e quali evidenze giustificano un riavvio, un ripristino, una correzione della configurazione o un rollback. Kubernetes avverte che liveness probe implementate in modo errato possono causare guasti a cascata attraverso riavvii sotto carico. Lo stesso principio operativo vale al di fuori di Kubernetes: il ripristino automatizzato dovrebbe essere ristretto, compreso e testato, anziché una risposta istintiva a qualsiasi dipendenza non riuscita.

Tra le informazioni diagnostiche utili rientrano il risultato osservato esternamente, lo stato di integrità dell’applicazione e del container quando disponibile, l’output recente dei controlli di integrità, le risposte delle dipendenze dirette e le condizioni pertinenti delle risorse. Docker documenta che lo stato di integrità configurato è visibile attraverso lo stato del container e che l’output diagnostico dei controlli di integrità può essere interrogato per le indagini. Conservate un contesto sufficiente affinché la persona reperibile possa agire senza dover fare supposizioni.

  • Responsabile del segnale: chi possiede la configurazione del controllo e il relativo runbook?
  • Policy di osservazione: con quale frequenza viene eseguito, quanto può durare e quanti fallimenti costituiscono una condizione significativa?
  • Canale di avviso: chi viene avvisato e quali condizioni giustificano un’escalation immediata?
  • Prima ispezione: quali log, output di integrità, controlli delle dipendenze e indicatori di risorse devono essere esaminati?
  • Azioni sicure: quali azioni di riavvio, configurazione, ripristino o rollback sono approvate?
  • Confine di escalation: quando il problema richiede il coinvolgimento del proprietario dell’applicazione, della dipendenza o del provider?

Domande frequenti

Una risposta HTTP 200 è sufficiente per un controllo di integrità di un’applicazione self-hosted?

Di solito no. Può dimostrare che una route raggiungibile ha restituito una risposta, ma potrebbe non provare che gli utenti possano accedere, consultare dati aggiornati, salvare modifiche, usare l’archiviazione, completare attività in background o raggiungere integrazioni necessarie. Affiancate un controllo esterno di base a controlli che riflettano i flussi di lavoro critici per l’applicazione.

Qual è la differenza tra vitalità e disponibilità al traffico?

La vitalità chiede se un’applicazione in esecuzione stia facendo progressi o possa richiedere un riavvio. La disponibilità al traffico chiede se possa ricevere in sicurezza il traffico previsto ora. Kubernetes documenta conseguenze diverse: una readiness probe non riuscita impedisce ai Service corrispondenti di inviare traffico, mentre una liveness probe non riuscita può portare alla terminazione del container secondo la policy di riavvio configurata.

Un controllo di disponibilità al traffico dovrebbe fallire quando un’API esterna non è disponibile?

Solo se quell’API è necessaria per il traffico o il flusso di lavoro che il segnale di disponibilità al traffico rappresenta. Se gli utenti non possono completare una funzione critica senza di essa, può essere una dipendenza bloccante. Se influisce su una funzionalità opzionale, classificatela invece come degradante o solo per avviso e definite esplicitamente l’esperienza di utenti e addetti alla risposta.

Cosa dovrebbe essere testato prima di fare affidamento sui controlli di integrità?

Testate scenari di guasto significativi in modo controllato: processo dell’applicazione arrestato, database non disponibile, archiviazione esaurita, worker della coda non riuscito e dipendenza esterna irraggiungibile. Confermate per ogni scenario il segnale osservato, il comportamento del traffico, il canale di avviso, la diagnostica, l’azione di ripristino sicura e i criteri di ripristino del servizio.

Come si inserisce Airbip nel monitoraggio delle applicazioni self-hosted?

Airbip gestisce il deployment delle applicazioni del catalogo come carichi di lavoro Docker sui propri server cloud e fornisce capacità infrastrutturali che includono automazione del routing e di TLS, controlli DNS, gestione del ciclo di vita dei servizi e backup configurabili giornalieri, settimanali e mensili. I proprietari delle applicazioni devono comunque definire i flussi di lavoro critici, effettuare scelte relative ad accesso e integrazioni, comprendere il comportamento di integrità specifico dell’applicazione e stabilire le priorità di ripristino.

Fonti e approfondimenti

  1. Liveness, Readiness, and Startup Probes — Kubernetes
  2. Dockerfile reference: HEALTHCHECK — Docker
  3. Running containers: Healthchecks — Docker
  4. Monitoring Distributed Systems — Google SRE
  5. Monitoring — Google SRE Workbook
  6. Testing for Reliability — Google SRE