Questa pagina fornisce una panoramica su come eseguire il deployment delle app .NET su Google Cloud e indicazioni su come scegliere l'approccio di deployment giusto per la tua app.
Introduzione
Il framework Microsoft .NET fornisce un ricco insieme di strumenti e librerie per lo sviluppo di app. Con l'avvento del supporto di Docker su Windows e la possibilità di eseguire app .NET su Linux, le app .NET ora possono supportare anche una serie di target di deployment.
Per uno sviluppo e test efficienti, puoi automatizzare il deployment dell'app e renderlo parte di una pipeline di integrazione continua e 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 quale approccio di deployment vuoi adottare.
Non esiste un modo migliore per eseguire il deployment di un'app .NET su Google Cloud. Le opzioni di deployment migliori per te dipendono dall'app e dai tuoi requisiti. Ad esempio, se la tua app richiede .NET Framework completo o deve essere eseguita su IIS, il deployment si baserà su Windows. D'altra parte, se la tua app può essere eseguita con la funzionalità supportata da .NET, hai la possibilità di eseguire il deployment in Linux.
Questa pagina esamina i vari modi in cui puoi eseguire app .NET e implementarle su Google Cloud, incluse le condizioni in cui ogni opzione è adatta. Alla fine, le opzioni di deployment vengono riepilogate in un albero decisionale per aiutarti a decidere quali Google Cloud componenti e approcci sono più adatti per la tua app .NET.
Modelli di deployment
Esistono due modi di base per eseguire il deployment automatico di un'app. Il pacchetto di deployment viene trasferito ai server dell'app oppure i server dell'app recuperano il pacchetto dell'app da una posizione nota. Le sezioni seguenti illustrano le differenze tra questi due modelli.
Deployment basati sul push
In un deployment basato sul 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 delle app, copia l'artefatto di deployment e ne avvia l'installazione. Se è presente più di un server delle app, questo processo viene ripetuto in parallelo o, più comunemente, in sequenza in modo che gli artefatti vengano distribuiti a tutti i server delle app.
Il seguente diagramma illustra questo flusso.
Sono disponibili diversi 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 dei passaggi di deployment è definita in modo simile a uno script. Sebbene questo approccio sia intuitivo, è soggetto a deriva della configurazione, ovvero dopo un certo periodo di tempo, gli stati di più macchine potrebbero non essere identici e potrebbero non riflettere completamente lo stato previsto. Molti strumenti, pertanto, ti consentono di definire lo stato che vuoi ottenere, lasciando allo strumento il compito di capire i passaggi necessari per realizzarlo.
Su Windows, gli strumenti comunemente utilizzati per questo modello di deployment includono:
- Microsoft Web Deploy, uno strumento senza costi progettato per eseguire il deployment remoto di app web sui server IIS.
- Octopus Deploy, un software commerciale che consente di orchestrare le implementazioni in modo flessibile su flotte di macchine.
- Microsoft Team Foundation Server o agenti Azure Pipelines, che si integrano direttamente con la funzionalità di gestione delle release di TFS o Azure Pipelines.
- Windows PowerShell Desired State Configuration (DSC), una funzionalità integrata di Windows Server 2012 R2 e versioni successive.
Gli strumenti open source più utilizzati includono Ansible, Chef Infra e Puppet. Sebbene questi strumenti siano destinati principalmente a Linux, sono anche in grado di eseguire il deployment di destinazioni Windows.
Sicurezza
Affinché il server di deployment possa eseguire il push di un deployment su un server delle app, deve essere disponibile un canale secondario. Ad esempio, Web Deploy e Octopus Deploy utilizzano 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 impedire agli autori di attacchi di utilizzare il canale secondario per distribuire app dannose. Ancora più importante, la comunicazione sicura richiede che il server di deployment sia in grado di autenticarsi con il server delle app.
SSH può utilizzare l'autenticazione a chiave pubblica. Se utilizzi una configurazione IAM appropriata, puoi consentire a Google Cloud di occuparsi 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 per te e devi gestire questa attività autonomamente.
Un'opzione è Active Directory. Se sia il server di deployment che il server delle 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 tollerante agli errori richiede almeno due istanze VM aggiuntive per eseguire i domain controller. Se la configurazione utilizza la scalabilità automatica, anche tutti i server devono essere uniti dinamicamente al dominio, il che rallenta il processo di avvio di un server. La scalabilità automatica può anche portare all'accumulo di oggetti computer obsoleti nella directory, richiedendo una logica di scavenging aggiuntiva. Se utilizzi Active Directory in un ambiente basato su cloud, devi tenere conto di questi fattori aggiuntivi.
In assenza di Active Directory, l'autenticazione deve essere gestita utilizzando NTLM o con altri mezzi, ad esempio l'autenticazione di base HTTP. Entrambi gli approcci richiedono che le credenziali vengano mantenute sincronizzate tra il server di deployment e i server delle app e che vengano archiviate in modo sicuro. Entrambe queste attività possono rivelarsi difficili.
Indipendentemente dal fatto che utilizzi Linux o Windows, la protezione della comunicazione tra i server di deployment e delle app richiede meccanismi separati da IAM. Tuttavia, l'utilizzo di più meccanismi per controllare l'accesso ai sistemi aumenta la complessità complessiva e quindi il rischio di errori di configurazione accidentali.
Aggiornamenti del sistema operativo
È importante poter eseguire il deployment in modo efficiente di nuove versioni di pacchetti di app sui server delle app, ma è anche fondamentale gestire il sistema operativo sottostante su questi server. Ciò significa installare patch di sicurezza. Per i parchi server più grandi, devi automatizzare questo processo in modo da ridurre al minimo il rischio e il numero di server non disponibili durante l'aggiornamento.
Puoi anche utilizzare un approccio push per gli aggiornamenti del sistema operativo, in cui il server di deployment attiva un aggiornamento del sistema operativo sui server delle app. Su Linux, è comune utilizzare SSH per eseguire da remoto i comandi di aggiornamento. Su Windows, PowerShell remoting (che si basa su WinRM) è una scelta comune. Per entrambi i meccanismi, devi essere in grado di autenticarti 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. Ciò crea due sfide quando utilizzi implementazioni basate sul push:
- Quando viene aggiunto un nuovo server delle app, registralo con il server di deployment per assicurarti che venga 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 del server delle app deve registrarsi con il server di deployment e attivare un deployment prima che possa gestire le richieste. Il seguente diagramma illustra questo processo.
Affinché questo approccio funzioni, non è sufficiente che il server di deployment possa contattare e autenticarsi con i server delle app. Anche i server delle app devono contattare il server di deployment ed eseguire l'autenticazione.
Infine, il server appena lanciato deve disporre anche delle patch di sicurezza del sistema operativo più recenti. L'avvio di un aggiornamento durante il processo di scalabilità automatica ritarderebbe in modo significativo il processo. Pertanto, l'immagine da cui viene creata la VM server delle app deve avere già installato gli aggiornamenti. Puoi gestire questa impostazione in due modi:
- Utilizza le immagini pubbliche fornite da Google Cloud, che vengono mantenute aggiornate da Google. Poiché queste immagini contengono solo il sistema operativo, devi gestire qualsiasi personalizzazione (il codice dell'app, le utilità e le configurazioni del sistema operativo) utilizzando script di avvio o nell'ambito del deployment dell'app.
- Mantieni un'immagine del sistema operativo personalizzata e aggiornala. In questo modo puoi applicare personalizzazioni all'immagine, ma aumenta la complessità complessiva della gestione delle implementazioni.
L'esecuzione di deployment basati sul push è intuitiva, ma può comportare una complessità sostanziale se si prendono in considerazione sicurezza, aggiornamenti del sistema operativo e scalabilità automatica. La sezione successiva tratta i deployment basati sul pull, che sono il modo più cloud-native per affrontare i deployment.
Deployment basati sul pull
Nei deployment basati sul pull, i deployment vengono eseguiti in modo indiretto. Dopo che il sistema CI ha prodotto una nuova versione di un artefatto di deployment, lo pubblica in un repository. Il seguente diagramma illustra questo flusso.
Quando viene eseguito un deployment, che potrebbe avvenire immediatamente dopo la pubblicazione dell'artefatto 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 che il sistema CI assume. L'attivazione del deployment prevede la connessione al server delle app per estrarre e installare l'artefatto di deployment dal repository centrale.
Sebbene le differenze tra un modello basato sul push e uno basato sul pull possano inizialmente sembrare minime, l'esecuzione di un deployment basato sul pull ha alcune importanti implicazioni:
- L'attivazione di un server delle app per estrarre un artefatto di deployment non deve avvenire a livello di app o sistema operativo. Il server di deployment può attivare l'operazione di pull facendo riavviare o sostituire la VM da Compute Engine. In questo modo è possibile evitare i problemi di sicurezza associati ai deployment basati sul push.
- Anziché contenere semplicemente i file dell'app, l'artefatto di deployment può essere un'immagine Docker o un'immagine VM, il 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 interagire con il server delle app. Ad esempio, non è necessaria alcuna interazione se l'artefatto di deployment è uno dei seguenti:
- Un'immagine VM.
- Un'immagine Docker da eseguire il deployment in Google Kubernetes Engine.
- Un pacchetto da eseguire il deployment in App Engine.
Il server di deployment deve solo interagire con le APIGoogle Cloud per avviare il deployment. Ciò significa a sua volta che la procedura di deployment può basarsi sui meccanismi di autenticazione forniti da IAM, il che elimina la necessità di gestire chiavi o credenziali.
Quando utilizzi artefatti di deployment come pacchetti ZIP o NuGet, che contengono solo i file e i binari dell'app, puoi attivare un deployment in questi modi:
- Se il server è configurato per estrarre e installare l'artefatto di deployment più recente all'avvio del sistema operativo, puoi attivare un aggiornamento riavviando la VM. Google Cloud Anche se un riavvio può sembrare inutilmente dispendioso in termini di tempo, in questo modo si evita la necessità che il server di deployment si autentichi con il server delle app.
- Come per le implementazioni basate sul push, il server di deployment può attivare l'aggiornamento da remoto utilizzando un canale secondario. Tuttavia, questo approccio è soggetto alle stesse implicazioni di sicurezza e alle stesse sfide di gestione delle credenziali che si applicano alle implementazioni basate sul push.
- Il server di deployment può eseguire un agente che monitora il repository per nuovi artefatti di deployment. Quando viene rilevato un nuovo artefatto, il server può applicarlo automaticamente. Un potenziale problema è che più server delle app potrebbero finire per installare gli aggiornamenti contemporaneamente e quindi non essere disponibili. Per evitare questo problema, l'agente può monitorare lo stato del server nel repository e utilizzare queste informazioni per fornire aggiornamenti in modo controllato.
In ognuno 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 le immagini Docker o VM vengono utilizzate come artefatti di deployment, questi artefatti combinano file e dipendenze delle app. In questo modo puoi utilizzare lo stesso meccanismo di deployment per aggiornare il sistema operativo e l'app. In questo caso, devi assicurarti che sia possibile creare e pubblicare un nuovo artefatto di deployment per due casi separati. Una è quando diventa disponibile una nuova versione dell'app. Il secondo è quando vengono rilasciati nuovi aggiornamenti della sicurezza per il sistema operativo o altre dipendenze.
In altri casi, in cui l'artefatto di deployment contiene solo i file dell'app, l'aggiornamento del sistema operativo è un'attività separata. Pertanto, si applicano le stesse implicazioni discusse nel contesto delle implementazioni basate sul push.
Scalabilità automatica
Il fatto che i server delle app estraggano gli artefatti di deployment è in linea con l'idea di scalabilità automatica ed evita gran parte della complessità che deriva dalla combinazione della scalabilità automatica con i deployment basati sul push. Ogni volta che viene avviato un nuovo server delle app a causa di un evento di scalabilità automatica, il server contatta il repository, recupera e installa l'ultimo pacchetto di deployment.
Se utilizzi immagini VM o Docker, i meccanismi per il pull delle immagini sono forniti da Google Cloud. Se utilizzi altri pacchetti come archivi zip o NuGet, devi configurare i server delle app per avviare un deployment dopo l'avvio. Puoi farlo personalizzando l'immagine VM o utilizzando script di avvio.
Destinazioni di deployment
In passato, le app .NET venivano eseguite solo su Windows e Windows non supportava i container. In questo modo, avevi poca scelta sull'ambiente in cui eseguire la tua app.
Con l'avvento di .NET, puoi scegliere se eseguire un'app su Windows o su Linux. Poiché entrambi i sistemi operativi supportano i container, ora hai diverse opzioni per l'ambiente di destinazione.
Sistema operativo
Sebbene Mono offra un modo per eseguire il deployment di app .NET su piattaforme diverse da Windows da molti anni, è stato solo con il rilascio di .NET che Linux è diventata una piattaforma completamente supportata per lo stack di sviluppo Microsoft.
.NET fornisce solo un sottoinsieme delle funzionalità di .NET Framework. Pertanto, il targeting .NET impone determinate limitazioni alle app. Ancora più importante per le app esistenti, il porting da .NET Framework a .NET potrebbe non essere sempre semplice ed economico; in alcuni casi, potrebbe non essere possibile.
Pertanto, una domanda fondamentale quando si sceglie un modello di deployment e una destinazione è se utilizzare Linux (che richiede .NET) o Windows (che supporta .NET o .NET Framework).
I potenziali vantaggi dell'esecuzione di app .NET su Linux includono 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 su Linux:
- L'impegno necessario per eseguire il porting di un'app .NET Framework esistente a .NET potrebbe compensare i potenziali risparmi sui costi. Come indicato, potrebbe non essere possibile portare un'app .NET Framework esistente in .NET.
- Linux non supporta IIS. Kestrel, il web server .NET, offre prestazioni molto buone, ma non offre lo stesso set di funzionalità di IIS. Pertanto, potresti dover utilizzare Kestrel in combinazione con un server web come Nginx.
- Non esiste un equivalente diretto di un servizio Windows su Linux. Sebbene di solito sia possibile convertire i servizi Windows in app console Linux che possono essere eseguite come daemon, questa conversione potrebbe non essere sempre semplice.
- La risoluzione dei problemi e il debug delle app .NET su Linux richiedono strumenti e competenze diversi rispetto a quando utilizzi .NET su Windows. Ciò può rivelarsi difficile se il tuo team ha un'esperienza limitata con Linux.
Container
I container si prestano particolarmente bene alle app che vengono eseguite in un unico processo. Ecco alcuni esempi:
- Servizi Windows
- App console Linux che fungono da daemon
- Servizi WCF self-hosted
- App ASP.NET MVC o Web API ospitate da Kestrel
Molte app .NET hanno come target IIS. Viene comunemente utilizzato per gestire più app (in directory virtuali e pool di app separati) e potrebbe quindi non corrispondere al pattern a processo singolo.
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/iiscome base. A meno che le app non siano strettamente accoppiate, questo approccio di solito non è consigliabile, perché non consente di aggiornare e implementare le app separatamente. - Utilizza immagini Docker basate su Windows separate per ogni app, ognuna in esecuzione di IIS. In questo modo puoi gestire le app in modo indipendente. Tuttavia, IIS comporta un overhead non trascurabile che può diventare significativo se devi gestire un numero elevato di questi container.
- Esegui la migrazione di alcune o di tutte le app da IIS a Kestrel. Poiché Kestrel può essere implementato in un container basato su Windows o in un container Docker basato su Linux, questo approccio ti 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 raggruppi le app in container separati, puoi ottenere la stessa funzionalità utilizzando il bilanciamento del carico basato sui contenuti. Allo stesso modo, un bilanciatore del carico HTTP di Google rende superfluo il deployment di un proxy inverso personalizzato davanti ai server Kestrel.
La maggior parte delle app può essere containerizzata; è raro che non sia possibile. Tuttavia, alcuni scenari di containerizzazione presentano delle sfide:
- Per le app gestite da IIS, è comune che il deployment dell'app sia già automatizzato. Tuttavia, i passaggi per configurare IIS (creazione di pool di applicazioni, binding e così via) vengono eseguiti manualmente. Quando passi ai container, devi automatizzare anche tutti questi passaggi iniziali.
- Le app che si basano su file di configurazione o su dati che si trovano sul disco potrebbero richiedere modifiche. Ad esempio, le informazioni di configurazione possono essere ottenute da variabili di ambiente e i file e le cartelle pertinenti possono essere montati come volume. In questo modo, l'immagine rimane stateless e priva di configurazione specifica per l'ambiente.
Infine, se utilizzi container Docker basati su Windows, tieni presente che Google Cloud non supporta Hyper-V e non ti consente di eseguire container Hyper-V. Pertanto, 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 relativi alla modalità di creazione dell'app possono imporre vincoli all'approccio di deployment che utilizzi, come descritto in questa sezione.
Architettura dell'app
Un fattore chiave da considerare quando si sceglie il modello e la destinazione di deployment è l'architettura dell'app. A un'estremità dello spettro, un'app potrebbe seguire un pattern architetturale monolitico, in cui tutta la logica dell'app viene implementata in un unico codebase ed eseguita in un singolo processo o pool di app IIS. All'altra estremità dello spettro, un'app potrebbe seguire un pattern di microservizi. In questo approccio, l'app è costituita da una serie di servizi che vengono eseguiti in modo indipendente in processi separati, in pool di applicazioni IIS separati o come servizi Windows separati.
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 economicamente vantaggioso mantenendo i servizi isolati e gestibili in modo indipendente. Puoi allocare VM dedicate per ogni servizio, il che garantisce che i servizi possano essere gestiti e implementati individualmente. Tuttavia, questo approccio può comportare un numero elevato di VM sottoutilizzate, con conseguenti costi inutili. Per app come queste, i modelli di deployment che consentono un impacchettamento più compatto, in particolare i modelli basati su container, sono quindi probabilmente più convenienti.
Stato e apolidia
Quando progetti app per il cloud, cerca di mantenerle senza stato e gestisci lo stato esternamente utilizzando un servizio di archiviazione basato su Google Cloud . Le app stateless offrono una serie di vantaggi, tra cui:
- Possono essere implementati 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 ricreato senza il rischio di perdita di dati.
La progettazione di app stateless non è sempre semplice e molte app meno recenti non seguono questa pratica. Tuttavia, vale la pena analizzare se puoi rendere un'app stateless.
Stato della sessione
Le app ASP.NET e ASP.NET MVC utilizzano comunemente le sessioni per monitorare lo stato dell'utente, rendendo l'app stateful. Tuttavia, esistono diverse opzioni per limitare l'impatto delle sessioni:
- Se la quantità di dati di sessione è ridotta, puoi memorizzare lo stato in un cookie criptato o firmato.
- Anziché utilizzare il provider di stato della sessione
InProcpredefinito, puoi utilizzare il providerSQLServer. 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à di sessione in Cloud Load Balancing. Questa funzionalità assicura che tutte le richieste di un singolo client vengano indirizzate alla stessa istanza dell'app. Tuttavia, l'utilizzo dell'affinità sessione può avere un impatto negativo sull'equità del bilanciamento del carico, ovvero alcune istanze dell'app possono finire per ricevere più richieste rispetto ad altre. Inoltre, se un'istanza dell'app viene terminata per qualsiasi motivo, tutte le sessioni gestite dall'istanza andranno perse, con potenziali conseguenze per l'utente finale. Pertanto, fare affidamento sull'affinità di sessione non è una soluzione ideale, ma spesso può essere un compromesso valido tra robustezza e costi.
Cache in memoria
Le app utilizzano comunemente le cache in memoria per evitare calcoli ridondanti o ricerche nel database. Ciò diventa problematico se vengono eseguite più istanze dell'app contemporaneamente, perché le cache possono diventare incoerenti.
Per evitare incoerenze, utilizza una cache distribuita, direttamente o
tramite l'interfaccia IDistributedCache. I server di memorizzazione nella cache come
Redis o Memcached di solito hanno
requisiti di risorse relativamente bassi, ma aggiungono complessità alla configurazione generale.
Archiviazione
I dati sotto forma di immagini, allegati o file multimediali vengono in genere archiviati su disco. L'utilizzo di un disco permanente su una VM a questo scopo di solito non è un'opzione, perché impedisce la condivisione dei dati tra più macchine e rischia la perdita di dati se viene ricreata un'istanza VM. In alternativa, puoi utilizzare uno dei seguenti approcci:
- Sposta i dati su un server di condivisione file. Ciò riduce al minimo l'impatto sull'app. Tuttavia, il funzionamento di un server SMB o NFS a disponibilità elevata implica costi e impegno di manutenzione aggiuntivi.
- Sposta i dati in Cloud Storage. Sebbene ciò richieda modifiche all'app, Cloud Storage è altamente disponibile, molto più conveniente rispetto all'esecuzione di un file server e non richiede ulteriori interventi di manutenzione.
- Sposta i dati nei file server Filestore. Questo approccio potrebbe richiedere alcune modifiche all'app, ma una volta eseguito il provisioning, puoi scalare la capacità delle istanze in base alle esigenze senza tempi di inattività. Filestore supporta anche più istanze di applicazioni simultanee che accedono contemporaneamente allo stesso file system.
- Sposta i dati in Cloud Volumes Service. Cloud Volumes Service ti consente di spostare le tue app basate su file su Google Cloud, con supporto per volumi NFS e SMB. Non devi riprogettare le tue app e ottieni uno 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 il rischio e l'impatto sull'utente finale. Le tre strategie più comuni per raggiungere questo obiettivo sono Ricrea, Blu/verde e Deployment in sequenza.
Strategia di ricreazione
L'idea della strategia Ricrea è di arrestare l'app in esecuzione su tutti i server, eseguire il deployment di una nuova versione e avviare l'app. Questa strategia presenta l'ovvio 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 (chiamata anche rosso/nero) è quella di eseguire il deployment di una nuova versione dell'app su un nuovo set di server. Al termine del deployment, sposti tutto il traffico dal vecchio al nuovo insieme di server. Questo approccio richiede temporaneamente fino al doppio dei server necessari per la produzione, ma evita l'interruzione del servizio.
Un prerequisito per questa strategia è che due versioni di un'app possano coesistere temporaneamente e non interferire tra loro. Per le app che accedono ai database, ogni iterazione delle modifiche agli schemi dei database deve essere compatibile con le versioni precedenti.
Strategia di deployment in sequenza
L'idea di un deployment in sequenza è quella di aggiornare un server dopo l'altro. Come per la strategia blu/verde, ciò significa che per un determinato periodo di tempo coesistono due versioni diverse di un'app. A differenza del deployment blu/verde, tuttavia, il traffico viene spostato gradualmente dalla versione precedente a quella nuova. Man mano che vengono aggiornati più server, un numero maggiore di utenti viene indirizzato alla nuova versione finché, quando l'ultimo server è stato aggiornato, tutti gli utenti utilizzano la nuova versione. Un vantaggio fondamentale di questo approccio è che i potenziali problemi possono essere rilevati in anticipo, prima che tutti gli utenti ne siano interessati, il che contribuisce a ridurre il rischio complessivo.
Poiché i deployment in più fasi richiedono la coesistenza di due versioni dell'app, questa strategia spesso richiede anche una configurazione del bilanciamento del carico che eviti di reindirizzare gli utenti tra le versioni.
Opzioni di deployment
Finora, questa pagina ha trattato modelli, target e strategie di deployment. Le sezioni seguenti esaminano opzioni specifiche per il deployment di app .NET su Google Cloud.
GKE (Windows o Linux)
GKE fornisce un ambiente Kubernetes completamente gestito. Le funzionalità di orchestrazione di Kubernetes rendono GKE particolarmente adatta all'esecuzione di app di microservizi complesse costituite da molti container. Tuttavia, anche per le app che non seguono il pattern dei microservizi, GKE ti consente di eseguire molti container su un'infrastruttura condivisa in modo efficiente dal punto di vista delle risorse e semplice da gestire.
GKE richiede che tutte le parti dell'app vengano pacchettizzate come container Docker. I container basati su Linux richiedono l'uso di .NET e un ambiente basato su Linux. La creazione di container in Linux può rivelarsi difficile se il tuo sistema CI è basato su Windows. Tuttavia, sia Azure Pipelines che Team Foundation Server e Cloud Build forniscono supporto integrato per la creazione di app .NET e per la creazione e la pubblicazione di immagini container basate su Linux.
GKE offre la massima flessibilità per le app stateless. Utilizzando StatefulSet e volumi permanenti, puoi anche eseguire alcuni tipi di app stateful su GKE.
Un cluster GKE include un numero di istanze VM, chiamate nodi, su cui vengono pianificati i container. In un cluster multizona o regionale, GKE può distribuire nodi e workload su più zone per garantire un'alta disponibilità.
I prezzi si basano sul numero di nodi in esecuzione. Pertanto, GKE è più conveniente quando i nodi vengono utilizzati in modo ottimale. Puoi eseguire workload più grandi sullo stesso cluster o scalando automaticamente il numero di nodi in base alle esigenze.
Deployment basato sul pull utilizzando i comandi kubectl
Il deployment di un'app in GKE comporta due passaggi:
- Pubblicazione di immagini Docker in
Artifact Registry
o in un registro Docker esterno utilizzando
docker pusho altri mezzi. Questo passaggio viene in genere gestito dal sistema CI. - Attivazione del deployment utilizzando
kubectl. Questo passaggio può essere gestito dal sistemaCIa o separatamente. Poiché il deployment viene avviato da remoto, non importa sekubectlviene eseguito su Linux o Windows.
GKE supporta le strategie di deployment ricrea e rolling. Sebbene le primitive per controllare le implementazioni siano abbastanza flessibili da consentire altre strategie di implementazione, l'utilizzo di una strategia diversa richiede strumenti o script aggiuntivi.
Deployment basato sul pull utilizzando Spinnaker
Se le funzionalità integrate di GKE per l'orchestrazione dei deployment non sono sufficienti per il tuo scopo, puoi combinare GKE con Spinnaker. Spinnaker supporta GKE in modo nativo e ti consente di implementare strategie di deployment più avanzate, inclusi i deployment blu/verde.
Poiché Spinnaker non è un servizio gestito, devi eseguirne il deployment e la manutenzione separatamente. Puoi eseguire il deployment di Spinnaker su istanze VM Linux separate o in un cluster GKE.
Knative e Cloud Run
Per i tuoi container .NET stateless, Knative e la sua versione gestita, Cloud Run, forniscono un ambiente serverless per i container. I container serverless offrono vantaggi come il provisioning, la scalabilità automatica e il bilanciamento del carico senza l'overhead della gestione dell'infrastruttura.
Per il deployment di container in un cluster Kubernetes, Knative fornisce una superficie API di livello superiore e più piccola di Kubernetes. Knative può quindi aiutarti a evitare le complessità di Kubernetes, semplificando il deployment dei 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 è espresso in secondi. Cloud Run fornisce anche funzionalità utili, come revisioni e suddivisione del traffico.
Knative serving è 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 GKE Enterprise ti consente di aggiungere GPU alle istanze sottostanti che eseguono i tuoi container o di scalare la tua applicazione a 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 i frontend web scalati automaticamente sia per i microservizi interni attivati dagli eventi.
Compute Engine (Windows o Linux)
Compute Engine consente di creare e gestire 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 garantire che le app vengano implementate e gestite singolarmente, esegui il deployment di una sola app o servizio per ogni istanza VM. Per garantire l'alta disponibilità, esegui almeno due istanze VM per app, ciascuna situata in una zona diversa. Pertanto, puoi presumere di aver bisogno del doppio del numero di istanze VM rispetto al numero di app o servizi che vuoi deployment, indipendentemente dal carico previsto.
Compute Engine offre un modo semplice per implementare la scalabilità automatica tramite i gruppi di istanze gestite. I gruppi di istanze gestite forniscono anche un modo per implementare i deployment in sequenza, come descritto più avanti in questa pagina.
Poiché Compute Engine ha un prezzo per istanza VM, puoi presumere che l'esecuzione di app su Compute Engine sia più conveniente quando le app ricevono un carico considerevole, il che si traduce in un utilizzo elevato delle istanze VM. Al contrario, se 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 dei carichi di lavoro.
Per eseguire istanze VM Windows devi utilizzare immagini premium. Queste immagini contengono copie con licenza di Windows e pertanto comportano 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 costi di licenza.
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, ciò può portare a macchine con configurazioni uniche, diverse dalle altre istanze VM. A lungo termine, la configurazione manuale di un'istanza VM può diventare complicata e laboriosa. Pertanto, è consigliabile automatizzare il processo per renderlo ripetibile.
L'automazione dei deployment delle app su Compute Engine include le seguenti attività:
- Provisioning e preparazione delle istanze VM per il primo deployment dell'app.
- Eseguire il deployment di un'app.
- 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 differiscano 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 sul pull utilizzando un gruppo di istanze gestite
I gruppi di istanze gestite vengono utilizzati più comunemente per implementare la scalabilità automatica, ma forniscono anche un modo per gestire le implementazioni in sequenza. Dopo aver creato un template di istanza che fa riferimento alla nuova versione dell'app, puoi utilizzare la funzionalità di sostituzione controllata per sostituire le istanze VM che utilizzano il vecchio modello con istanze che utilizzano il nuovo modello.
Un prerequisito per questo approccio è che la nuova versione dell'app venga resa disponibile come modello di istanza. Puoi farlo in due modi:
Definisci un template di istanza che utilizzi una delle immagini del sistema operativo pubbliche. Utilizza uno script di avvio per configurare il sistema e installare l'app da un bucket Cloud Storage, un repository NuGet, un registro Docker o un'altra origine. Il seguente diagramma illustra questo approccio.
Crea un'immagine VM personalizzata nell'ambito del processo CI/CD, un processo spesso definito baking delle immagini. In questo approccio, utilizzi una delle immagini sistema operativo pubbliche per generare una nuova istanza VM, installi l'ultima app, crei un'immagine VM dall'istanza e rendi l'immagine disponibile nel progetto Google Cloud . L'intero processo può essere completamente automatizzato utilizzando uno strumento come Packer. È quindi possibile fare riferimento all'immagine risultante in un modello di istanza. Il seguente diagramma illustra questo approccio.
Uno svantaggio della creazione di un'immagine personalizzata (la seconda opzione) è che il baking dell'immagine è un processo relativamente lento, che spesso richiede diversi minuti. L'approccio non solo aggiunge complessità al processo CI/CD, ma lo rallenta. Il vantaggio è che l'avvio di nuove VM utilizzando un'immagine personalizzata è un processo semplice e veloce, il che è utile quando utilizzi la scalabilità automatica.
L'utilizzo degli script di avvio per il deployment dell'app (la prima opzione) presenta i compromessi opposti. 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 vengono scaricati i binari dell'app non sono a disponibilità elevata, questo approccio può comportare una disponibilità inferiore.
L'approccio più adatto alla tua app dipende dall'app stessa e dalla complessità della configurazione. In alcuni scenari, potrebbe essere meglio combinare entrambi gli approcci:
- Un'immagine personalizzata contiene tutte le configurazioni e le dipendenze, ma non i binari dell'app. Viene creata una nuova immagine quando cambia la configurazione o una delle dipendenze, ma non per ogni build dell'app. In questo modo si evita il rallentamento della pipeline CI/CD dell'app.
- L'app viene installata utilizzando uno script di avvio. Per ridurre al minimo il rischio e il rallentamento, questo processo deve essere il più semplice possibile.
In uno scenario in cui vuoi eseguire il deployment di molte app o servizi diversi che hanno una configurazione di base comune, questo approccio ibrido può evitare di dover creare e gestire 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 di container Docker sulle 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 pochi vantaggi rispetto all'utilizzo dell'ambiente flessibile di GKE o App Engine.
Se utilizzi i container Windows Server, segui queste linee guida per l'esecuzione dei container utilizzando Compute Engine e i gruppi di istanze gestite:
- Utilizza un'immagine creata su misura con Docker preinstallato o una delle
seguenti immagini pubbliche:
Windows Server 2019 Datacenter Core for ContainersWindows 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 i mapping delle porte appropriati per esporre i servizi in esecuzione all'interno del container.
Tieni presente che non è garantito che uno script di avvio venga eseguito solo dopo l'avvio del servizio Docker. Per gestire correttamente il caso in cui lo script viene eseguito prima che Docker sia disponibile, incorpora una logica di ripetizione 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 le istanze VM basate su Windows. Pertanto, in genere non è necessario utilizzare file unattend.xml personalizzati. Tuttavia, è comunque
importante che un'installazione di Windows venga generalizzata utilizzando GCESysprep prima
di creare un'immagine.
Deployment basato sul pull utilizzando Spinnaker
I gruppi di istanze gestite forniscono un modo semplice e affidabile 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 di base adottato da Spinnaker per orchestrare i deployment su Compute Engine è simile a quello descritto nella sezione precedente, ovvero si basa anche sulla creazione di immagini. Pertanto, si applicano le stesse considerazioni.
Poiché Spinnaker non è un servizio gestito, devi eseguirne il deployment e la manutenzione separatamente dall'app. Puoi eseguire il deployment di Spinnaker su istanze VM Linux separate o in un cluster GKE.
Deployment remoto basato sul push
Le opzioni di deployment basate sul pull descritte nelle sezioni precedenti offrono una serie di vantaggi. Tuttavia, non sono adatti a tutti i tipi 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 ciascuna attività.
Puoi eseguire il provisioning delle istanze VM del server delle app nello stesso modo di altre infrastrutture, utilizzando strumenti di automazione come Terraform. Puoi utilizzare script di avvio o di specializzazione per installare gli strumenti necessari per automatizzare il deployment dell'app. Ad esempio, se utilizzi Puppet, Chef o Octopus Deploy, devi assicurarti che sia installato il software agente per questi strumenti.
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 non viene utilizzata la scalabilità automatica, l'aggiunta di server delle app basati su Windows a un dominio Active Directory è un modo pratico per centralizzare la configurazione. L'utilizzo di Active Directory ti consente inoltre di controllare le attività di gestione come la manutenzione del sistema operativo.
Scegliere un'opzione di deployment
Come indicato all'inizio di questa pagina, non esiste un modo migliore per eseguire il deployment di un'app .NET su Google Cloud. Le opzioni di deployment migliori per te dipendono dall'app e dai tuoi requisiti. Per scegliere il modello giusto, una delle prime domande da porsi è se utilizzare .NET 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 i seguenti alberi decisionali per identificare un modello di deployment adatto.
Per il deployment delle app .NET su Linux:
Per il deployment di un'app .NET o .NET Framework su Windows:
Passaggi successivi
- Scopri come creare una pipeline CI/CD per un'app .NET con Azure Pipelines e GKE o come creare una pipeline CI/CD per un'app .NET Framework con Azure Pipelines e Compute Engine
- Scopri di più su .NET su Google Cloud
- Installa Tools for Visual Studio, che ti consentono di interagire con Google Cloud da Visual Studio
- Scopri di più sull'ambiente flessibile .NET di App Engine
- Esplora architetture, diagrammi e best practice di riferimento su Google Cloud. Consulta il nostro Cloud Architecture Center.