Approcci architetturali per il calcolo in soluzioni multi-tenant

La maggior parte delle soluzioni basate sul cloud è costituita da risorse di calcolo di qualche tipo, ad esempio livelli Web e applicazione, processori batch, processi pianificati e anche risorse specializzate come GPU e HPC (High Performance Compute). Le soluzioni multi-tenant spesso traggono vantaggio dalle risorse di calcolo condivise, perché una maggiore densità di tenant per l'infrastruttura riduce i costi operativi e la gestione. È consigliabile considerare i requisiti di isolamento e le implicazioni dell'infrastruttura condivisa.

Questo articolo fornisce indicazioni sulle considerazioni e i requisiti essenziali per gli architetti delle soluzioni da considerare quando si pianifica un livello di calcolo multi-tenant. Sono inclusi alcuni modelli comuni per l'applicazione di multi-tenancy ai servizi di calcolo, insieme ad alcuni antipattern da evitare.

Considerazioni e requisiti principali

Multi-tenancy e il modello di isolamento selezionato influisce sul ridimensionamento, sulle prestazioni, sulla gestione dello stato e sulla sicurezza delle risorse di calcolo. In questa sezione vengono esaminate alcune delle decisioni chiave da prendere quando si pianifica una soluzione di calcolo multi-tenant.

Ridimensiona

I sistemi devono eseguire in modo adeguato la domanda in fase di modifica. Man mano che il numero di tenant e la quantità di traffico aumentano, potrebbe essere necessario aumentare la capacità delle risorse, per mantenere il numero crescente di tenant e mantenere un tasso di prestazioni accettabile. Analogamente, quando il numero di utenti attivi o la quantità di traffico diminuisce, è consigliabile ridurre automaticamente la capacità di calcolo per ridurre i costi, ma è necessario ridurre la capacità con un impatto minimo sugli utenti.

Se si distribuiscono risorse dedicate per ogni tenant, è possibile ridimensionare le risorse di ogni tenant in modo indipendente. In una soluzione in cui le risorse di calcolo vengono condivise tra più tenant, se si ridimensionano tali risorse, tutti questi tenant possono usare la nuova scalabilità. Tuttavia, subiranno tutti i problemi quando la scalabilità non è sufficiente per gestire il carico complessivo. Per altre informazioni, vedere il problema di Noisy Neighbor.

Quando si creano soluzioni cloud, è possibile scegliere se ridimensionare orizzontalmente o verticalmente. In una soluzione multi-tenant con un numero crescente di tenant, la scalabilità orizzontale offre in genere maggiore flessibilità e un limite di scalabilità generale superiore.

I problemi di prestazioni vengono spesso rilevati solo nel momento in cui un'applicazione si trova in condizioni di carico. È possibile usare un servizio completamente gestito, ad esempio Test di carico di Azure, per informazioni sul comportamento dell'applicazione sotto stress.

Trigger di scalabilità

Indipendentemente dall'approccio usato per la scalabilità, in genere è necessario pianificare i trigger che causano la scalabilità dei componenti. Quando si dispone di componenti condivisi, prendere in considerazione i modelli di carico di lavoro di ogni tenant che usa le risorse, per garantire che la capacità di cui è stato effettuato il provisioning possa soddisfare la capacità totale richiesta e ridurre al minimo la probabilità che un tenant abbia riscontrato il problema Di tipo Noisy Neighbor. È anche possibile pianificare la capacità di ridimensionamento considerando il numero di tenant. Ad esempio, se si misurano le risorse usate per gestire 100 tenant, quando si esegue l'onboarding di più tenant, è possibile pianificare la scalabilità in modo che le risorse raddoppiino per ogni tenant aggiuntivo di 100.

Provincia

Le risorse di calcolo possono essere senza stato oppure con stato. I componenti senza stato non mantengono dati tra le richieste. Dal punto di vista della scalabilità, i componenti senza stato sono spesso facili da aumentare perché è possibile aggiungere rapidamente nuovi ruoli di lavoro, istanze o nodi e possono iniziare immediatamente a elaborare le richieste. Se l'architettura lo consente, è anche possibile riutilizzare le istanze assegnate a un tenant e allocarle a un altro tenant.

Le risorse con stato possono essere ulteriormente suddivise in base al tipo di stato gestito. Lo stato persistente è costituito da dati che devono essere archiviati in modo permanente. Nelle soluzioni cloud è consigliabile evitare di archiviare uno stato persistente nel livello di calcolo. Usare invece servizi di archiviazione come database o account di archiviazione. Lo stato temporaneo è costituito dai dati archiviati temporaneamente e include cache in memoria di sola lettura e l'archiviazione di file temporanei nei dischi locali.

Lo stato temporaneo è spesso utile per migliorare le prestazioni del livello applicazione, riducendo il numero di richieste ai servizi di archiviazione back-end. Ad esempio, quando si usa una cache in memoria, potrebbe essere possibile gestire le richieste di lettura, senza connettersi a un database e senza eseguire una query intensa eseguita di recente quando è stata servita un'altra richiesta.

Nelle applicazioni sensibili alla latenza, il costo dell'idratazione della cache può diventare significativo. Una soluzione multi-tenant può esacerbare questo problema, se ogni tenant richiede dati diversi da memorizzare nella cache. Per attenuare questo problema, alcune soluzioni usano l'affinità di sessione per assicurarsi che tutte le richieste per un utente o un tenant specifico vengano elaborate dallo stesso nodo del ruolo di lavoro di calcolo. Anche se l'affinità di sessione può migliorare la capacità del livello applicazione di usare la cache in modo efficace, rende anche più difficile ridimensionare e bilanciare il carico del traffico tra i ruoli di lavoro. Questo compromesso deve essere considerato attentamente. Per molte applicazioni, l'affinità di sessione non è necessaria.

È anche possibile archiviare i dati in cache esterne, ad esempio cache di Azure per Redis. Le cache esterne sono ottimizzate per il recupero dei dati a bassa latenza, mantenendo lo stato isolato dalle risorse di calcolo, in modo che possano essere ridimensionate e gestite separatamente. In molte soluzioni, le cache esterne consentono di migliorare le prestazioni dell'applicazione, mantenendo il livello di calcolo senza stato.

Importante

Evitare la perdita di dati tra tenant, ogni volta che si usano cache in memoria o altri componenti che mantengono lo stato. Si consideri ad esempio la pre-attesa di un identificatore del tenant per tutte le chiavi della cache, per assicurarsi che i dati siano separati per ogni tenant.

Isolamento

Quando si progetta un livello di calcolo multi-tenant, spesso sono disponibili molte opzioni da considerare per il livello di isolamento tra i tenant, tra cui la distribuzione di risorse di calcolo condivise, da usare da tutti i tenant, dalle risorse di calcolo dedicate per ogni tenant o da un elemento tra questi estremi. Ogni opzione è dotata di compromessi. Per decidere l'opzione più adatta alla soluzione, prendere in considerazione i requisiti per l'isolamento.

È possibile preoccuparsi dell'isolamento logico dei tenant e di come separare le responsabilità o i criteri di gestione applicati a ogni tenant. In alternativa, potrebbe essere necessario distribuire configurazioni di risorse distinte per tenant specifici, ad esempio la distribuzione di uno SKU di macchina virtuale specifico in base al carico di lavoro di un tenant.

Indipendentemente dal modello di isolamento selezionato, verificare che i dati del tenant rimangano isolati in modo appropriato anche quando i componenti non sono disponibili o non funzionano correttamente. Prendere in considerazione l'uso di Azure Chaos Studio come parte del normale processo di test automatizzato per introdurre intenzionalmente errori che simulano interruzioni del mondo reale e verificare che la soluzione non perda i dati tra i tenant e funzioni correttamente anche sotto pressione.

Approcci e modelli da prendere in considerazione

Autoscale

I servizi di calcolo di Azure offrono funzionalità diverse per ridimensionare i carichi di lavoro. Molti servizi di calcolo supportano la scalabilità automatica, che richiede di prendere in considerazione quando è necessario ridimensionare e i livelli minimi e massimi di scalabilità. Le opzioni specifiche disponibili per il ridimensionamento dipendono dai servizi di calcolo usati. Vedere i servizi di esempio seguenti:

  • app Azure Servizio: specificare le regole di scalabilità automatica che ridimensionano l'infrastruttura in base alle esigenze.
  • Funzioni di Azure: selezionare tra più opzioni di scalabilità, tra cui un modello di ridimensionamento basato su eventi che viene ridimensionato automaticamente, in base al lavoro eseguito dalle funzioni.
  • App Azure Container: usare la scalabilità automatica basata su eventi per ridimensionare l'applicazione, in base al lavoro eseguito e al carico corrente.
  • servizio Azure Kubernetes (servizio Azure Kubernetes): per tenere il passo con le esigenze dell'applicazione, potrebbe essere necessario modificare il numero di nodi che eseguono i carichi di lavoro. Inoltre, per ridimensionare rapidamente i carichi di lavoro delle applicazioni in un cluster del servizio Azure Kubernetes, è possibile usare nodi virtuali.
  • Macchine virtuali: un set di scalabilità di macchine virtuali può aumentare o diminuire automaticamente il numero di istanze di macchine virtuali che eseguono l'applicazione.

Modello degli stamp di distribuzione

Per altre informazioni sul modo in cui è possibile usare il modello Deployment Stamps per supportare una soluzione multi-tenant, vedere Panoramica.

Modello di consolidamento delle risorse di calcolo

Il modello di consolidamento delle risorse di calcolo consente di ottenere una maggiore densità di tenant per l'infrastruttura di calcolo, condividendo le risorse di calcolo sottostanti. Condividendo le risorse di calcolo, spesso è possibile ridurre il costo diretto di tali risorse. Inoltre, i costi di gestione sono spesso inferiori perché sono presenti meno componenti da gestire.

Tuttavia, il consolidamento delle risorse di calcolo aumenta la probabilità del problema Noisy Neighbor. Il carico di lavoro di qualsiasi tenant potrebbe usare una quantità sproporzionata della capacità di calcolo disponibile. Spesso è possibile attenuare questo rischio assicurandosi di ridimensionare la soluzione in modo appropriato e applicando controlli come quote e limiti api, per evitare tenant che utilizzano più della loro equa quota di capacità.

Questo modello viene ottenuto in modi diversi, a seconda del servizio di calcolo usato. Vedere i servizi di esempio seguenti:

  • app Azure Servizio e Funzioni di Azure: distribuire piani di servizio app condivisi, che rappresentano l'infrastruttura del server di hosting.
  • App contenitore di Azure: distribuire ambienti condivisi.
  • servizio Azure Kubernetes (servizio Azure Kubernetes): distribuire pod condivisi con un'applicazione compatibile con più tenancy.
  • Macchine virtuali: distribuire un singolo set di macchine virtuali per tutti i tenant da usare.

Risorse di calcolo dedicate per tenant

È anche possibile distribuire risorse di calcolo dedicate per ogni tenant. Le risorse dedicate attenuano il rischio del problema Noisy Neighbor, assicurandosi che le risorse di calcolo per ogni tenant siano isolate dalle altre. Consente anche di distribuire una configurazione distinta per le risorse di ogni tenant, in base ai requisiti. Tuttavia, le risorse dedicate in genere includono un costo più elevato, perché si ha una densità inferiore di tenant per le risorse.

A seconda dei servizi di calcolo di Azure usati, è necessario distribuire risorse dedicate diverse, come indicato di seguito:

  • app Azure Servizio e Funzioni di Azure: distribuire piani di servizio app separati per ogni tenant.
  • App Azure Container: distribuire ambienti separati per ogni tenant.
  • servizio Azure Kubernetes (servizio Azure Kubernetes): distribuire cluster dedicati per ogni tenant.
  • Macchine virtuali: distribuire macchine virtuali dedicate per ogni tenant.

Risorse di calcolo semi isolate

Gli approcci semi-isolati richiedono la distribuzione di aspetti della soluzione in una configurazione isolata, mentre si condividono gli altri componenti.

Quando si lavora con servizio app e Funzioni di Azure, è possibile distribuire applicazioni distinte per ogni tenant ed è possibile ospitare le applicazioni in piani di servizio app condivisi. Questo approccio riduce il costo del livello di calcolo, perché i piani servizio app rappresentano l'unità di fatturazione. Consente anche di applicare configurazioni e criteri distinti a ogni applicazione. Tuttavia, questo approccio introduce il rischio del problema Noisy Neighbor.

App Azure Container consente di distribuire più applicazioni in un ambiente condiviso e quindi di usare Dapr e altri strumenti per configurare ogni applicazione separatamente.

servizio Azure Kubernetes (servizio Azure Kubernetes) e Kubernetes offrono un'ampia gamma di opzioni per la multi-tenancy, tra cui:

  • Spazi dei nomi specifici del tenant, per l'isolamento logico delle risorse specifiche del tenant, distribuite in cluster condivisi e pool di nodi.
  • Nodi o pool di nodi specifici del tenant in un cluster condiviso.
  • Pod specifici del tenant che potrebbero usare lo stesso pool di nodi.

Il servizio Azure Kubernetes consente anche di applicare la governance a livello di pod per attenuare il problema di Noisy Neighbor. Per altre informazioni, vedere Procedure consigliate per gli sviluppatori di applicazioni per gestire le risorse in servizio Azure Kubernetes (servizio Azure Kubernetes).

È anche importante essere consapevoli dei componenti condivisi in un cluster Kubernetes e del modo in cui questi componenti potrebbero essere interessati dalla multi-tenancy. Ad esempio, il server API Kubernetes è un servizio condiviso usato in tutto il cluster. Anche se si forniscono pool di nodi specifici del tenant per isolare i carichi di lavoro dell'applicazione dei tenant, il server API potrebbe riscontrare conflitti da un numero elevato di richieste tra i tenant.

Antipattern da evitare

Antipattern noisy neighbor

Ogni volta che si distribuiscono componenti condivisi tra tenant, il problema Noisy Neighbor è un rischio potenziale. Assicurarsi di includere la governance delle risorse e il monitoraggio per ridurre il rischio che il carico di lavoro di calcolo di un tenant sia interessato dall'attività di altri tenant.

Perdita di dati tra tenant

I livelli di calcolo possono essere soggetti a perdite di dati tra tenant, se non vengono gestiti correttamente. Questo non è in genere un aspetto da considerare quando si usa un servizio multi-tenant in Azure, perché Microsoft fornisce protezioni a livello di piattaforma. Tuttavia, quando si sviluppa una propria applicazione multi-tenant, valutare se qualsiasi risorsa condivisa (ad esempio cache del disco locale, RAM e cache esterne) potrebbe contenere dati che un altro tenant può visualizzare o modificare inavvertitamente.

Antipattern Front End occupato

Per evitare l'antipattern Front End occupato, evitare il livello front-end eseguendo molte operazioni che potrebbero essere gestite da altri componenti o livelli dell'architettura. Questo antipattern è particolarmente importante quando si creano front-end condivisi per una soluzione multi-tenant, perché un front-end occupato riduce l'esperienza per tutti i tenant.

Prendere invece in considerazione l'uso dell'elaborazione asincrona usando code o altri servizi di messaggistica. Questo approccio consente anche di applicare controlli QoS (Quality of Service) per tenant diversi, in base ai requisiti. Ad esempio, tutti i tenant possono condividere un livello front-end comune, ma i tenant che pagano per un livello di servizio superiore potrebbero avere un set più elevato di risorse dedicate per elaborare il lavoro dai messaggi della coda.

Scalabilità inelastica o insufficiente

Le soluzioni multi-tenant sono spesso soggette a modelli di scalabilità bursty. I componenti condivisi sono particolarmente soggetti a questo problema, perché l'ambito per il burst è più elevato e l'impatto è maggiore quando si hanno più tenant con modelli di utilizzo distinti.

Assicurarsi di sfruttare al meglio l'elasticità e la scalabilità del cloud. Valutare se è consigliabile usare il ridimensionamento orizzontale o verticale e usare la scalabilità automatica per gestire automaticamente i picchi di carico. Testare la soluzione per comprendere il comportamento con livelli di carico diversi. Assicurarsi di includere i volumi di carico previsti nell'ambiente di produzione e la crescita prevista. È possibile usare un servizio completamente gestito, ad esempio Test di carico di Azure, per informazioni sul comportamento dell'applicazione sotto stress.

Antipattern Nessuna memorizzazione nella cache

L'antipattern Nessuna memorizzazione nella cache è quando le prestazioni della soluzione risentono perché il livello applicazione richiede ripetutamente o ricompila le informazioni che potrebbero essere riutilizzate tra le richieste. Se si dispone di dati che possono essere condivisi, tra tenant o tra utenti all'interno di un singolo tenant, è probabile che valga la pena memorizzarli nella cache per ridurre il carico nel livello back-end/database.

Non necessario con stato

L'antipattern Nessuna memorizzazione nella cache è che è anche consigliabile evitare di archiviare lo stato non necessario nel livello di calcolo. Essere espliciti sulla posizione in cui si mantiene lo stato e sul motivo. I livelli front-end o applicazione con stato possono ridurre la capacità di ridimensionare. I livelli di calcolo con stato richiedono in genere anche l'affinità di sessione, che consente di ridurre in modo efficace il carico del traffico, tra i ruoli di lavoro o i nodi.

Prendere in considerazione i compromessi per ogni elemento di stato gestito nel livello di calcolo e se influisce sulla capacità di ridimensionare o aumentare man mano che cambiano i modelli di carico di lavoro dei tenant. È anche possibile archiviare lo stato in una cache esterna, ad esempio cache di Azure per Redis.

Collaboratori

Questo articolo viene gestito da Microsoft. Originariamente è stato scritto dai seguenti contributori.

Autori principali:

  • Dixit Arora | Senior Customer Engineer, FastTrack per Azure
  • John Downs | Principal Software Engineer

Altri contributori:

Passaggi successivi

Esaminare le linee guida specifiche del servizio per i servizi di calcolo: