Il momento più delicato nella vita di un'applicazione non è quando gira, ma quando cambia. Ogni rilascio introduce codice nuovo in un sistema che fino a un minuto prima funzionava. Fermare tutto, sostituire i file e riavviare è il metodo più semplice, ma impone un'interruzione e lascia poche vie d'uscita se qualcosa va storto. Esistono strategie che riducono entrambi i problemi, ciascuna con il suo prezzo.
Il punto di partenza: sostituzione completa
Nella strategia più elementare, detta anche recreate, si spegne la versione vecchia e si accende la nuova. È accettabile per strumenti interni o sistemi con finestre di manutenzione concordate. Ha due difetti evidenti: per qualche secondo o minuto il servizio non risponde, e se la nuova versione ha un problema bisogna ripetere l'intera procedura al contrario.
Rolling update
Con il rolling update le istanze vengono sostituite una alla volta, o a piccoli gruppi. Se un servizio gira su quattro istanze, se ne aggiorna una, si verifica che sia sana, poi si passa alla successiva.
Vantaggi:
- nessuna interruzione, purché ci siano almeno due istanze e un bilanciatore di carico;
- nessuna risorsa aggiuntiva significativa;
- è il comportamento predefinito di molti orchestratori, Kubernetes compreso.
Svantaggi:
- per un certo periodo convivono due versioni dell'applicazione, che devono essere compatibili tra loro e con il database;
- il rollback è a sua volta un rolling update, quindi non è istantaneo;
- un problema che emerge solo sotto carico può colpire tutti prima di essere notato.
Blue-green
Nel blue-green deployment esistono due ambienti di produzione identici. Uno, chiamiamolo blu, serve il traffico. La nuova versione viene installata sull'altro, il verde, dove la si può verificare con calma. Quando tutto è pronto, il bilanciatore o il DNS sposta il traffico dal blu al verde in un colpo solo.
Vantaggi:
- il passaggio è pressoché istantaneo;
- il rollback è immediato: basta riportare il traffico sul blu, che è rimasto intatto;
- la nuova versione si può testare nell'ambiente reale prima di esporla agli utenti.
Svantaggi:
- servono temporaneamente risorse doppie;
- tutti gli utenti passano alla nuova versione nello stesso momento, quindi un errore sfuggito ai test li colpisce tutti;
- le sessioni attive e le connessioni lunghe vanno gestite con attenzione durante lo scambio.
Se il passaggio avviene tramite DNS, ricorda che le risposte restano nelle cache per la durata del TTL: alcuni client continueranno a raggiungere il vecchio ambiente per un po'. Un bilanciatore di carico offre un controllo molto più preciso.
Canary
Il nome viene dai canarini che un tempo i minatori portavano in galleria per accorgersi dei gas pericolosi. Nel canary release la nuova versione riceve inizialmente solo una piccola parte del traffico, per esempio il cinque per cento. Si osservano errori, tempi di risposta e metriche di business; se tutto è regolare si aumenta gradualmente la quota fino al cento per cento.
Vantaggi:
- un difetto colpisce solo una frazione degli utenti;
- si raccolgono dati reali sul comportamento della nuova versione prima di estenderla;
- il ritorno indietro consiste nel riportare a zero la quota.
Svantaggi:
- richiede un monitoraggio solido, capace di confrontare le due versioni, altrimenti il canarino non segnala nulla;
- serve un sistema di instradamento del traffico più sofisticato;
- come nel rolling update, due versioni convivono a lungo.
Confronto rapido
| Strategia | Interruzione | Risorse extra | Velocità di rollback | Esposizione al rischio |
|---|---|---|---|---|
| Recreate | Sì | No | Lenta | Tutti gli utenti |
| Rolling update | No | Minime | Media | Crescente |
| Blue-green | No | Doppie, temporanee | Immediata | Tutti, ma reversibile |
| Canary | No | Limitate | Rapida | Una piccola quota |
Il vero problema: il database
Qualunque strategia senza interruzione implica che, almeno per qualche momento, versione vecchia e nuova accedano allo stesso database. Se la nuova versione rinomina una colonna, la vecchia smette di funzionare.
La soluzione è separare le modifiche allo schema in più rilasci compatibili, secondo lo schema detto espandi e contrai:
- si aggiunge la nuova colonna senza rimuovere la vecchia;
- si rilascia codice che scrive in entrambe e legge dalla nuova;
- si copiano i dati esistenti;
- quando nessuna istanza usa più la vecchia colonna, la si elimina in un rilascio successivo.
È più lento, ma ogni passo è reversibile e nessuna versione si trova davanti a uno schema che non conosce.
Feature flag: separare rilascio e attivazione
Un complemento utile a tutte le strategie sono i feature flag, interruttori nel codice che attivano una funzionalità senza un nuovo deploy. Il codice arriva in produzione spento, viene acceso per pochi utenti o per il personale interno e, se crea problemi, si spegne in un istante. I flag vanno però rimossi quando non servono più, altrimenti il codice si riempie di rami morti difficili da mantenere.
In sintesi
- La sostituzione completa è semplice ma comporta un'interruzione e un rollback lento.
- Il rolling update aggiorna le istanze una alla volta ed è la scelta predefinita di molti orchestratori.
- Il blue-green richiede risorse doppie ma consente un ritorno indietro immediato.
- Il canary limita l'impatto dei difetti, a patto di avere un monitoraggio efficace.
- Le modifiche al database vanno rese compatibili tra versioni con l'approccio espandi e contrai.