Su AZ-400 la domanda non è “come faccio uno swap di slot”, ma “dato questo requisito di rischio, osservabilità e compliance, quale strategia di rilascio lo soddisfa e a quale costo”. Le strategie non sono intercambiabili: differiscono per granularità dell’esposizione, velocità di rollback, costo infrastrutturale e capacità di produrre un segnale di salute utilizzabile. Diamo per acquisiti i meccanismi base e concentriamoci sulle decisioni di design e sui trade-off.

Blue-green: commutazione atomica e il prezzo dell’ambiente parallelo

Il blue-green mantiene due ambienti di pari capacità e commuta il traffico in blocco. Il valore è il rollback deterministico: se la nuova versione fallisce, si ri-commuta e si torna al last known good. Il costo è l’ambiente duplicato e soprattutto il vincolo sullo stato condiviso: database e cache restano comuni, quindi lo schema deve essere retrocompatibile (expand/contract) o il rollback è illusorio.

Su Azure App Service l’implementazione canonica sono i deployment slot, disponibili nei tier Standard, Premium e Isolated. Le decisioni rilevanti sono tre. Primo, il warm-up: lo swap applica le impostazioni dello slot di destinazione, riavvia le istanze sorgente e attende che rispondano, così il traffico non colpisce mai istanze fredde. Secondo, quali impostazioni seguono il contenuto: app settings e connection string vengono scambiati per default e vanno marcati come deployment slot setting se devono restare ancorati allo slot, mentre identità gestite, integrazione VNet e restrizioni IP non seguono lo swap. È la trappola più frequente: una connection string di staging che finisce in produzione. Terzo, la modalità di swap: lo swap with preview mette in pausa dopo la prima fase e permette di validare lo slot sorgente già configurato come la produzione, mentre l’auto swap automatizza tutto ma rinuncia alla validazione pre-swap e non è supportato su Web App per Linux né su Web App for Containers.

Su Azure Container Apps lo stesso pattern si ottiene con le revision in multiple revision mode: due revision attive e regole di traffico. Le label meritano attenzione a parte: espongono una URL stabile verso una singola revision e funzionano indipendentemente dal traffic splitting, quindi rispondono al requisito “un gruppo ristretto di tester deve raggiungere la nuova versione senza che nessun utente pubblico ci finisca”.

Canary, ring e feature flag: esporre progressivamente invece di commutare

Blue-green è binario. Quando il requisito è “limitare il blast radius e osservare il comportamento reale prima di generalizzare”, serve un’esposizione progressiva.

Il canary instrada una quota di traffico verso la nuova versione e la amplia man mano che i segnali reggono. Su App Service si esprime con il routing percentuale verso lo slot: il client che vi finisce resta pinnato per un’ora tramite il cookie x-ms-routing-name (senza pinning rimbalzerebbe fra le due versioni a ogni richiesta), e lo stesso meccanismo permette opt-in e opt-out espliciti via query string. Su Container Apps il canary è la ripartizione percentuale del traffico fra revision.

Il ring-based deployment è la generalizzazione organizzativa del canary, ed è il modello descritto da Microsoft come progressive exposure: si segmentano utenti e infrastruttura in tier (o ring) ordinati per tolleranza al rischio, partendo da utenti interni e allargando fino alla totalità della base. La differenza rispetto al canary è che il ring non segmenta il traffico in modo casuale ma per popolazione e per scale unit, intercettando classi di problemi diverse: bug funzionali nei ring iniziali, problemi di scala e regionali in quelli successivi. Il parametro chiave è il bake time, il tempo in cui una versione resta in un ring prima della promozione: la guida Microsoft indica che una giornata è generalmente sufficiente a far emergere bug latenti e che l’intervallo deve includere un picco di utilizzo. Regola derivata: il bake time si dimensiona sul ciclo di carico, non sull’orologio della pipeline.

Canary e ring spostano codice. I feature flag spostano comportamento, e coprono requisiti che le strategie infrastrutturali non risolvono. Con Azure App Configuration come repository centralizzato dei flag ottieni dark deployment (codice in produzione ma dormiente), flighting verso una quota crescente di utenti, kill switch istantaneo senza redeploy e attivazione selettiva per segmento; i filtri valutano il flag su regole quali gruppi di utenti, device o browser, area geografica e finestre temporali.

Da qui la distinzione che l’esame ama: l’A/B testing non è una strategia di deployment ma un esperimento. Il canary chiede “la nuova versione è sana?” e risponde con un segnale tecnico. L’A/B test chiede “quale variante converte meglio?” e risponde con una metrica di prodotto, che richiede assegnazione stabile degli utenti alle varianti. Se il requisito parla di ipotesi e confronto fra varianti, la risposta è feature flag più telemetria, non traffico ripartito fra due slot.

Deployment job: runOnce, rolling e canary in YAML

In Azure Pipelines la strategia si dichiara nel deployment job, che oltre a eseguire i passi registra la cronologia di deployment sull’environment. Due comportamenti impliciti: il deployment job non fa il checkout del repo (serve checkout: self) e il download degli artifact è iniettato solo nell’hook deploy.

I lifecycle hook sono la vera unità di design: preDeploy inizializza, deploy rilascia, routeTraffic sposta il traffico, postRouteTraffic osserva la salute dopo lo spostamento, e on: success / on: failure gestiscono notifica e rollback. È in postRouteTraffic che vive la logica di promozione o abort del canary.

  • runOnce: tutti gli hook eseguiti una volta. È il default e copre il blue-green tramite swap, perché la commutazione è un’operazione singola.
  • rolling: sostituisce le istanze a ondate, con maxParallel espresso come numero o percentuale di target. Supportato per le risorse di tipo macchina virtuale, con gli hook eseguiti per ogni batch. Vincolo da ricordare: il retry di uno stage rilancia il deployment su tutte le VM, non solo su quelle fallite.
  • canary: si dichiara con increments, esegue preDeploy una volta sola e poi itera deploy, routeTraffic e postRouteTraffic per ciascun incremento. Espone le variabili strategy.name, strategy.action e strategy.increment, passate ai task Kubernetes perché azione (deploy, promote, reject) e percentuale seguano l’iterazione corrente.

Checks e approval: il gate che il YAML non controlla

Il punto architetturale più frainteso: approvals e checks non si definiscono nel file YAML. Li configura il proprietario della risorsa dall’interfaccia web, ed è esattamente il controllo di separation of duties che l’esame cerca: chi modifica la pipeline non può rimuovere il gate. Si applicano a risorse tra cui environment, service connection, repository, variable group, secure file e agent pool, e tutti i check su tutte le risorse consumate da uno stage devono essere soddisfatti prima che lo stage parta.

L’ordine di valutazione è definito: prima i check statici (branch control, required template, evaluate artifact), poi le pre-check approval, i check dinamici (approval, invoke Azure Function, invoke REST API, business hours, query Azure Monitor alerts), le post-check approval e infine l’exclusive lock. Scelte ricorrenti: branch control perché in produzione arrivi solo ciò che nasce da un branch protetto; required template per imporre l’estensione da un template approvato, cioè rendere non aggirabili i passi di sicurezza; query Azure Monitor alerts come gate automatico del canary, che passa se nessuna regola di alert è attiva; exclusive lock con lockBehavior a sequential quando i rilasci devono accodarsi, contro il default runLatest che scarta le run intermedie. Se un gruppo è approvatore basta un solo membro, e allo scadere del timeout lo stage non viene eseguito.

Su GitHub Actions l’equivalente sono le deployment protection rule sugli environment: required reviewers (fino a 6 persone o team, basta una approvazione), wait timer, deployment branch e tag policy, più regole personalizzate fornite da GitHub App. Gli environment secret diventano accessibili solo dopo che le protection rule sono soddisfatte: è la leva per impedire che le credenziali di produzione siano raggiungibili da una run non approvata.

Come cade all’esame

  • “Rollback immediato di un’intera versione, con validazione prima della commutazione” → slot con swap with preview, non auto swap.
  • “Un gruppo di beta tester deve raggiungere la nuova versione senza esporla al pubblico”label su Container Apps o routing a zero percento con opt-in via x-ms-routing-name, non un canary percentuale.
  • “Aumentare l’esposizione a ondate osservando la salute e abortendo in automatico” → strategia canary con increments, gate in postRouteTraffic e check query Azure Monitor alerts sull’environment.
  • “Aggiornare un parco di VM senza downtime, mantenendo capacità di servizio” → strategia rolling con maxParallel; runOnce non offre batching.
  • “Disattivare una funzionalità difettosa in produzione senza rideployare”feature flag, non rollback della release.
  • “Chi modifica la pipeline non deve poter rimuovere l’approvazione di produzione” → check sull’environment definiti dal resource owner, più required template; le condizioni sullo stage nel YAML non bastano.