
Nota del traduttore.: l'autore di questo articolo (Luc Perkins) è un developer advocate presso l'organizzazione CNCF, che ospita progetti Open Source come Linkerd, SMI (Service Mesh Interface) e Kuma (a proposito, vi siete mai chiesti perché in questo elenco non ci sia Istio?). Ancora una volta, cercando di portare nella comunità DevOps una migliore comprensione di quello che è il trend del service mesh, presenta 16 caratteristiche distintive che queste soluzioni offrono.
Oggi ― uno dei temi più caldi nel campo dell'ingegneria del software (e a buon diritto!). Credo che questa tecnologia abbia un potenziale incredibile e sogno di assistere alla sua ampia diffusione (ovviamente, quando ha senso farlo). Tuttavia, è ancora circondata da un'aura di mistero per la maggior parte delle persone. Anche coloro che sono ben familiari con essa spesso faticano a formulare i suoi vantaggi e cosa rappresenti realmente (incluso il vostro umile servitore). In questo articolo cercherò di correggere la situazione elencando vari cenari d'uso delle "service mesh"*.
* Nota: qui e in seguito nell'articolo verrà utilizzata questa traduzione (« rete di servizi ») per il termine ancora nuovo service mesh.
Ma prima voglio fare alcune osservazioni:
- Non ho mai lavorato con le reti di servizi né le ho utilizzate al di fuori di progetti intrapresi per la mia formazione personale. D'altro canto, ho scritto una quantità di documentazione per la rete di servizi interna dell'azienda Twitter nel 2015 (all'epoca non si chiamava nemmeno « rete di servizi ») e ho partecipato allo sviluppo del sito e della documentazione per , quindi questo significa qualcosa.
- La mia lista è indicativa e incompleta. È del tutto possibile che esistano scenari di utilizzo a me sconosciuti, e nel tempo sicuramente emergeranno nuove opzioni man mano che la tecnologia si sviluppa e cresce in popolarità.
- Allo stesso tempo, non tutte le implementazioni esistenti di service mesh supportano tutti i casi d'uso elencati. Pertanto, le mie affermazioni come « service mesh può... » devono essere interpretate come « singole, e forse tutte le implementazioni popolari di service mesh possono... ».
- L'ordine degli esempi non ha alcuna importanza.
Elenco breve:
- scoperta dei servizi;
- crittografia;
- autenticazione e autorizzazione;
- bilanciamento del carico;
- circuit breaking;
- autoscaling;
- deployments canary;
- deployments blu-verdi;
- controllo della salute;
- load shedding;
- mirroraggio del traffico;
- isolamento;
- limitazione della frequenza delle richieste, tentativi ripetuti e timeout;
- telemetria;
- audit;
- visualizzazione.
1. Rilevamento dei servizi
TL;DR: Connettiti ad altri servizi nella rete usando nomi semplici.
I servizi devono essere in grado di "trovare" automaticamente gli uni con gli altri tramite nomi adeguati, ad esempio, service.api.production, pets/staging o cassandra. Gli ambienti cloud si distinguono per la loro elasticità, e dietro un solo nome possono nascondersi molteplici istanze di servizio. È chiaro che, in una tale situazione, è fisicamente impossibile codificare a mano tutti gli indirizzi IP.
Inoltre, quando un servizio trova un altro, deve essere in grado di inviare richieste a quel servizio senza temere che queste arrivino a un'istanza non funzionante. In altre parole, la service mesh deve monitorare la disponibilità di tutte le istanze dei servizi e mantenere l'elenco degli host il più aggiornato possibile.
Ogni service mesh implementa meccanismi di scoperta dei servizi a modo suo. Al momento, il metodo più comune è delegare a processi esterni come DNS Kubernetes. In passato, in Twitter, utilizzavamo un sistema di nomi per questi scopi. . Inoltre, la tecnologia del service mesh consente l'emergere di meccanismi di denominazione personalizzati (anche se non ho ancora incontrato alcuna implementazione di SM con tale funzionalità).
2. Crittografia
TL;DR: Elimina il traffico non crittografato tra i servizi e fai sì che questo processo sia automatizzato e scalabile.
È rassicurante sapere che i malintenzionati non possono accedere alla tua rete interna. I firewall fanno un ottimo lavoro in questo. Ma cosa succede se un hacker riesce comunque a entrare? Potrà fare ciò che vuole con il traffico intra-servizio? Speriamo che ciò non accada. Per prevenire tale scenario, è necessario implementare una rete a zero fiducia (zero-trust), in cui tutto il traffico tra i servizi è crittografato. La maggior parte delle moderne service mesh ottiene questo tramite autenticazione reciproca. (mutual TLS, mTLS). In alcuni casi, mTLS funziona in interi cloud e cluster (penso che in futuro anche le comunicazioni interplanetarie saranno organizzate in modo simile).
Certo, per il servizio mTLS non è obbligatorio. Ogni servizio può gestire autonomamente il proprio TLS, ma ciò implica trovare un modo per generare certificati, distribuiti tra gli host del servizio, e includere nel codice dell'applicazione il codice che carica questi certificati dai file. E, naturalmente, non dimenticate di aggiornare questi certificati a intervalli regolari. Le service mesh automatizzano mTLS attraverso sistemi come , che a loro volta automatizzano il processo di emissione e rotazione dei certificati.
3. Autenticazione e autorizzazione
TL;DR: Stabilite chi è l'iniziatore della richiesta e determinate cosa gli è permesso fare prima che la richiesta raggiunga il servizio.
I servizi spesso desiderano sapere, chi esegue la richiesta (autenticazione), e, usando questa informazione, decidono cosa cosa è autorizzato a fare questo soggetto (autorizzazione). In questo caso, il pronome «chi» può nascondere:
- Altri servizi. Questo si chiama «autenticazione peer’.». Ad esempio, il servizio
webvuole accedere al serviziodb. Le reti di servizio risolvono generalmente problemi come questo tramite mTLS: i certificati in questo caso fungono da identificatori necessari. - Alcuni utenti umani. Questo è chiamato «autenticazione della richiesta». Ad esempio, l'utente
haxor69vuole acquistare una nuova lampada. Le reti di servizio forniscono vari meccanismi, ad esempio, .Molti di noi l'hanno già fatto nel codice dell'applicazione. Arriva una richiesta, controlliamo la tabella
users, troviamo l'utente e confrontiamo la password, poi controlliamo la colonnaautorizzazionie così via. Nel caso della rete di servizio, ciò avviene ancora prima che la richiesta raggiunga il servizio.
Dopo aver stabilito da chi proviene la richiesta, è necessario determinare cosa è consentito fare a questo soggetto. Alcuni sistemi di rete di servizio consentono di definire politiche di base (su chi può fare cosa) sotto forma di file YAML o nella riga di comando, mentre altri offrono integrazioni con framework come . L'obiettivo finale è fare in modo che i tuoi servizi accettino qualsiasi richiesta, presupponendo con sicurezza che provenga da una fonte affidabile. e questa azione è consentita.
4. Bilanciamento del carico
TL;DR: Distribuisci il carico tra le istanze del servizio secondo un modello prestabilito.
Il "servizio" in un settore dei servizi è molto spesso composto da molte istanze identiche. Ad esempio, oggi il servizio cache è composto da 5 repliche, ma domani il numero potrebbe aumentare a 11. Le richieste dirette a cache, devono essere distribuite secondo un obiettivo preciso. Ad esempio, minimizzare la latenza o massimizzare la probabilità di raggiungere un'istanza funzionante. Spesso viene utilizzato l'algoritmo del round-robin, ma ci sono anche molti altri — come il metodo dei request pesati (weighted) (è possibile scegliere obiettivi preferenziali), l'hashing a anello (ring) (uso di un hashing coerente per gli host upstream) o il metodo del minor numero di richieste (si preferisce l'istanza con il minor numero di richieste). richieste (puoi scegliere obiettivi preferiti), anello (anello) hashing (uso di hashing coerente per gli host upstream) o metodo delle richieste minime (si preferisce l'istanza con il numero minore di richieste).
I bilanciatori classici offrono anche altre funzionalità come la cache HTTP e la protezione DDoS, ma non sono molto rilevanti per il traffico di tipo east-west (cioè per il traffico all'interno del data center - nota del traduttore) (area di applicazione tipica del service mesh). Certo, non è strettamente necessario utilizzare un service mesh per il bilanciamento del carico, tuttavia consente di definire e controllare le politiche di bilanciamento per ciascun servizio da un layer di gestione centralizzato, eliminando così la necessità di eseguire e configurare bilanciatori separati nello stack di rete.
5. Interruzione del circuito (circuit breaking)
TL;DR: Ferma il traffico verso il servizio problematico e controlla i danni in scenari negativi.
Se per qualche motivo il servizio non riesce a gestire il traffico, il service mesh offre diverse opzioni per affrontare questo problema (di altre si parlerà nelle sezioni corrispondenti). L'interruzione del circuito è l'opzione più severa per disconnettere il servizio dal traffico. Tuttavia, di per sé non ha senso: è necessario avere un piano di emergenza. Può essere previsto un contro-pressione. () per i servizi che elaborano le richieste (non dimenticare di configurare la tua service mesh per questo!), oppure, ad esempio, colorare la pagina di stato di rosso e reindirizzare gli utenti su una versione diversa della pagina con il "grande balena che affonda" ("Twitter is down").
Le service mesh non solo consentono di determinare quando si verificherà un'interruzione e cosa cosa seguirà. In questo caso, "quando" può includere qualsiasi combinazione di parametri stabiliti: numero totale di richieste in un certo periodo, numero di connessioni parallele, richieste in attesa, tentativi attivi, ecc.
È probabile che tu non voglia abusare del circuit breaking, ma è confortante sapere che c'è un piano di riserva in caso di emergenza.
6. Autoscalabilità
TL;DR: Aumenta o diminuisci il numero di istanze del servizio in base ai criteri stabiliti.
Le service mesh non sono pianificatori, quindi non effettuano scalabilità autonoma. Tuttavia, possono fornire informazioni su cui i pianificatori prenderanno decisioni. Poiché i service mesh hanno accesso a tutto il traffico tra i servizi, dispongono di informazioni dettagliate su ciò che accade: quali servizi stanno avendo problemi, quali sono gravemente sottoutilizzati (le risorse allocate a loro vengono sprecate), ecc.
Ad esempio, Kubernetes dimensiona i servizi in base all'utilizzo della CPU e della memoria da parte dei pod. (vedi la nostra rapportazione «» — nota del traduttore.), ma se decidi di eseguire la scalabilità sulla base di un altro indicatore (nel nostro caso legato al traffico), sarà necessaria una metrica specifica. La guida mostra come farlo usando , e , ma il processo stesso è piuttosto complesso. Ci piacerebbe che il service mesh lo rendesse più semplice, permettendo di impostare condizioni come «aumenta il numero di istanze del servizio auth, se il numero di richieste in attesa supera una soglia per un minuto».
7. Deployments a canarini
TL;DR: Prova nuove funzionalità o versioni del servizio su un sottoinsieme di utenti.
Immagina di sviluppare un prodotto SaaS e di voler rilasciare una nuova versione eccezionale. L'hai testata in staging, e ha funzionato perfettamente. Tuttavia, ci sono ancora preoccupazioni su come si comporterà in condizioni reali. In altre parole, è necessario testare la nuova versione con compiti reali, senza compromettere la fiducia degli utenti. I deployment canary sono perfetti per questo. Permettono di mostrare una nuova funzionalità a un sottoinsieme di utenti. Questo sottoinsieme può consistere nei tuoi utenti più fedeli o in quelli che utilizzano la versione gratuita del prodotto, o in utenti che si sono dichiarati disponibili a essere 'cavie'.
I servizi mesh realizzano questo, permettendo di specificare criteri che definiscono chi e quale versione dell'applicazione vedrà, e instradando il traffico di conseguenza. Per i servizi stessi, nulla cambia. La versione 1.0 del servizio presume che tutte le richieste provengano da utenti che devono vederla, mentre la versione 1.1 considera lo stesso per i propri utenti. Nel frattempo, puoi cambiare la percentuale di traffico tra la vecchia e la nuova versione, reindirizzando un numero crescente di utenti verso la nuova, se funziona stabilmente e i tuoi "cavie" danno il via libera.
8. Deploy blu-verdi
TL;DR: Lancia una nuova fantastica funzionalità, ma preparati a tornare indietro immediatamente.
Significato è quello di lanciare un nuovo servizio "blu", eseguendolo in parallelo con il vecchio, "verde". Se tutto va bene e il nuovo servizio si comporta bene, il vecchio può essere disattivato gradualmente. (Purtroppo, un giorno anche questo nuovo servizio "blu" subirà la stessa sorte del "verde" e scomparirà...) I deploy blu-verdi si differenziano dai canary poiché la nuova funzionalità copre subito tutti gli utenti (e non solo una parte); il senso qui è quello di avere una "riserva" pronta, nel caso qualcosa vada storto.
I service mesh offrono un modo molto utile per testare il servizio "blu" e passare immediatamente a quello "verde" in caso di problemi. Senza contare che, nel contempo, forniscono molte informazioni (vedi il punto "Telemetria" qui sotto) sul funzionamento del "blu", che aiuta a capire se è pronto per un utilizzo completo.
Nota del traduttore.: Ulteriori dettagli sulle diverse strategie di distribuzione in Kubernetes (comprese le citate canary, blue/green e altre) possono essere trovati in .
9. Controllo dello stato
TL;DR: Tieni d'occhio quali istanze dei servizi sono attive e reagisci a quelle che smettono di esserlo.
Controllo dello stato (health check) aiuta a decidere se le istanze del servizio sono pronte ad accettare e gestire il traffico. Ad esempio, nel caso dei servizi HTTP, un controllo dello stato potrebbe consistere in una richiesta GET a un endpoint /health. Risposta 200 OK significherà che l'istanza è sana, qualsiasi altro indicatore significherà che non è pronta ad accettare traffico. I service mesh consentono di specificare sia il metodo per controllare la disponibilità, sia la frequenza con cui questo controllo verrà effettuato. Queste informazioni possono poi essere utilizzate per altre finalità, come il bilanciamento del carico e il circuit breaking.
Pertanto, il monitoraggio della salute non è un caso d'uso a sé stante, ma viene solitamente utilizzato per raggiungere altri obiettivi. Inoltre, a seconda dei risultati dei health check, possono essere necessarie azioni esterne (rispetto ad altri obiettivi delle reti di servizio): ad esempio, aggiornare la pagina di stato, aprire issue su GitHub o compilare un ticket JIRA. E i service mesh offrono un meccanismo comodo per automatizzare tutto ciò.
10. Scarico del carico (load shedding)
TL;DR: Ridireziona il traffico in risposta a un picco temporaneo nell'uso.
Se un certo servizio si trova sovraccarico di traffico, puoi temporaneamente reindirizzare parte di questo traffico altrove (cioè "scartare", "versare") (shed) lì. Ad esempio, nel servizio di backup o nel data center, o in modo permanente topic. Di conseguenza, il servizio continuerà a gestire alcune delle richieste invece di bloccarsi e smettere di elaborare del tutto. Il bilanciamento del carico è preferibile alla rottura della catena, ma è comunque sconsigliato abusarne. Questo permette di prevenire guasti a cascata, che portano al malfunzionamento dei servizi downstream.
11. Parallelizzazione/mirroraggio del traffico
TL;DR: Invia una richiesta a più destinazioni contemporaneamente.
A volte è necessario inviare una richiesta (o un certo campione di richieste) contemporaneamente a più servizi. Un esempio caratteristico è l'invio di parte del traffico di produzione al servizio di staging. Il server web principale della produzione invia una richiesta al servizio sottostante products.production e solo a lui. E la service mesh copia intelligentemente questa richiesta e la invia a products.staging, di cui il server web non è nemmeno a conoscenza.
Un altro scenario d'uso correlato della service mesh che può essere realizzato sopra la parallelizzazione del traffico è . Prevede l'invio delle stesse richieste a diverse versioni del servizio e la verifica che tutte le versioni si comportino in modo identico. Finora non ho incontrato implementazioni di service mesh con un sistema di testing regressive integrato come , ma l'idea stessa sembra promettente.
12. Isolamento
TL;DR: Suddividi la tua service mesh in micro-reti.
Conosciuta anche come segmentazione, l'isolamento è l'arte di suddividere la rete dei servizi in segmenti logicamente distinti che non sanno nulla l'uno dell'altro. L'isolamento è un po' simile alla creazione di reti private virtuali. La differenza fondamentale è che puoi ancora sfruttare tutti i vantaggi della service mesh (come la scoperta dei servizi), ma con maggiore sicurezza. Ad esempio, se un attaccante riesce a penetrare in un servizio in una delle sotto-reti, non sarà in grado di vedere quali servizi sono attivi nelle altre sotto-reti o di intercettare il loro traffico.
Inoltre, i vantaggi possono essere anche organizzativi. Potresti voler suddividere i servizi in sottoreti a seconda della struttura aziendale e liberare gli sviluppatori dal carico cognitivo causato dalla necessità di tenere a mente l'intera service mesh.
13. Limitazione della frequenza delle richieste, retry e timeout
TL;DR: Non è più necessario includere nella base di codice le attività urgenti relative alla gestione delle richieste.
Tutte queste cose potrebbero essere considerate casi d'uso distinti, ma ho deciso di unirle per una caratteristica comune: si occupano della gestione del ciclo di vita delle richieste, tipicamente gestita da librerie applicative. Se stai sviluppando un server web in Ruby on Rails (non integrato con la service mesh) che esegue richieste ai servizi backend attraverso , l'applicazione dovrà decidere autonomamente cosa fare se N richieste falliscono. Inoltre, sarà necessario determinare quale volume di traffico questi servizi saranno in grado di gestire e 'hardcodare' questi parametri utilizzando una libreria specifica. Inoltre, l'applicazione dovrà decidere quando è il momento di arrendersi e lasciar decadere la richiesta (a causa del timeout). E per modificare uno qualsiasi dei parametri sopra menzionati, sarà necessario fermare il server web, riconfigurarlo e riavviarlo.
Delegare queste attività alla rete di servizi significa non solo che gli sviluppatori dei servizi non dovranno più preoccuparsene, ma che possono essere considerate in una visione più globale. Se è in uso una catena complessa di servizi, ad esempio, A → B → C → D → E, è necessario considerare l'intero ciclo di vita della richiesta. Se l'obiettivo è prolungare i timeout nel servizio C, è logico farlo tutto in una volta anziché in parte: aggiornando il codice del servizio e aspettando che la richiesta di pull venga accettata e che il sistema CI distribuisca il servizio aggiornato.
14. Telemetria
TL;DR: Raccogliete tutte le informazioni necessarie (e non) dai servizi.
La telemetria è un termine generico che include metriche, tracciamento distribuito e log. Le service mesh offrono meccanismi per la raccolta e l'elaborazione di tutti e tre i tipi di dati. Qui le cose si fanno un po' sfocate, poiché il numero di varianti possibili è troppo grande. Per la raccolta delle metriche ci sono e altri strumenti, per la raccolta dei log si può utilizzare , , e altro. (per esempio, ClickHouse con il nostro per K8s — nota del traduttore.), per il tracciamento distribuito ci sono e simili. Ogni service mesh può supportare alcuni strumenti e non supportare altri. Sarà interessante vedere se il progetto può garantire una certa convergenza.
In questo caso, il vantaggio della tecnologia service mesh è che i container sidecar possono, in linea di principio, raccogliere tutti i dati sopra menzionati dai loro servizi. In altre parole, avete a disposizione un sistema unico di raccolta della telemetria, e la service mesh può elaborare tutte queste informazioni in vari modi. Ad esempio:
- seguire i log di un certo servizio tramite CLI;
- monitorare il volume delle richieste dalla dashboard della service mesh;
- raccogliere tracce distribuite e inoltrarle a un sistema come Jaeger.
Attenzione, giudizio soggettivo: In generale, la telemetria è un'area in cui un forte intervento della service mesh è indesiderato. Raccogliere informazioni di base e monitorare in tempo reale alcune 'metriche d'oro' come la percentuale di richieste riuscite e i ritardi è accettabile, ma speriamo di non assistere all'emergere di questi stack di Frankenstein che tentano di sostituire sistemi specializzati, alcuni dei quali hanno già dimostrato di essere eccellenti e ben studiati.
15. Audit
TL;DR: Chi dimentica le lezioni della storia è destinato a ripeterle.
L'audit è l'arte di osservare eventi importanti nel sistema. Nel caso della service mesh, questo può significare tracciare chi ha effettuato richieste a specifici endpoint di determinati servizi o quante volte, nell'ultimo mese, si è verificato un evento relativo alla sicurezza.
È chiaro che l'audit è strettamente legato alla telemetria. La differenza risiede nel fatto che la telemetria è solitamente associata a elementi come prestazioni e solidità tecnica, mentre l'audit può riguardare questioni legali e altri aspetti che vanno oltre la mera sfera tecnica (ad esempio, conformità al GDPR ― Regolamento generale sulla protezione dei dati dell'UE).
16. Visualizzazione
TL;DR: Evviva React.js ― una fonte inesauribile di interfacce stravaganti.
Forse esiste un termine più appropriato, ma non lo conosco. Mi riferisco semplicemente alla rappresentazione grafica della service mesh o di alcuni dei suoi componenti. Queste visualizzazioni possono includere indicatori come i ritardi medi, informazioni sulla configurazione dei contenitori sidecar, risultati dei controlli di salute e avvisi.
Lavorare in un ambiente orientato ai servizi comporta un carico cognitivo molto maggiore rispetto a Sua Maestà il Monolite. Pertanto, è fondamentale ridurre la pressione cognitiva a tutti i costi. Un'interfaccia grafica banale per il service mesh, con la possibilità di cliccare su un pulsante e ottenere il risultato desiderato, può fare una differenza decisiva per la crescita della popolarità di questa tecnologia.
Non inclusi nell'elenco
Inizialmente intendevo includere nel l'elenco altri casi d'uso, ma poi ho deciso di non farlo. Ecco quelli insieme ai motivi della mia decisione:
- Multi-datacenter. Nella mia visione, questo non è tanto un caso d'uso, quanto una nicchia specifica per l'applicazione delle service mesh o di alcune funzionalità, come la scoperta dei servizi.
- Ingress ed egress. Questo è un campo correlato, ma mi sono limitato (forse artificialmente) al caso d'uso del traffico "east-west". Ingress ed egress meritano un articolo a parte.
Conclusione
Questo è tutto per ora! Ancora una volta, questa lista è piuttosto convenzionale e, probabilmente, incompleta. Se pensi che mi sia sfuggito qualcosa, o che abbia commesso un errore, contattami su Twitter (). Ti preghiamo di rispettare le regole di cortesia.
P.S. dal traduttore
L'immagine di copertura dell'articolo è basata su un'immagine dell'articolo «» (autore — Gregory MacKinnon). Essa mostra come parte delle funzionalità delle applicazioni (in verde) sia stata trasferita al service mesh, che garantisce le interconnessioni tra di esse (in blu).
Leggete anche nel nostro blog:
- «»;
- «»;
- «».
Fonte: habr.com
