Deployment delle app .NET su Google Cloud

Last reviewed 2022-01-19 UTC

Questo articolo fornisce una panoramica su come eseguire il deployment delle app .NET su Google Cloud e fornisce indicazioni su come scegliere l'approccio giusto al deployment della tua app.

Introduzione

Il framework Microsoft .NET fornisce un ricco set di strumenti e librerie per lo sviluppo di app. Con l'avvento del supporto Docker su Windows e la possibilità di eseguire app .NET Core su Linux, anche le app .NET sono in grado di supportare una varietà di target di deployment.

Affinché lo sviluppo e i test siano efficienti, puoi automatizzare il deployment delle app e includerle in una pipeline di integrazione continua/distribuzione continua (CI/CD). Tuttavia, per scegliere gli strumenti giusti e creare una pipeline CI/CD, devi prima identificare come eseguire l'app in produzione e l'approccio al deployment che vuoi intraprendere.

Non esiste un unico modo migliore per eseguire il deployment di un'app .NET su Google Cloud. Le migliori opzioni di deployment per te dipendono dall'app e dai tuoi requisiti. Ad esempio, se la tua app richiede il framework .NET completo o deve essere eseguita su IIS, il deployment sarà basato su Windows. Se invece l'app può essere eseguita con la funzionalità supportata da .NET Core, puoi eseguire il deployment in Linux.

Questo articolo illustra i vari modi in cui puoi eseguire le app .NET ed eseguirne il deployment su Google Cloud, incluse le condizioni in cui ciascuna opzione è adatta. Alla fine, le opzioni di deployment sono riassunte in una struttura decisionale per aiutarti a decidere quali componenti e approcci di Google Cloud sono i migliori per la tua app .NET.

Modelli di deployment

Esistono due metodi di base per eseguire il deployment automatico di un'app. Il pacchetto di deployment viene inviato ai server dell'app oppure i pacchetti dell'app tirano il pacchetto dell'app da una posizione nota. Le seguenti sezioni esaminano le differenze tra questi due modelli.

Deployment basati su push

In un deployment basato su push, l'artefatto di deployment (un file ZIP, un pacchetto NuGet o un altro artefatto) è inizialmente disponibile solo per un server di deployment. Il server di deployment può essere una macchina dedicata o un ruolo assunto dal sistema CI.

Per eseguire un deployment, un processo sul server di deployment si connette a un server app, copia l'artefatto di deployment e ne avvia l'installazione. Se sono presenti più server app, questo processo viene ripetuto in parallelo o, più comunemente, in sequenza in modo che venga eseguito il deployment degli artefatti in tutti i server app.

Il seguente diagramma illustra questo flusso.

Deployment basati su push

Sono disponibili una serie di strumenti di gestione della configurazione che ti consentono di automatizzare i deployment in questo modo. Alcuni di questi strumenti seguono un approccio imperativo in cui la sequenza di passaggi di deployment viene definita in modo simile a uno script. Anche se questo approccio è intuitivo, è soggetto a deviazioni di configurazione, il che significa che, dopo un determinato periodo di tempo, gli stati di più macchine potrebbero non essere identici e potrebbero non riflettere completamente lo stato previsto. Di conseguenza, molti strumenti consentono di definire lo stato desiderato, lasciandolo a questo strumento per determinare i passaggi necessari per realizzare questo stato.

Su Windows, gli strumenti di uso comune per questo modello di implementazione includono:

Gli strumenti open source più diffusi includono Ansible, Chef Infra e Puppet. Anche se questi strumenti sono destinati principalmente a Linux, sono in grado di eseguire il deployment di destinazioni Windows.

Sicurezza

Affinché il server di deployment esegua il push di un deployment a un server app, deve essere disponibile un canale posteriore. Ad esempio, Web Deploy e Octopus Deploy usano un protocollo e una porta personalizzati per questa attività, mentre Ansible utilizza SSH.

Indipendentemente dal protocollo utilizzato dallo strumento, è fondamentale che la comunicazione sia sicura per aiutare gli utenti malintenzionati a utilizzare il canale posteriore per il deployment di app dannose. Ma soprattutto, la comunicazione sicura richiede che il server di deployment sia in grado di eseguire l'autenticazione con il server delle app.

SSH può utilizzare l'autenticazione con chiave pubblica. Se utilizzi la configurazione IAM appropriata, puoi lasciare che Google Cloud si occupi automaticamente della distribuzione della chiave pubblica utilizzata per SSH ai server delle app. Tuttavia, se non utilizzi IAM, Google Cloud non può gestire la chiave al posto tuo e tu devi gestire questa attività autonomamente.

Un'opzione è Active Directory. Quando il server di deployment e l'app eseguono Windows e sono membri di un dominio Active Directory, l'autenticazione viene gestita utilizzando Kerberos. Tuttavia, l'esecuzione di un ambiente Active Directory a tolleranza di errore richiede almeno due istanze VM aggiuntive per poter eseguire i controller di dominio. Se la tua configurazione utilizza la scalabilità automatica, tutti i server devono anche essere uniti in modo dinamico al dominio, cosa che rallenta il processo di generazione di un server. La scalabilità automatica può anche causare l'accumulo di oggetti inattivi nel computer nella directory, rendendo necessaria una logica di scavenging aggiuntiva. Se utilizzi Active Directory in un ambiente basato su cloud, devi prendere in considerazione questi fattori aggiuntivi.

In assenza di Active Directory, l'autenticazione deve essere gestita utilizzando NTLM o con altri mezzi, come l'autenticazione HTTP di base. Entrambi gli approcci richiedono che le credenziali siano sincronizzate tra il server di deployment e i server di app e siano archiviate in modo sicuro. Entrambe queste attività possono rivelarsi difficili.

Sia che utilizzi Linux o Windows, la protezione della comunicazione tra il deployment e i server delle app richiede meccanismi separati da IAM. Tuttavia, l'uso di più meccanismi per controllare l'accesso ai sistemi aumenta la complessità complessiva e aumenta il rischio di configurazioni errate accidentali.

Aggiornamenti del sistema operativo

È importante poter eseguire il deployment in modo efficiente di nuove versioni dei pacchetti di app sui server di app, ma è anche fondamentale gestire il sistema operativo sottostante su tali server. Ciò significa installare le patch di sicurezza. Per parchi risorse di dimensioni maggiori, devi automatizzare questo processo in modo da ridurre al minimo i rischi e il numero di server non disponibili durante l'aggiornamento.

Puoi usare anche un approccio push agli aggiornamenti del sistema operativo, in cui il server di deployment attiva un aggiornamento del sistema operativo sui server dell'applicazione. Su Linux, è comune utilizzare SSH per eseguire da remoto i comandi di aggiornamento. Su Windows, la telecomando PowerShell (si basa su WinRM) è una scelta comune. Per entrambi i meccanismi, devi essere in grado di eseguire l'autenticazione in modo sicuro e di archiviare le credenziali in modo sicuro.

Scalabilità automatica

In un ambiente statico in cui il numero di server delle app non cambia, il server di deployment conosce in anticipo tutte le destinazioni di deployment. In un ambiente cloud, spesso è utile scalare automaticamente il numero di server delle app verso l'alto e verso il basso. Ciò crea due sfide quando utilizzi deployment push:

  • Quando viene aggiunto un nuovo server app, registralo con il server di deployment per assicurarti che sia incluso nei deployment futuri.
  • Il nuovo server deve ricevere il deployment iniziale.

Un evento di scalabilità automatica non viene avviato dal server di deployment. Viene invece avviato dal gruppo di istanze gestite sottostante, che funziona a un livello inferiore a quello del server di deployment.

La nuova istanza di app server deve registrarsi al server di deployment e attivare un deployment prima che il nuovo server di app possa gestire le richieste. Il seguente diagramma illustra questo processo.

Scalabilità automatica con deployment basati su push

Affinché questo approccio funzioni, non è sufficiente che il server di deployment possa contattare e autenticare i server di app. Inoltre, i server di app devono contattare il server di deployment e autenticarsi.

Infine, il server lanciato di recente deve disporre anche delle patch di sicurezza del sistema operativo più recenti. L'avvio di un aggiornamento durante il processo di scalabilità automatica ritarderebbe notevolmente il processo. Pertanto, è necessario che gli aggiornamenti siano già installati nell'immagine da cui viene creata la VM dell'app. Puoi gestirlo in due modi:

  • Utilizzare le immagini pubbliche fornite da Google Cloud, che vengono sempre aggiornate da Google. Poiché queste immagini contengono solo il sistema operativo, devi gestire eventuali personalizzazioni (codice dell'app, utilità e configurazioni del sistema operativo) utilizzando gli script di avvio o come parte del deployment dell'app.
  • Mantenere un'immagine personalizzata del sistema operativo e mantenerla aggiornata. Questo ti consente di applicare personalizzazioni all'immagine, ma aumenta la complessità complessiva della gestione dei deployment.

L'esecuzione di deployment basati su push è intuitiva, ma può comportare una complessità complessa quando si prendono in considerazione la sicurezza, gli aggiornamenti del sistema operativo e la scalabilità automatica. La sezione successiva riguarda i deployment basati su pull, che rappresentano il modo più cloud-native per avvicinarsi ai deployment.

Deployment basati su pull

Nei deployment basati su pull, questi vengono eseguiti in modo indiretto. Dopo che il sistema CI ha prodotto una nuova versione di un artefatto di deployment, pubblica l'artefatto in un repository. Il seguente diagramma illustra questo flusso.

Deployment basati su pull

Quando viene eseguito un deployment, che può essere subito dopo la pubblicazione dell'elemento o in una fase successiva, il server di deployment attiva il deployment effettivo. Anche in questo caso, il server di deployment potrebbe essere un sistema separato o un ruolo previsto dal sistema CI. L'attivazione del deployment comporta la connessione al server app per l'estrazione e l'installazione dell'artefatto di deployment dal repository centrale.

Sebbene le differenze tra un modello basato su push e un modello basato su pull possano inizialmente sembrare minori, l'esecuzione di un deployment basato su pull ha alcune implicazioni importanti:

  • L'attivazione di un server app per il pull di un artefatto di deployment non deve avvenire a livello di app o sistema operativo. Il server di deployment può invece attivare l'operazione di pull chiedendo a Compute Engine di riavviare o sostituire la VM. Ciò può evitare le sfide di sicurezza associate ai deployment push.
  • Anziché limitarsi a contenere i file dell'app, l'artefatto di deployment può essere un'immagine Docker o un'immagine VM, che può unificare il processo di applicazione degli aggiornamenti dell'app e del sistema operativo.

Sicurezza

Per alcuni tipi di deployment, il server di deployment non deve affatto interagire con il server delle app. Ad esempio, non è necessaria alcuna interazione se l'elemento di deployment è uno dei seguenti:

  • Un'immagine VM.
  • Un'immagine Docker di cui eseguire il deployment in Google Kubernetes Engine.
  • Un pacchetto di cui eseguire il deployment in App Engine.

Il server di deployment deve semplicemente interagire con le API Google Cloud per avviare il deployment. A sua volta, questo processo di deployment può fare affidamento su meccanismi di autenticazione forniti da IAM, che eliminano la necessità di gestire chiavi o credenziali.

Quando utilizzi artefatti di deployment come pacchetti zip o NuGet, che contengono solo i file delle app e i programmi binari, puoi attivare un deployment in questi modi:

  • Se il server è configurato per eseguire il pull e installare l'elemento di deployment più recente all'avvio del sistema operativo, puoi attivare un aggiornamento con il riavvio della VM da parte di Google Cloud. Sebbene un riavvio possa sembrare inutilmente dispendioso in termini di tempo, ciò evita la necessità di autenticare il server di deployment con il server delle app.
  • Come nel caso dei deployment basati su push, il server di deployment può attivare l'aggiornamento a distanza tramite un canale posteriore. Tuttavia, questo approccio è soggetto alle stesse implicazioni di sicurezza e alle stesse difficoltà della gestione delle credenziali che si applicano ai deployment basati su push.
  • Il server di deployment può eseguire un agente che osserva il repository per i nuovi artefatti di deployment. Quando viene rilevato un nuovo artefatto, il server può applicarlo automaticamente. Un potenziale problema è dovuto al fatto che più server app potrebbero alla volta installare aggiornamenti e pertanto non essere disponibili. Per evitare ciò, l'agente può tenere traccia dello stato del server nel repository e utilizzare queste informazioni sullo stato del server per implementare gli aggiornamenti in modo controllato.

In ciascuno di questi casi, assicurati di controllare l'accesso in scrittura al repository per impedire ai server di estrarre e installare pacchetti dannosi.

Aggiornamenti del sistema operativo

Quando vengono utilizzate immagini Docker o VM come artefatti di deployment, questi artefatti combinano file di app e dipendenze. Ciò consente di utilizzare lo stesso meccanismo di deployment per l'aggiornamento del sistema operativo e per l'aggiornamento dell'applicazione. In questo caso, devi assicurarti che sia possibile creare e pubblicare un nuovo artefatto di deployment per due casi separati. Uno è quando una nuova versione dell'app diventa disponibile. Il secondo si verifica quando vengono rilasciati nuovi aggiornamenti della sicurezza al sistema operativo o altre dipendenze.

In altri casi, quando l'artefatto del deployment contiene solo i file dell'app, è un'attività separata mantenere aggiornato il sistema operativo. Di conseguenza, si applicano le stesse implicazioni discusse nel contesto dei deployment basati su push.

Scalabilità automatica

Avere server di app per estrarre gli artefatti di deployment è allineato all'idea di scalabilità automatica ed evita gran parte della complessità derivante dalla combinazione della scalabilità automatica con i deployment basati su push. Ogni volta che viene avviato un nuovo server di app a causa di un evento di scalabilità automatica, il server contatta il repository ed esegue il pull e installa il pacchetto di deployment più recente.

Se utilizzi immagini VM o Docker, i meccanismi per ottenere le immagini estratti sono forniti da Google Cloud. Se utilizzi altri pacchetti come gli archivi Zip o NuGet, devi configurare i server di app per avviare un deployment dopo l'avvio. Per farlo, puoi personalizzare l'immagine VM o utilizzare gli script di avvio.

Destinazioni di deployment

In passato, le app .NET funzionavano solo su Windows, e Windows non supportava i container. In questo modo non avevi più scelta sull'ambiente in cui eseguire la tua app.

Con l'avvento di .NET Core, puoi decidere se eseguire un'app su Windows o Linux. Inoltre, poiché entrambi i sistemi operativi supportano i container, ora hai più opzioni di scelta per l'ambiente di destinazione.

Sistema operativo

Anche se Mono offre da molti anni un modo per eseguire il deployment di app .NET su piattaforme diverse da Windows, è stato solo con il rilascio di .NET Core che Linux è diventata una piattaforma completamente supportata per lo stack di sviluppo Microsoft.

.NET Core fornisce solo un sottoinsieme delle funzionalità di .NET Framework. Di conseguenza, il targeting di .NET Core impone alcune restrizioni alle app. Ma soprattutto, per le app esistenti, il trasferimento da .NET Framework a .NET Core potrebbe non essere sempre facile ed economico; in alcuni casi potrebbe non essere possibile.

Pertanto, una scelta fondamentale per scegliere un modello e un target di deployment è se utilizzare Linux (che richiede .NET Core) o Windows (che supporta .NET Core o .NET Framework).

I potenziali vantaggi dell'esecuzione di app .NET su Linux sono i seguenti:

  • Puoi utilizzare l'ambiente flessibile di App Engine, un ambiente completamente gestito.
  • Puoi utilizzare GKE, un ambiente gestito che supporta l'orchestrazione dei container.
  • Puoi evitare il costo aggiuntivo delle immagini Compute Engine premium associate alle licenze Windows.

Devi valutare questi vantaggi rispetto ai seguenti potenziali svantaggi dell'utilizzo di .NET Core su Linux:

  • Lo sforzo necessario per trasferire un'app .NET esistente a .NET Core potrebbe compensare i potenziali risparmi sui costi. Oppure, come indicato, potrebbe non essere possibile trasferire un'app .NET esistente su .NET Core.
  • Linux non supporta IIS. Kestrel, il server web .NET Core, mostra prestazioni molto elevate, ma non offre lo stesso set di funzionalità di IIS. Di conseguenza, potrebbe essere necessario utilizzare Kestrel insieme a un server web come Nginx.
  • Non esiste un equivalente diretto di un servizio Windows su Linux. Anche se in genere puoi convertire i servizi Windows in app per console Linux che possono essere eseguite come daemon, questa conversione potrebbe non essere sempre facile.
  • La risoluzione dei problemi e il debug delle app .NET Core su Linux richiedono strumenti e competenze diversi rispetto a quando utilizzi .NET su Windows. Questo può dimostrarsi difficile se il team ha un'esperienza limitata con Linux.

Container

I container si prestano particolarmente bene alle app che vengono eseguite in un singolo processo. Ecco alcuni esempi:

  • Servizi Windows
  • App della console Linux che fungono da daemon
  • Servizi WCF self-hosted
  • App API MVC o API ASP.NET ospitate da Kestrel

Molte app .NET hanno come target IIS. Viene utilizzato comunemente per gestire più app (in directory virtuali e pool di app) separati e, di conseguenza, potrebbe non corrispondere al pattern di un singolo processo.

Quando sposti una configurazione basata su IIS in un container, puoi adottare approcci diversi:

  • Inserisci IIS, con tutte le directory virtuali e i pool, in una singola immagine Docker basata su Windows utilizzando l'immagine microsoft/iis come base. A meno che le app non siano ad alto accoppiamento, questo approccio di solito non è consigliabile, perché non consente l'aggiornamento e il deployment delle app separatamente.
  • Utilizza immagini Docker basate su Windows separate per ogni app, ciascuna con IIS in esecuzione. In questo modo puoi gestire le app in modo indipendente. Tuttavia, IIS comporta un overhead non trascurabile che può diventare significativo se è necessario gestire un numero elevato di questi container.
  • Esegui la migrazione di alcune o tutte le app da IIS a Kestrel. Poiché è possibile eseguire il deployment di Kestrel in un container basato su Windows o in un container Docker basato su Linux, questo approccio consente di gestire i container singolarmente.

IIS consente l'esecuzione di più app web in un unico sito web, condividendo un unico nome di dominio. Quando pacchettizzi app in container separati, puoi usufruire della stessa funzionalità con il bilanciamento del carico basato sui contenuti. Analogamente, un bilanciatore del carico HTTP di Google non rende necessario il deployment di un proxy inverso personalizzato davanti ai server Kestrel.

La maggior parte delle app può essere containerizzata, ma è raro averne una che non può esserlo. Tuttavia, alcuni scenari di containerizzazione presentano sfide:

  • Per le app gestite da IIS, il deployment delle app è già automaticamente automatizzato. Tuttavia, i passaggi per configurare IIS (creazione di pool di app, associazioni e così via) vengono eseguiti manualmente. Quando passi ai container, devi automatizzare anche tutti questi passaggi iniziali.
  • Le app basate su file di configurazione o sui dati ospitati su disco potrebbero richiedere modifiche. Ad esempio, le informazioni di configurazione possono essere ottenute dalle variabili di ambiente, mentre i file e le cartelle pertinenti possono essere montati come volume. In questo modo l'immagine rimane stateless e non è configurata per l'ambiente.

Infine, se utilizzi container Docker basati su Windows, tieni presente che Google Cloud attualmente non supporta Hyper-V e non consente di eseguire container Hyper-V. Di conseguenza, puoi eseguire il deployment dei container Windows Server solo in Google Cloud. I container Windows Server sono più leggeri dei container Hyper-V e offrono un diverso livello di isolamento.

Vincoli di deployment

Alcuni fattori nel modo in cui è stata creata l'app possono imporre vincoli all'approccio di deployment utilizzato, come discusso in questa sezione.

Architettura dell'app

Un fattore chiave da considerare quando si sceglie il target e il modello di deployment è l'architettura dell'app. Ad un'estremità dello spettro, un'app potrebbe seguire un pattern architetturale monolitico, in cui tutta la logica dell'app è implementata in un singolo codebase e viene eseguita in un singolo processo o pool di app IIS. All'altra estremità dello spettro, un'app potrebbe seguire un pattern di microservizi. Con questo approccio, l'app è costituita da una serie di servizi eseguiti in modo indipendente in processi distinti, in pool di app IIS distinti o come servizi Windows distinti.

Infine, potresti avere più app indipendenti di cui è stato eseguito il deployment utilizzando una strategia di deployment uniforme, in cui ogni app potrebbe essere monolitica. Ai fini di questa discussione, questo approccio può essere considerato equivalente allo scenario dei microservizi.

In un'architettura di microservizi, vuoi che l'app venga eseguita in modo conveniente mantenendo i servizi isolati e gestibili in modo indipendente. Puoi allocare VM dedicate per ogni servizio, garantendo in tal modo la gestione e il deployment individuali dei servizi. Tuttavia, questo approccio può comportare un numero elevato di VM sottoutilizzate, comportando costi non necessari. Per app come queste, è probabile che i modelli di deployment che consentono un imballaggio più rigido, in particolare i modelli basati su container, siano più vantaggiosi in termini di costi.

Stato e apolidia

Quando progetti le app per il cloud, prova a mantenere stateless le app e a gestirne lo stato esternamente utilizzando un servizio di archiviazione basato su Google Cloud. Le app stateless offrono una serie di vantaggi, tra cui:

  • Il deployment può essere eseguito in modo ridondante per aumentare la disponibilità e la capacità.
  • Le richieste possono essere distribuite liberamente tra le istanze.
  • Si prestano bene alla scalabilità automatica.
  • In caso di errore, l'ambiente (container o VM) può essere semplicemente ricreato senza il rischio di perdere i dati.

Progettare app come stateless non è sempre facile e molte app meno recenti non seguono questa pratica. Tuttavia, vale la pena analizzare la possibilità di rendere un'app stateless.

Stato della sessione

Le app ASP.NET e ASP.NET MVC utilizzano comunemente le sessioni per monitorare lo stato degli utenti, rendendo le applicazioni stateful. Tuttavia, sono disponibili diverse opzioni per limitare l'impatto delle sessioni:

  • Se la quantità di dati delle sessioni è ridotta, puoi memorizzare lo stato in un cookie criptato o firmato.
  • Anziché utilizzare il provider di stato della sessione InProc predefinito, puoi utilizzare il provider SQLServer. Tuttavia, ciò richiede un'istanza SQL Server, che comporta costi aggiuntivi e può influire sulla latenza e sulla disponibilità dell'app.
  • Puoi sfruttare l'affinità sessione in Cloud Load Balancing. Questa funzionalità garantisce che tutte le richieste da un singolo client vengano instradate alla stessa istanza di app. Tuttavia, l'utilizzo dell'affinità sessione può avere un impatto negativo sull'equità del bilanciamento del carico. Ciò significa che alcune istanze dell'app possono ricevere una quantità maggiore di richieste rispetto ad altre. Inoltre, se un'istanza di app viene terminata per qualsiasi motivo, le sessioni gestite dall'istanza andranno perse e ciò potrebbe avere un impatto sull'utente finale. Affidarsi all'affinità sessione non è quindi una soluzione ideale, ma spesso può essere un compromesso efficace tra robustezza e costo.

Cache in memoria

Le app comunemente utilizzano le cache in memoria per evitare calcoli ridondanti o ricerche nel database. Questo diventa problematico se più istanze dell'app sono in esecuzione contemporaneamente, perché le cache possono diventare incoerenti.

Per evitare incoerenze, utilizza una cache distribuita, direttamente o utilizzando l'interfaccia IDistributedCache. I server di memorizzazione nella cache come Redis o Memcached di solito hanno esigenze relative alle risorse relativamente basse, ma rendono più complessa la configurazione complessiva.

Archiviazione

I dati sotto forma di immagini, allegati o file multimediali sono generalmente archiviati su disco. In genere, l'utilizzo di un disco permanente su una VM non è un'opzione, perché impedisce la condivisione dei dati tra più macchine e rischia la perdita di dati se viene ricreata un'istanza VM. Puoi invece utilizzare uno dei seguenti approcci:

  • Spostare i dati in un server di condivisione file. In questo modo, ridurrai al minimo l'impatto sull'app. Tuttavia, l'utilizzo di un server SMB o NFS ad alta disponibilità comporta costi di manutenzione e costi aggiuntivi.
  • Spostare i dati in Cloud Storage. Sebbene richieda modifiche all'app, Cloud Storage è ad alta disponibilità, notevolmente più economico rispetto all'esecuzione di un file server e non richiede interventi di manutenzione aggiuntivi.
  • Spostare i dati nei file server di Filestore. Questo approccio potrebbe richiedere alcune modifiche all'app. Tuttavia, una volta eseguito il provisioning, puoi scalare la capacità delle istanze in base alle tue esigenze senza tempi di inattività. Filestore supporta anche più istanze di applicazioni simultanee che accedono contemporaneamente allo stesso file system.
  • Spostare i dati nel servizio Cloud Volumes. Il servizio Cloud Volumes ti consente di spostare le tue app basate su file in Google Cloud, con supporto per volumi NFS e SMB. Non è necessario riprogettare le app e ottieni spazio di archiviazione permanente per le tue app senza complessità.

Strategie di deployment

Quando esegui il deployment di una nuova versione di un'app, devi ridurre al minimo i rischi e l'impatto sugli utenti finali. Le tre strategie più comuni per raggiungere questo obiettivo sono ricreazione, blu/verde e deployment in sequenza.

Strategia di ricreazione

L'idea della strategia di ricreazione è di arrestare l'app in esecuzione su tutti i server, eseguire il deployment di una nuova versione e avviare l'app. Questa strategia ha l'evidente svantaggio di causare un'interruzione del servizio, ma evita potenziali problemi che possono sorgere quando due versioni diverse di un'app coesistono temporaneamente e accedono a dati comuni.

Strategia blu/verde

L'idea della strategia blu/verde (nota anche come rosso/nero) è il deployment di una nuova versione dell'app su un nuovo set di server. Al termine del deployment, cambi tutto il traffico dal vecchio insieme al nuovo set di server. Questo approccio richiede temporaneamente fino al doppio del numero di server di cui hai bisogno per la produzione, ma evita interruzioni del servizio.

Un prerequisito di questa strategia è che due versioni di un'app possano coesistere temporaneamente e non interferire tra loro. Per le app che accedono ai database, è necessario che ogni iterazione delle modifiche agli schemi dei database sia compatibile con almeno le versioni precedenti.

Strategia di deployment in sequenza

L'idea di un deployment in sequenza è aggiornare un server dopo l'altro. Come con la strategia blu/verde, ciò significa che per un certo periodo coesistono due versioni diverse di un'app. A differenza del deployment Blu/Verde, tuttavia, il traffico dalla precedente versione alla nuova versione viene gradualmente spostato. Man mano che un numero maggiore di server viene aggiornato, più utenti vengono indirizzati alla nuova versione fino all'ultimo aggiornamento, quando tutti gli utenti usano la nuova versione. Un vantaggio chiave di questo approccio è che i potenziali problemi possono essere rilevati in anticipo, prima che tutti gli utenti vengano interessati, il che aiuta a ridurre il rischio complessivo.

Poiché i deployment in sequenza richiedono due versioni dell'app per coesistere, questa strategia spesso richiede anche una configurazione del bilanciatore del carico che eviti di far rimbalzare gli utenti tra le versioni.

Opzioni di relative al deployment

Finora, questo articolo ha parlato di modelli, target e strategie di deployment. Le seguenti sezioni esaminano opzioni specifiche per il deployment di app .NET su Google Cloud.

GKE (Windows o Linux)

GKE offre un ambiente Kubernetes completamente gestito. Le funzionalità di orchestrazione di Kubernetes rendono GKE particolarmente adatto per l'esecuzione di app di microservizi complesse composte da molti container. Tuttavia, anche per le app che non seguono il pattern dei microservizi, GKE consente di eseguire molti container sull'infrastruttura condivisa in modo efficiente a livello di risorse e di semplice manutenzione.

GKE richiede che tutte le parti dell'app vengano pacchettizzate come container Docker. I container basati su Linux richiedono l'utilizzo di .NET Core e di un ambiente basato su Linux. La creazione di container in Linux può risultare difficile se il sistema CI è basato su Windows. Tuttavia, sia Azure Pipelines/Team Foundation Server che Cloud Build forniscono supporto integrato per la creazione di app .NET Core e per la creazione e la pubblicazione di immagini container basate su Linux.

GKE offre la massima flessibilità per le app stateless. Utilizzando set stateful e volumi permanenti, puoi anche eseguire determinati tipi di app stateful su GKE.

Un cluster GKE include una serie di istanze VM, dette nodi, su cui sono pianificati i container. In un cluster multi-zona o a livello di area geografica, GKE può distribuire nodi e carichi di lavoro su più zone per garantire l'alta disponibilità.

I prezzi si basano sul numero di nodi in esecuzione. GKE è quindi più conveniente se i nodi sono ben utilizzati. Puoi eseguire carichi di lavoro più grandi sullo stesso cluster o scalare automaticamente il numero di nodi necessario.

Deployment basato su pull mediante comandi kubectl

Il deployment di un'app in GKE prevede due passaggi:

  1. Pubblicazione di immagini Docker su Artifact Registry o in un registro Docker esterno utilizzando docker push o altri mezzi. Questo passaggio è in genere gestito dal sistema CI.
  2. Attivazione del deployment tramite kubectl. Questo passaggio può essere gestito dal sistema CI o separatamente. Poiché il deployment viene avviato da remoto, non importa se kubectl viene eseguito su Linux o Windows.

GKE ha il supporto integrato per le strategie di deployment e ricreazione e deployment. Sebbene le primitive per controllare i deployment siano abbastanza flessibili da consentire altre strategie di deployment, l'utilizzo di una strategia diversa richiede strumenti o script aggiuntivi.

Deployment basato su pull mediante Spinnaker

Se le funzionalità integrate di GKE per orchestrare i deployment non sono sufficienti per il tuo scopo, puoi combinare GKE con Spinnaker. Spinnaker ha un supporto integrato per GKE e consente di implementare strategie di deployment più avanzate, inclusi deployment blu/verdi.

Spinnaker non è un servizio gestito, pertanto devi eseguirne il deployment e gestirlo separatamente. Puoi eseguire il deployment di Spinnaker su istanze VM Linux separate o in un cluster GKE.

Knative e Cloud Run

Per i container stateless .NET Core, Knative e la sua versione gestita Cloud Run, forniscono un ambiente container serverless. I container serverless offrono vantaggi come provisioning, scalabilità automatica e bilanciamento del carico senza overhead per la gestione dell'infrastruttura.

Per il deployment di container in un cluster Kubernetes, Knative fornisce una piattaforma API di livello superiore e inferiore rispetto a Kubernetes. Knative può quindi aiutarvi a evitare le complessità di Kubernetes, semplificando il deployment del container.

Cloud Run segue l'API Knative, ma viene eseguito sull'infrastruttura Google, eliminando così la necessità di cluster Kubernetes. Cloud Run offre un'opzione serverless per i container. Per impostazione predefinita, i container in Cloud Run vengono scalati automaticamente e fatturati per la durata della richiesta. Il tempo di deployment è in secondi. Cloud Run fornisce inoltre funzionalità utili, come le revisioni e la suddivisione del traffico.

Cloud Run for Anthos è la versione più flessibile di Cloud Run che offre la semplicità di Knative e Cloud Run con la flessibilità operativa di Kubernetes. Ad esempio, Cloud Run su Anthos consente di aggiungere GPU alle istanze sottostanti che eseguono i container o di fare lo scale up dell'applicazione in molti container.

Cloud Run si integra con altri servizi come Pub/Sub, Cloud Scheduler, Cloud Tasks e backend come Cloud SQL. Può essere utilizzato sia per frontend web con scalabilità automatica sia per i microservizi interni attivati da eventi.

Compute Engine (Windows o Linux)

Compute Engine consente di creare e gestire le istanze VM. Supporta una gamma di versioni di Windows Server e distribuzioni Linux, oltre a opzioni di dimensionamento e configurazione. Grazie a questa flessibilità, puoi utilizzare le istanze VM di Compute Engine per un'ampia gamma di carichi di lavoro.

Per assicurarti che il deployment delle app venga eseguito e gestito singolarmente, esegui il deployment di una sola app o di un servizio per ogni istanza VM. Per garantire un'alta disponibilità, esegui almeno due istanze VM per app, ciascuna situata in una zona diversa. Pertanto, puoi supporre che tu abbia bisogno del doppio del numero di istanze VM rispetto al numero di app o servizi di cui vuoi eseguire il deployment, indipendentemente dal carico previsto.

Compute Engine offre un modo semplice per implementare la scalabilità automatica tramite gruppi di istanze gestite. I gruppi di istanze gestite forniscono anche un modo per implementare i deployment in sequenza, come descritto più avanti in questo articolo.

Dal momento che Compute Engine ha il prezzo per istanza VM, puoi presumere che l'esecuzione di app su Compute Engine sia la più conveniente quando le app ricevono un carico considerevole, il che si traduce in un elevato utilizzo delle istanze VM. Se, invece, il numero di servizi e app è elevato, ma l'utilizzo medio è basso, altre opzioni di deployment, come GKE, sono spesso più economiche, perché consentono a più app di utilizzare un'infrastruttura comune senza sacrificare l'isolamento del carico di lavoro.

Per eseguire le istanze VM Windows è necessario utilizzare immagini premium. Queste immagini contengono copie concesse in licenza di Windows e pertanto prevedono costi aggiuntivi. Di conseguenza, le VM Windows sono generalmente meno convenienti rispetto alle VM che utilizzano distribuzioni Linux, come CentOS o Debian, che non comportano addebiti per le licenze.

Puoi utilizzare SSH o RDP per configurare manualmente un'istanza VM, per eseguire il deployment di un'app manualmente o per gestire qualsiasi configurazione iniziale necessaria per preparare una macchina per un primo deployment. Tuttavia, questo può portare a macchine con configurazioni univoche, diverse dalle altre istanze VM. A lungo termine, la configurazione manuale di un'istanza VM può diventare complicato e richiedere molto lavoro. Per questo motivo, è consigliabile automatizzare il processo in modo che sia ripetibile.

L'automazione del deployment delle app su Compute Engine include queste attività:

  1. Provisioning e preparazione delle istanze VM per un primo deployment di app.
  2. Eseguire un deployment di app.
  3. Manutenzione del sistema operativo (installazione degli aggiornamenti della sicurezza).

Le due sezioni seguenti descrivono come gestire tutti e tre i passaggi in modo unificato utilizzando un approccio di deployment basato sul pull. Sebbene i meccanismi e gli strumenti siano diversi per gli approcci descritti in queste sezioni, l'idea generale è simile a come viene eseguito il deployment di un'app basata su container utilizzando GKE.

Deployment basato su pull mediante un gruppo di istanze gestite

I gruppi di istanze gestite sono comunemente utilizzati per implementare la scalabilità automatica, ma forniscono anche un modo per gestire i deployment in sequenza. Dopo aver creato un modello di istanza che fa riferimento alla nuova versione dell'app, puoi utilizzare la funzionalità di sostituzione in sequenza per sostituire le istanze VM che utilizzano il vecchio modello con quelle che utilizzano il nuovo modello.

Un prerequisito di questo approccio è che la nuova versione dell'app sia stata resa disponibile come modello di istanza. Puoi farlo in due modi:

  • Definisci un modello di istanza che utilizza una delle immagini del sistema operativo pubblico. Utilizza uno script di avvio per configurare il sistema e installare l'app da un bucket Cloud Storage, un repository NuGet, un registry Docker o un'altra origine. Il seguente diagramma illustra questo approccio.

    Deployment basati su pull mediante un gruppo di istanze gestite e un'immagine pubblica

  • Crea un'immagine VM personalizzata come parte del processo CI/CD, un processo spesso definito baking delle immagini. In questo approccio, puoi utilizzare una delle immagini del sistema operativo pubblico per generare una nuova istanza VM, installare l'applicazione più recente, creare un'immagine VM dall'istanza e rendere l'immagine disponibile nel progetto Google Cloud. L'intera procedura può essere completamente automatizzata utilizzando uno strumento come Packer. Sarà quindi possibile fare riferimento all'immagine risultante in un modello di istanza. Il seguente diagramma illustra questo approccio.

    Deployment basati su pull mediante un gruppo di istanze gestite e un'immagine personalizzata

Uno svantaggio di creare un'immagine personalizzata (la seconda opzione) è che la cottura delle immagini è un processo relativamente lento, che spesso richiede diversi minuti. L'approccio quindi non solo aggiunge complessità al processo CI/CD, ma lo rallenta anche. Inoltre, l'avvio di nuove VM con un'immagine personalizzata è un processo semplice e veloce, vantaggioso quando si utilizza la scalabilità automatica.

L'utilizzo di script di avvio per il deployment dell'app (la prima opzione) presenta compromessi significativi. Non comporta l'overhead della creazione di immagini nel processo CI/CD, ma rallenta il processo di creazione delle istanze VM. Inoltre, se lo script di avvio non è completamente affidabile o se i sistemi da cui sono scaricati i programmi binari non sono molto disponibili, questo approccio può comportare una minore disponibilità.

L'approccio più adatto alla tua app dipende dall'app stessa e dalla complessità della configurazione. In alcuni casi, è preferibile combinare entrambi gli approcci:

  • Un'immagine personalizzata contiene tutte le configurazioni e le dipendenze, ma non gli effettivi programmi binari dell'app. Viene creata una nuova immagine quando la configurazione o una qualsiasi delle dipendenze cambiano, ma non per ogni build dell'app. Ciò consente di evitare il rallentamento della pipeline CI/CD dell'app.
  • L'app viene installata utilizzando uno script di avvio. Per ridurre al minimo i rischi e il rallentamento, questa procedura dovrebbe essere il più semplice possibile.

In uno scenario in cui vuoi eseguire il deployment di molti servizi o app diversi con una configurazione di base comune, questo approccio ibrido può evitare di dover creare e mantenere decine o centinaia di immagini quasi identiche.

Puoi utilizzare i gruppi di istanze gestite per orchestrare i deployment per i carichi di lavoro Linux e Windows. Per Linux, l'utilizzo di gruppi di istanze gestite per il deployment dei container Docker nelle istanze VM è possibile e supportato dalla piattaforma. Tuttavia, è consigliabile solo per le app molto utilizzate. In altri casi, il deployment di un singolo container Docker per VM offre poco vantaggio rispetto all'utilizzo dell'ambiente flessibile GKE o App Engine.

Se utilizzi i container Windows Server, segui queste linee guida per eseguire i container utilizzando Compute Engine e i gruppi di istanze gestite:

  • Utilizza un'immagine personalizzata con Docker preinstallato o una delle seguenti immagini pubbliche:
    • Windows Server 2019 Datacenter Core for Containers
    • Windows Server 2019 Datacenter for Containers
  • Utilizza uno script di avvio per eseguire il pull dell'immagine Docker e avviarla come container Windows Server durante l'avvio della VM. Puoi utilizzare le mappature delle porte appropriate per esporre i servizi in esecuzione all'interno del container.

L'esecuzione di uno script di avvio non è garantita solo dopo l'avvio del servizio Docker. Per gestire in modo controllato il caso in cui lo script viene eseguito prima che Docker sia disponibile, incorpora la logica di nuovo tentativo appropriata nello script.

Quando crei immagini basate su Windows in un ambiente non cloud, potresti fare affidamento su Microsoft Deployment Toolkit (MDT) o Windows Deployment Services (WDS). Tuttavia, poiché la gestione delle immagini e la creazione di istanze VM basate su immagini personalizzate sono funzionalità di base di Compute Engine, questi strumenti aggiuntivi non sono necessari. Compute Engine supporta non solo gli script di avvio, ma anche gli script di specializzazione per istanze VM basate su Windows. Pertanto, di solito non è necessario lavorare con file unattend.xml personalizzati. Tuttavia, è comunque importante che un'installazione di Windows sia generalizzata utilizzando GCESysprep prima di creare un'immagine.

Deployment basato su pull mediante Spinnaker

I gruppi di istanze gestite forniscono un modo semplice ed efficiente per implementare i deployment in sequenza, ma le funzionalità dei gruppi di istanze gestite potrebbero essere insufficienti per alcune app. Per implementare strategie e pipeline di deployment più sofisticate, puoi utilizzare Spinnaker.

L'approccio base adottato da Spinnaker per orchestrare i deployment su Compute Engine è simile a quello discusso nella sezione precedente, ovvero si basa anche sulla creazione di immagini. Di conseguenza, valgono le stesse considerazioni.

Spinnaker non è un servizio gestito, pertanto devi eseguirne il deployment e gestirlo separatamente dall'app. Puoi eseguire il deployment di Spinnaker su istanze VM Linux separate o in un cluster GKE.

Deployment remoto basato su push

Le opzioni di deployment basate su pull illustrate nelle sezioni precedenti offrono una serie di vantaggi. Tuttavia, non sono appropriate per ogni tipo di app. In particolare, le app stateful spesso non si prestano bene a questo approccio e potrebbero essere più adatte a un approccio basato sul push.

Nell'approccio basato sul push, le tre attività di deployment (provisioning delle istanze VM, esecuzione del deployment dell'app e manutenzione del sistema operativo) devono essere gestite singolarmente. È possibile utilizzare gli stessi strumenti per tutte e tre le attività, ma non è raro utilizzare strumenti diversi per ogni attività.

Puoi eseguire il provisioning delle istanze VM dell'app nello stesso modo di altre infrastruttura, utilizzando gli strumenti di automazione come Terraform. Puoi utilizzare script di avvio o di specializzazione per installare gli strumenti necessari per automatizzare il deployment delle app. Ad esempio, se utilizzi Puppet, Chef o Octopus Deploy, devi assicurarti che il software dell'agente per questi strumenti sia installato.

Dal punto di vista della sicurezza, per ridurre la superficie di attacco, assicurati che qualsiasi comunicazione tra il server di deployment e gli agenti in esecuzione sulle istanze VM del server delle app utilizzi la rete interna. Inoltre, assicurati che le porte utilizzate non siano esposte alla rete Internet pubblica.

In un ambiente in cui la scalabilità automatica non viene utilizzata, l'unione dei server di app basati su Windows a un dominio Active Directory è un modo efficace per centralizzare la configurazione. L'utilizzo di Active Directory ti consente inoltre di controllare le attività di gestione, come la manutenzione del sistema operativo.

Scelta di un'opzione di deployment

Come indicato all'inizio di questo articolo, non esiste un unico modo migliore per eseguire il deployment di un'app .NET su Google Cloud. Le migliori opzioni di deployment per te dipendono dall'app e dai requisiti. Per scegliere il modello giusto, una delle prime domande è se utilizzare .NET Core o .NET Framework e, a seconda di questo, se eseguire il deployment su Linux o Windows. Dopo aver identificato il sistema operativo di destinazione, utilizza le seguenti strutture decisionali per identificare un modello di deployment adatto.

Per il deployment delle app .NET Core su Linux:

Albero decisionale per il deployment tramite .NET Core e Linux

Per il deployment di un'app .NET Core o .NET Framework su Windows:

Albero decisionale per il deployment tramite Windows

Passaggi successivi