Il rilascio applicativo su AZ-400 non si valuta sul “come si scrive la task”, ma sul contratto di rollback che la soluzione garantisce. Un deployment di codice e reversibile in secondi; un deployment di database, spesso, no. La domanda d’esame ricorrente e quindi: dato questo target, questo requisito di downtime e questo vincolo sui dati, quale unita di deployment e quale strategia di migrazione minimizzano il rischio. Diamo per acquisiti i meccanismi base — cosa sia un artifact o una connection string — e concentriamoci sulle decisioni di design.

Container, binari, script: scegliere l’unita di deployment

Le tre modalita non sono intercambiabili: differiscono per cosa viene versionato e per cosa resta mutabile sul target.

Il container e l’unita piu forte perche l’immagine include runtime, dipendenze e configurazione di base. L’artefatto e immutabile e identificato dal digest, quindi ambiente di test e produzione eseguono letteralmente lo stesso bit. Il rollback e la ridistribuzione del tag precedente. Il costo e la superficie di governance che si sposta sul registry: promozione fra registry o fra tag, scansione vulnerabilita, provenienza. Nota di design spesso trascurata: usare il tag latest distrugge la riproducibilita, tanto che su AKS le Deployment Safeguards includono una policy che blocca proprio le immagini senza tag versionato esplicito.

Il binario (pacchetto zip, artefatto di build, WebDeploy) versiona solo l’applicazione e lascia il runtime al piano di hosting. E la scelta naturale per App Service o per macchine virtuali gia standardizzate: meno infrastruttura da gestire, ma la coppia “versione applicativa + versione runtime del target” non e piu atomica, e le regressioni da drift del runtime diventano possibili.

Lo script e la modalita residuale ma indispensabile: configurazione del sistema operativo, registrazione servizi, task idempotenti su VM. La regola di design e trattarlo come codice — versionato, idempotente, eseguito da una deployment job invece che a mano. Su target VM, definire l’ambiente come risorsa di tipo VirtualMachine fa si che gli step girino sulla macchina e non sull’agent del pool, e registra lo storico di deployment per singola risorsa.

Strategie di rilascio: quale strategia per quale target

In Azure Pipelines le deployment job supportano tre strategie — runOnce, rolling e canary — costruite sugli stessi lifecycle hook: preDeploy, deploy, routeTraffic, postRouteTraffic e infine on: success oppure on: failure. Riconoscere questi hook e riconoscere la struttura di un rilascio sicuro: inizializzo, distribuisco, sposto traffico, osservo dopo aver spostato il traffico, e ho un ramo esplicito per il rollback.

Il vincolo da memorizzare e che rolling e supportata solo su risorse VM: maxParallel, in numero assoluto o percentuale, definisce quante macchine si aggiornano per iterazione mantenendo le altre in servizio. La strategia canary esegue preDeploy una volta sola e poi itera deploy, routeTraffic e postRouteTraffic sugli increments dichiarati, esponendo variabili tra cui strategy.increment utilizzabili dalle task Kubernetes.

Sul lato piattaforma, i meccanismi di rilascio sono nativi e vanno preferiti alla logica custom.

  • App Service deployment slot (disponibili in tier Standard, Premium e Isolated): lo swap applica le impostazioni slot-specific alla source, attende il riavvio e il warm-up di tutte le istanze, e solo allora inverte le regole di routing. Il target resta online per tutta la preparazione. Il rollback e uno swap immediato dei medesimi due slot. Da ricordare: alcune impostazioni sono sticky e non seguono lo swap, e l’auto swap non e supportato su Linux e Web App for Containers.
  • Azure Container Apps revision: le revisioni sono immutabili e versionate. In single revision mode il traffico passa alla nuova revisione solo quando ha superato provisioning, scale-up e probe di startup e readiness; in multiple revision mode si controlla la ripartizione percentuale del traffico, ovvero blue-green e A/B. Le label sono ortogonali al traffic splitting: danno un URL stabile che punta a una revisione specifica, ideale per far testare la candidata a un gruppo ristretto senza toccare le percentuali.

Distinzione utile: una modifica alla sezione template (immagine, scale rule) e revision-scope e crea una nuova revisione; una modifica alla configurazione (ingress, traffic splitting, secret) e application-scope e non ne crea nessuna.

Database: state-based o migration-based

Qui si decide il contratto di rollback. Le due famiglie rispondono a domande diverse.

L’approccio state-based e rappresentato dal DACPAC, artefatto di build di un progetto SQL. Il pacchetto descrive lo stato desiderato; al deploy la differenza rispetto al database target viene calcolata dinamicamente e applicata come aggiornamento incrementale. Il vantaggio e che il repository contiene lo schema leggibile, non una catena di delta. Il prezzo e che il piano di deployment non e noto finche non lo si genera: per questo in pipeline si usa SqlPackage con /DeployScriptPath e /DeployReportPath per produrre lo script e il report in uno stage precedente, sottoporli a review o approval, ed eseguirli solo dopo.

L’approccio migration-based, tipico di EF Core, versiona invece la sequenza di trasformazioni. Microsoft e esplicita: il modo raccomandato per la produzione e generare script SQL, perche possono essere revisionati, adattati e archiviati separatamente. Gli script idempotenti verificano la tabella di storico e applicano solo le migrazioni mancanti, il che li rende adatti a parchi di database in stati diversi. I migration bundle (efbundle) sono eseguibili singoli generabili in CI ed eseguibili senza SDK, sorgenti o EF tool sul target. Applicare le migrazioni a runtime con Migrate() resta invece sconsigliato in produzione: richiede permessi elevati all’applicazione, non lascia ispezionare il SQL e complica il rollback. Da EF Core 9 esiste un lock a livello di database che protegge dall’esecuzione concorrente, ma il lock risolve la corruzione, non la reversibilita.

Compatibilita di schema e rollback dei dati

Il rollback applicativo e istantaneo, quello dei dati no: la conseguenza di design e che lo schema deve essere compatibile con almeno due versioni dell’applicazione. E il pattern expand and contract: prima si espande lo schema in modo retrocompatibile (aggiungere colonna nullable, nuova tabella, doppia scrittura), poi si rilascia il codice che la usa, e solo in un rilascio successivo si contrae rimuovendo il vecchio. Senza questo, qualunque strategia canary o blue-green e illusoria, perche le due versioni convivono sullo stesso database.

Gli strumenti offrono guardrail che vanno interpretati come decisioni, non come default da subire.

  • BlockOnPossibleDataLoss in SqlPackage ha default True e termina l’operazione in fase di validazione se le modifiche potrebbero causare perdita di dati, inclusa una riduzione di precisione o un cast di tipo. Disattivarlo e una scelta consapevole, e non mette comunque al riparo: l’esecuzione puo ancora fallire se i dati presenti non sono convertibili.
  • DropObjectsNotInSource ha default False: attivarlo per allineare rigidamente il target allo stato desiderato significa accettare drop di oggetti non presenti nel progetto.
  • GenerateSmartDefaults fornisce un default automatico quando si aggiunge una colonna non nullable a una tabella con dati.
  • Uno script generato “da migrazione piu recente a migrazione precedente” e a tutti gli effetti uno script di rollback, ma reverte lo schema, non i dati gia persi.

Regola operativa che ne discende: la reversibilita dei dati si ottiene con backup o snapshot presi prima dello stage di migrazione e con migrazioni progettate come additive, non affidandosi al down script.

Come si presenta all’esame

  • “Serve rilasciare su un set di VM mantenendo il servizio disponibile, con health check fra un gruppo e l’altro” → deployment job con strategia rolling e maxParallel; ricorda che rolling e supportata solo su risorse VM.
  • “Serve esporre la nuova versione a un gruppo ristretto di tester senza modificare le percentuali di traffico”label su Container Apps in multiple revision mode, non traffic splitting.
  • “Zero downtime su App Service con possibilita di tornare indietro subito”slot swap con warm-up, rollback tramite swap inverso; attenzione alle impostazioni slot-specific e al limite dell’auto swap su Linux e container.
  • “Il DBA deve approvare il SQL prima che tocchi produzione” → generare lo script con /DeployScriptPath (o dotnet ef migrations script) in uno stage con approval, poi eseguirlo; non pubblicare direttamente il DACPAC.
  • “Deployment verso molti database in stati di migrazione diversi”script idempotenti o migration bundle, non dotnet ef database update puntuale.
  • “La release va poter essere annullata dopo il rilascio, ma una colonna viene rinominata”expand and contract: colonna nuova in aggiunta, doppia scrittura, rimozione in un rilascio successivo; il rename secco rompe la retrocompatibilita e puo essere emesso come drop.