Cos'è il canary deployment? Guida pratica per sviluppatori

Riassunto

Un canary deployment invia una nuova versione a una piccola quota di traffico reale, spesso dall'1% al 5%, prima che la ricevano tutti. Confronti tasso di errori e latenza con la versione stabile, allarghi la fetta se regge e riporti il peso del canary a zero se non regge. Limita i danni di una release difettosa, ma richiede metriche per versione e abbastanza traffico perché abbia senso.

Una scrivania da sviluppatore di notte con un dashboard di grafici del traffico e una piccola statuina di canarino giallo

Cos'è il canary deployment? È un rilascio in cui la nuova versione della tua app riceve per prima una piccola fetta di traffico reale, diciamo dall'1% al 5%, mentre tutti gli altri restano sulla versione vecchia. Tieni d'occhio il tasso di errori e la latenza su quella fetta. Se è sana, la allarghi. Se va male, rimandi il traffico indietro e quasi nessuno se ne accorge. È tutta l'idea, e il resto dell'articolo serve a farla funzionare davvero.

Una vecchia lanterna da minatore e una gabbia vuota su un banco da lavoro, l'origine del nome canary

Perché si chiama canary?

I minatori portavano i canarini nelle gallerie perché gli uccelli reagivano ai gas tossici prima delle persone. Un canarino che smetteva di cantare era il segnale per uscire. Il deployment funziona allo stesso modo: un piccolo gruppo di utenti incontra per primo il codice nuovo e fa da sistema di allarme. Il glossario CNCF lo descrive come due ambienti, uno che serve il traffico reale e uno con il codice aggiornato, con il traffico spostato gradualmente, partendo da una quota piccola come l'1%.

In pratica il problema è questo: gli utenti del canary sono utenti veri. Lo staging non può darti questo. In produzione ci sono i browser strani, le cache vecchie, il cliente con il file di importazione da 40 MB. Il canary è il modo per incontrarli prima che li incontrino tutti i tuoi bug.

Come funziona davvero un canary deployment?

Quattro parti in gioco, niente di esotico.

Una rampa tipica va così: 1%, 5%, 25%, 50%, 100%, con una pausa a ogni passo. Anche Google Cloud Deploy segue la stessa forma: definisci una serie di percentuali e lo strumento distribuisce il traffico, con un esempio che usa fasi al 25%, 50% e 75% prima della versione stabile finale. La documentazione sui canary di Cloud Deploy mostra inoltre che ogni fase può eseguire un job di verifica e un'analisi per decidere se avanzare.

Non è un setup perfetto. È un setup fattibile. Non ti serve Kubernetes: una route pesata in nginx, una regola di Cloudflare Worker che imposta un cookie o due macchine Fly.io dietro un proxy contano tutte.

Come appare lo split del traffico in una configurazione?

Ecco l'esempio utile più piccolo, un upstream nginx con pesi. Nove richieste su dieci vanno alla stabile, una va al canary.

upstream app {
    server 10.0.0.10:3000 weight=9;   # stabile
    server 10.0.0.11:3000 weight=1;   # canary
}

Questo ha un difetto che devi conoscere: lo split avviene per richiesta, quindi lo stesso utente può passare da una versione all'altra su due clic consecutivi. Se la nuova versione cambia la forma di una risposta API o di una colonna del database, quell'utente passerà un brutto momento. Il routing sticky per cookie o per ID utente risolve il problema, ed è la prima cosa da aggiungere una volta che lo split di base funziona.

Portatile con due linee di metriche divergenti che confrontano una release stabile e una canary

Cosa guardare mentre il canary è attivo?

Confronta il canary con la versione stabile nello stesso momento, non con la settimana scorsa. La settimana scorsa aveva un traffico diverso. La domanda è sempre la stessa: il canary va peggio della versione che sta servendo il restante 95% adesso?

L'errore che vediamo più spesso nei team piccoli è far avanzare la rampa a tempo. Cinque minuti all'1%, poi al 25%, indipendentemente da ciò che dicono i grafici. Con poco traffico, cinque minuti all'1% possono voler dire sei richieste, e non ti dicono nulla. Aspetta un numero minimo di richieste, non un numero minimo di minuti.

Gli strumenti che rendono tutto meno manuale meritano un'occhiata quando hai traffico reale.

Canary o blue-green: quale scegliere?

Il blue-green mantiene due ambienti completi e sposta tutto il traffico in un colpo solo. Il rollback significa rimettere il traffico sul vecchio, ed è veloce e pulito. Il costo è che per un attimo il 100% degli utenti è sulla nuova versione, e durante lo switch paghi il doppio dell'infrastruttura.

Il canary espone solo una fetta, quindi il raggio d'impatto è più piccolo. Il prezzo è la complessità: ti servono pesi sul traffico, metriche per versione e una regola di decisione. Il rollback consiste nel portare il peso del canary a zero, cosa rapida ma non letteralmente istantanea se le connessioni devono drenare.

Tre ragioni per scegliere il canary, una per non sceglierlo. Scegli il canary quando un bug in produzione costa caro, quando hai abbastanza traffico perché una piccola fetta abbia senso e quando puoi confrontare le metriche per versione. Evitalo quando hai qualche decina di utenti al giorno: la fetta del canary sarà statisticamente vuota e andrai a intuito. A quella scala, il blue-green o anche un deploy semplice con uno script di rollback veloce è la risposta onesta.

I rolling update stanno nel mezzo. Sostituiscono le istanze una alla volta, in modo delicato, ma non sono un esperimento controllato: non scegli chi vede la nuova versione e non confronti coorti.

Dove si inseriscono i feature flag?

Un canary deployment divide il traffico tra versioni del codice. Un feature flag divide il comportamento dentro una sola versione. Le due cose si confondono spesso, e la confusione costa cara.

Distribuisci il nuovo codice a tutti, nascosto dietro un flag spento. Poi accendi il flag per l'1% degli utenti, poi per il 10%, poi per tutti. Spesso si parla di release canary a livello di funzionalità. Il vantaggio: il rollback è girare un flag, senza rideploy. Lo svantaggio: il percorso di codice morto resta in produzione per tutti, e i flag dimenticati diventano debito tecnico.

Per chi sviluppa da solo, i flag sono di solito il primo passo più economico. Un booleano in una tabella di configurazione e un hash dell'ID utente ti danno l'80% del valore. Se ti serve di più, un servizio gestito si occupa di targeting, log di audit e rollout graduali in percentuale.

Una manopola girata leggermente, come quando si sposta una piccola quota di traffico verso una nuova versione

Cosa va storto con i canary nei progetti reali?

Testato. Non ottimale. Ecco perché lo facciamo lo stesso. Questi sono i problemi che mordono davvero.

Migrazioni del database. Entrambe le versioni colpiscono lo stesso database nello stesso momento. Se il canary elimina o rinomina una colonna, la stabile si rompe. La soluzione è il pattern expand and contract: aggiungi prima le nuove colonne, rilascia codice che gestisce entrambe le forme e rimuovi quelle vecchie solo in una release successiva. Se salti questo passaggio, il canary abbatte la versione stabile.

Sessioni con stato. Se le sessioni vivono in memoria su un'istanza, un utente che passa tra le versioni viene disconnesso. Sposta lo stato della sessione in uno store condiviso prima di provare i canary.

Cache avvelenate. Una nuova versione che scrive un formato di cache diverso può corrompere ciò che legge la vecchia. Versiona le chiavi della cache.

Job in background. Anche il canary consuma i messaggi delle code. Un worker difettoso può divorare job alla massima velocità, perché la percentuale di traffico non limita il consumo delle code. Dai al canary una coda o un peso di consumer dedicati.

Allarmi mai collegati. Il canary può fallire rumorosamente in una dashboard che nessuno apre. Un'interruzione automatica su una soglia batte una persona che guarda, soprattutto alle 2 di notte a Taipei o a Bangkok, quando l'unica persona sveglia è quella che ha fatto il deploy.

Come iniziare con un canary su un progetto personale?

Parti più in piccolo di quanto pensi. Sei uno sviluppatore, non un team di piattaforma.

  1. Etichetta ogni metrica con una versione. Metti lo SHA di git in un header e nei log. Senza, non puoi confrontare canary e stabile.

  2. Scegli una sola regola di interruzione. Per esempio: tasso di errori sul canary sopra il doppio della stabile per cinque minuti significa rollback. Una regola, scritta.

  3. Aggiungi una route pesata. Pesi di nginx, una regola di Cloudflare o la funzione di split del traffico del tuo host. La maggior parte delle piattaforme gestite oggi offre il routing in percentuale senza strumenti extra.

  4. Rilascia prima qualcosa di banale. Una modifica al testo, non la riscrittura della pagina dei prezzi. Prova la rampa e il rollback quando non c'è niente in gioco.

  5. Cronometra il rollback. Eseguilo davvero una volta. Se ti servono dieci minuti di tentativi, quello è il problema da sistemare, non la rampa.

Se il tuo progetto è ancora nella fase in cui cerchi di capire chi lo pagherà, probabilmente è prematuro. Rilascia in modo semplice, tieni uno script di rollback e torna ai canary quando un'interruzione ti costerebbe clienti veri. Se sei già lì, la route pesata più una regola di interruzione sono un weekend di lavoro, e si ripagano la prima volta che una release difettosa muore all'1% invece che al 100%.

Bisogna usare il canary per tutto?

No. Modifiche di configurazione, ritocchi al testo e correzioni di un refuso nel footer non hanno bisogno di una rampa. Usa i canary per le modifiche in cui sbagliare costa denaro o fiducia: pagamenti, autenticazione, modelli di dati, tutto ciò che tocca il percorso critico. Una pipeline che fa la rampa su ogni commit per un'ora verrà aggirata la prima volta che qualcuno ha fretta, e un processo aggirato è peggio di nessun processo.

Quindi, qual è la modifica più rischiosa del tuo prossimo rilascio, e cosa servirebbe per mandarla prima all'1% degli utenti?

Domande frequenti

Cos'è un canary deployment in parole semplici?
È un metodo di rilascio in cui una nuova versione serve per prima una piccola percentuale di utenti reali, mentre gli altri restano sulla versione precedente. Se le metriche restano sane, la quota cresce fino a servire tutti. Se peggiorano, il traffico torna sulla versione stabile.
Con quale percentuale di traffico dovrebbe partire un canary?
Molti team partono tra l'1% e il 5%. Il numero giusto dipende dai volumi: la fetta deve generare abbastanza richieste per confrontare tasso di errori e latenza. Con traffico molto basso, aspetta un numero minimo di richieste invece di un numero fisso di minuti.
Qual è la differenza tra canary e blue-green deployment?
Il blue-green gestisce due ambienti completi e sposta tutto il traffico in un colpo solo, quindi il rollback significa tornare indietro in un istante. Il canary sposta il traffico gradualmente: meno utenti sono esposti a una release difettosa, ma servono pesi sul traffico e monitoraggio per versione.
Un canary deployment è la stessa cosa di un feature flag?
No. Un canary divide il traffico tra due versioni del codice distribuite. Un feature flag accende o spegne un comportamento all'interno di una sola versione. Funzionano bene insieme: distribuisci il codice nascosto dietro un flag, poi attivalo per una piccola percentuale di utenti.
Serve Kubernetes per fare canary deployment?
No. Upstream pesati in nginx, una regola su CDN o edge, oppure lo split del traffico su un host gestito possono farlo tutti. Gli strumenti Kubernetes rendono più facili le rampe e l'analisi automatica, ma non sono obbligatori.
Come funzionano le migrazioni del database con i canary?
Entrambe le versioni condividono un solo database, quindi usa il pattern expand and contract: aggiungi prima le nuove colonne, rilascia codice che gestisce entrambe le forme e rimuovi le vecchie colonne solo in una release successiva.