Resilienza della piattaforma Azure

La creazione di un'applicazione affidabile nel cloud è diversa dallo sviluppo di applicazioni locali tradizionali. Mentre in un tempo si acquistava hardware di fascia più alta per aumentare le prestazioni, in un ambiente cloud si scalava orizzontalmente. Invece di tentare di evitare errori, l'obiettivo è ridurre al minimo gli effetti e mantenere stabile il sistema.

Detto questo, le applicazioni cloud affidabili visualizzano caratteristiche distinte:

  • Sono resilienti, si riprendono normalmente dai problemi e continuano a funzionare.
  • Sono a disponibilità elevata ed eseguiti come progettato in uno stato integro senza tempi di inattività significativi.

Per creare un'applicazione affidabile nativa del cloud, è essenziale comprendere il funzionamento di queste caratteristiche e come influiscono sui costi. Verranno ora a esaminare i modi in cui è possibile creare resilienza e disponibilità nelle applicazioni native del cloud sfruttando le funzionalità del cloud di Azure.

Progettare con resilienza

Si è detto che la resilienza consente all'applicazione di reagire agli errori e di rimanere funzionante. Il white paper Resilienza in Azureoffre indicazioni per ottenere resilienza nella piattaforma Azure. Ecco alcune raccomandazioni chiave:

  • Errore hardware. Creare ridondanza nell'applicazione distribuendo i componenti in domini di errore diversi. Ad esempio, assicurarsi che le macchine virtuali di Azure siano posizionate in rack diversi usando set di disponibilità.

  • Errore del data center. Creare ridondanza nell'applicazione con zone di isolamento degli errori nei data center. Ad esempio, assicurarsi che le macchine virtuali di Azure siano posizionate in data center con isolamento errori diversi usando zone di disponibilità di Azure.

  • Errore a livello di regione. Replicare i dati e i componenti in un'altra area in modo che le applicazioni possano essere ripristinate rapidamente. Ad esempio, usare Azure Site Recovery per replicare le macchine virtuali di Azure in un'altra area di Azure.

  • Carico elevato. Bilanciare il carico tra le istanze per gestire i picchi di utilizzo. Ad esempio, inserire due o più macchine virtuali di Azure dietro un servizio di bilanciamento del carico per distribuire il traffico a tutte le macchine virtuali.

  • Eliminazione o danneggiamento accidentale dei dati. Eseguire il backup dei dati in modo che possano essere ripristinati in caso di eliminazione o danneggiamento. Ad esempio, usare Backup di Azure per eseguire periodicamente il backup delle macchine virtuali di Azure.

Progettare con ridondanza

Gli errori variano nell'ambito dell'impatto. Un errore hardware, ad esempio un disco guasto, può influire su un singolo nodo in un cluster. Un commutatore di rete non riuscito potrebbe influire su un intero rack del server. Gli errori meno comuni, ad esempio la perdita di energia, potrebbero interrompere un intero data center. Raramente, un'intera area diventa non disponibile.

La ridondanza è un modo per garantire la resilienza dell'applicazione. Il livello esatto di ridondanza necessario dipende dai requisiti aziendali e influisce sui costi e sulla complessità del sistema. Ad esempio, una distribuzione in più aree è più costosa e più complessa da gestire rispetto a una distribuzione in una singola area. Saranno necessarie procedure operative per gestire il failover e il failback. I costi aggiuntivi e la complessità potrebbero essere giustificati per alcuni scenari aziendali, ma non per altri.

Per architettare la ridondanza, è necessario identificare i percorsi critici nell'applicazione e quindi determinare se è presente ridondanza in ogni punto del percorso? Se un sottosistema deve avere esito negativo, l'applicazione avrà il failover su un altro elemento? Infine, è necessaria una conoscenza chiara delle funzionalità integrate nella piattaforma cloud di Azure che è possibile sfruttare per soddisfare i requisiti di ridondanza. Di seguito sono riportati i consigli per la progettazione della ridondanza:

  • Distribuire più istanze di servizi. Se l'applicazione dipende da una singola istanza di un servizio, crea un singolo punto di errore. Il provisioning di più istanze migliora sia la resilienza che la scalabilità. Quando si esegue l'hosting servizio Azure Kubernetes, è possibile configurare in modo dichiarativo le istanze ridondanti (set di repliche) nel file manifesto Kubernetes. Il valore del numero di repliche può essere gestito a livello di codice, nel portale o tramite funzionalità di scalabilità automatica.

  • Sfruttare un servizio di bilanciamento del carico. Il bilanciamento del carico distribuisce le richieste dell'applicazione a istanze del servizio integre e rimuove automaticamente le istanze non integre dalla rotazione. Quando si esegue la distribuzione in Kubernetes, è possibile specificare il bilanciamento del carico nel file manifesto kubernetes nella sezione Servizi.

  • Pianificare la distribuzione in più aree. Se si distribuisce l'applicazione in una singola area e tale area diventa non disponibile, anche l'applicazione non sarà più disponibile. Ciò potrebbe non essere accettabile in base ai termini dei contratti di servizio dell'applicazione. Valutare invece la possibilità di distribuire l'applicazione e i relativi servizi in più aree. Ad esempio, un cluster servizio Azure Kubernetes viene distribuito in una singola area. Per proteggere il sistema da un errore a livello di regione, è possibile distribuire l'applicazione in più cluster del servizio AzureKs tra aree diverse e usare la funzionalità Aree abbinate per coordinare gli aggiornamenti della piattaforma e assegnare priorità alle attività di ripristino.

  • Abilitare la replica geografica. La replica geografica per servizi come database SQL di Azure e Cosmos crea repliche secondarie dei dati in più aree. Sebbene entrambi i servizi esercitino automaticamente la replica dei dati all'interno della stessa area, la replica geografica protegge l'utente da un'interruzione dell'area consentendo di eseguire il failover in un'area secondaria. Un'altra procedura consigliata per la replica geografica è l'archiviazione delle immagini dei contenitori. Per distribuire un servizio nel servizio AKS, è necessario archiviare ed eseguire il pull dell'immagine da un repository. Registro Azure Container si integra con il servizio AKS e può archiviare in modo sicuro le immagini dei contenitori. Per migliorare le prestazioni e la disponibilità, è consigliabile eseguire la replica geografica delle immagini in un registro in ogni area in cui si dispone di un cluster del servizio Web Disaks. Ogni cluster del servizio Web Del servizio Container estrae quindi le immagini del contenitore dal registro contenitori locale nella relativa area, come illustrato nella figura 6-4:

Risorse replicate tra aree

Figura 6-4. Risorse replicate tra aree

  • Implementare un servizio di bilanciamento del carico del traffico DNS. Gestione traffico di Azure disponibilità elevata per le applicazioni critiche tramite il bilanciamento del carico a livello di DNS. Può indirizzare il traffico a aree diverse in base all'area geografica, al tempo di risposta del cluster e persino all'integrità dell'endpoint dell'applicazione. Ad esempio, Gestione traffico di Azure indirizzare i clienti al cluster del servizio Web del servizio Web e all'istanza dell'applicazione più vicini. Se si dispone di più cluster del servizio AKS in aree diverse, usare Gestione traffico per controllare il flusso del traffico verso le applicazioni eseguite in ogni cluster. La figura 6-5 illustra questo scenario.

AKS e Gestione traffico di Azure

Figura 6-5. AKS e Gestione traffico di Azure

Progettazione per la scalabilità

Il cloud si sviluppa in base al ridimensionamento. La possibilità di aumentare/ridurre le risorse di sistema per gestire il carico di sistema crescente/decrescente è un elemento chiave del cloud di Azure. Tuttavia, per ridimensionare in modo efficace un'applicazione, è necessaria una conoscenza delle funzionalità di ridimensionamento di ogni servizio di Azure incluso nell'applicazione. Di seguito sono riportati consigli per implementare in modo efficace il ridimensionamento nel sistema.

  • Progettare per il ridimensionamento. Un'applicazione deve essere progettata per il ridimensionamento. Per iniziare, i servizi devono essere senza stato in modo che le richieste possano essere indirizzate a qualsiasi istanza. La presenza di servizi senza stato significa anche che l'aggiunta o la rimozione di un'istanza non influisce negativamente sugli utenti correnti.

  • Partizionare i carichi di lavoro. La scomposizione dei domini in microservizi indipendenti consente a ogni servizio di ridimensionarsi indipendentemente dagli altri. In genere, i servizi hanno esigenze e requisiti di scalabilità diversi. Il partizionamento consente di ridimensionare solo ciò che deve essere ridimensionato senza il costo superfluo del ridimensionamento di un'intera applicazione.

  • Favorire la scalabilità orizzontale. Le applicazioni basate sul cloud favoriscono la scalabilità orizzontale delle risorse anziché l'aumento delle dimensioni. La scalabilità orizzontale implica l'aggiunta di più risorse del servizio a un sistema esistente per soddisfare e condividere un livello di prestazioni desiderato. La scalabilità verticale comporta la sostituzione delle risorse esistenti con hardware più potente (più dischi, memoria ed core di elaborazione). La scalabilità orizzontale può essere richiamata automaticamente con le funzionalità di scalabilità automatica disponibili in alcune risorse cloud di Azure. La scalabilità orizzontale tra più risorse aggiunge anche ridondanza al sistema complessivo. Infine, la scalabilità verticale di una singola risorsa è in genere più costosa rispetto alla scalabilità orizzontale tra molte risorse più piccole. La figura 6-6 illustra i due approcci seguenti:

Scalabilità verticale e scalabilità orizzontale

Figura 6-6. Scalabilità verticale e scalabilità orizzontale

  • Ridimensionare in modo proporzionale. Quando si ridimensiona un servizio, si pensi ai set di risorse. Se si aumenta in modo significativo un servizio specifico, quale impatto avrebbe sugli archivi dati back-end, sulle cache e sui servizi dipendenti? Alcune risorse, ad esempio Cosmos database, possono aumentare in modo proporzionale, mentre molte altre no. Si vuole assicurarsi di non aumentare le dimensioni di una risorsa fino a un punto in cui esaurirà le altre risorse associate.

  • Evitare l'affinità. È consigliabile assicurarsi che un nodo non richieda l'affinità locale, spesso definita sessione sticky. Una richiesta deve essere in grado di eseguire il routing a qualsiasi istanza. Se è necessario rendere persistente lo stato, deve essere salvato in una cache distribuita, ad esempio Cache Redis di Azure.

  • Sfruttare le funzionalità di scalabilità automatica della piattaforma. Usare le funzionalità di scalabilità automatica incorporate quando possibile, anziché meccanismi personalizzati o di terze parti. Laddove possibile, usare regole di scalabilità pianificate per garantire che le risorse siano disponibili senza un ritardo di avvio, ma aggiungere la scalabilità automatica reattiva alle regole in base alle esigenze, per far fronte a modifiche impreviste della domanda. Per altre informazioni, vedere Linee guida per la scalabilità automatica.

  • Aumentare le dimensioni in modo aggressivo. Una pratica finale consiste nell'aumentare le dimensioni in modo aggressivo in modo da poter soddisfare rapidamente picchi immediati di traffico senza perdere le attività aziendali. E quindi aumentare il numero di istanze (ovvero rimuovere le istanze non necessario) in modo conservativo per mantenere stabile il sistema. Un modo semplice per implementarlo è impostare il periodo di raffreddamento, ovvero il tempo di attesa tra le operazioni di ridimensionamento, su cinque minuti per l'aggiunta di risorse e fino a 15 minuti per la rimozione di istanze.

Ripetizione dei tentativi predefiniti nei servizi

È consigliabile implementare operazioni di ripetizione dei tentativi a livello di codice in una sezione precedente. Tenere presente che molti servizi di Azure e gli SDK client corrispondenti includono anche meccanismi di ripetizione dei tentativi. L'elenco seguente riepiloga le funzionalità di ripetizione dei tentativi nei numerosi servizi di Azure descritti in questo libro:

  • Database Cosmos Azure. La DocumentClient classe dall'API client ritira automaticamente i tentativi non riusciti. Il numero di tentativi e il tempo di attesa massimo sono configurabili. Le eccezioni generate dall'API client sono richieste che superano i criteri di ripetizione o errori non temporanei.

  • Cache Redis di Azure. Il client Redis StackExchange usa una classe di gestione connessione che include i tentativi nei tentativi non riusciti. Il numero di tentativi, i criteri di ripetizione e il tempo di attesa specifici sono tutti configurabili.

  • Azure bus di servizio. Il client bus di servizio espone una classe RetryPolicy che può essere configurata con un intervallo di back-off, un numero di tentativi e , che specifica il tempo massimo che un'operazione TerminationTimeBuffer può richiedere. Il criterio predefinito è nove tentativi massimi con un periodo di backoff di 30 secondi tra i tentativi.

  • Database SQL di Azure Il supporto per i tentativi viene fornito quando si usa Entity Framework Core libreria.

  • Archiviazione di Azure. La libreria client di archiviazione supporta le operazioni di ripetizione dei tentativi. Le strategie variano in base a tabelle, BLOB e code di archiviazione di Azure. Quando la funzionalità di ridondanza geografica è abilitata, anche i tentativi alternativi passano da una posizione di servizi di archiviazione primaria a una secondaria.

  • Hub eventi di Azure. La libreria client dell'hub eventi include una proprietà RetryPolicy, che include una funzionalità di backoff esponenziale configurabile.