Benchmark sul consumo della CPU per Istio e Linkerd

Benchmark sul consumo della CPU per Istio e Linkerd

Introduzione

Siamo dentro Shopify: ha iniziato a distribuire Istio come mesh di servizi. In linea di principio va tutto bene, tranne una cosa: è costoso.

В benchmark pubblicati per Istio dice:

Con Istio 1.1, il proxy consuma circa 0,6 vCPU (core virtuali) per 1000 richieste al secondo.

Per la prima regione della service mesh (2 proxy su ciascun lato della connessione), avremo 1200 core solo per il proxy, ad una velocità di un milione di richieste al secondo. Secondo il calcolatore dei costi di Google, la configurazione ammonta a circa $ 40 al mese per core n1-standard-64, cioè solo questa regione ci costerà più di 50mila dollari al mese per 1 milione di richieste al secondo.

Ivan Sim (Ivan Sim) confrontato visivamente l'anno scorso il service mesh ha subito ritardi e ha promesso lo stesso per memoria e processore, ma non ha funzionato:

Apparentemente, valori-istio-test.yaml aumenterà seriamente le richieste della CPU. Se ho fatto bene i conti, sono necessari circa 24 core CPU per il pannello di controllo e 0,5 CPU per ciascun proxy. Non ho molto. Ripeterò i test quando mi verranno assegnate più risorse.

Volevo vedere di persona quanto le prestazioni di Istio siano simili a quelle di un altro mesh di servizi open source: Linkerd.

Installazione della rete di servizi

Prima di tutto l'ho installato in un cluster SuperGloo:

$ supergloo init
installing supergloo version 0.3.12
using chart uri https://storage.googleapis.com/supergloo-helm/charts/supergloo-0.3.12.tgz
configmap/sidecar-injection-resources created
serviceaccount/supergloo created
serviceaccount/discovery created
serviceaccount/mesh-discovery created
clusterrole.rbac.authorization.k8s.io/discovery created
clusterrole.rbac.authorization.k8s.io/mesh-discovery created
clusterrolebinding.rbac.authorization.k8s.io/supergloo-role-binding created
clusterrolebinding.rbac.authorization.k8s.io/discovery-role-binding created
clusterrolebinding.rbac.authorization.k8s.io/mesh-discovery-role-binding created
deployment.extensions/supergloo created
deployment.extensions/discovery created
deployment.extensions/mesh-discovery created
install successful!

Ho utilizzato SuperGloo perché rende molto più semplice il bootstrap della mesh di servizi. Non dovevo fare molto. Non utilizziamo SuperGloo in produzione, ma è l'ideale per tale compito. Ho dovuto utilizzare letteralmente un paio di comandi per ciascuna mesh di servizi. Ho utilizzato due cluster per l'isolamento, uno ciascuno per Istio e Linkerd.

L'esperimento è stato condotto su Google Kubernetes Engine. Ho usato Kubernetes 1.12.7-gke.7 e un pool di nodi n1-standard-4 con ridimensionamento automatico dei nodi (minimo 4, massimo 16).

Quindi ho installato entrambe le mesh di servizi dalla riga di comando.

Primo Linker:

$ supergloo install linkerd --name linkerd
+---------+--------------+---------+---------------------------+
| INSTALL |     TYPE     | STATUS  |          DETAILS          |
+---------+--------------+---------+---------------------------+
| linkerd | Linkerd Mesh | Pending | enabled: true             |
|         |              |         | version: stable-2.3.0     |
|         |              |         | namespace: linkerd        |
|         |              |         | mtls enabled: true        |
|         |              |         | auto inject enabled: true |
+---------+--------------+---------+---------------------------+

Poi Istio:

$ supergloo install istio --name istio --installation-namespace istio-system --mtls=true --auto-inject=true
+---------+------------+---------+---------------------------+
| INSTALL |    TYPE    | STATUS  |          DETAILS          |
+---------+------------+---------+---------------------------+
| istio   | Istio Mesh | Pending | enabled: true             |
|         |            |         | version: 1.0.6            |
|         |            |         | namespace: istio-system   |
|         |            |         | mtls enabled: true        |
|         |            |         | auto inject enabled: true |
|         |            |         | grafana enabled: true     |
|         |            |         | prometheus enabled: true  |
|         |            |         | jaeger enabled: true      |
+---------+------------+---------+---------------------------+

Il crash-loop durò alcuni minuti, poi i pannelli di controllo si stabilizzarono.

(Nota: per ora SuperGloo supporta solo Istio 1.0.x. Ho ripetuto l'esperimento con Istio 1.1.3, ma non ho notato alcuna differenza evidente.)

Configurazione della distribuzione automatica di Istio

Per fare in modo che Istio installi il sidecar Envoy, utilizziamo l'iniettore sidecar − MutatingAdmissionWebhook. Non ne parleremo in questo articolo. Lasciatemi solo dire che questo è un controller che monitora l'accesso di tutti i nuovi pod e aggiunge dinamicamente un sidecar e un initContainer, che è responsabile delle attività iptables.

Noi di Shopify abbiamo scritto il nostro controller di accesso per implementare i sidecar, ma per questo benchmark ho utilizzato il controller fornito con Istio. Il controller inserisce sidecar per impostazione predefinita quando è presente un collegamento nello spazio dei nomi istio-injection: enabled:

$ kubectl label namespace irs-client-dev istio-injection=enabled
namespace/irs-client-dev labeled

$ kubectl label namespace irs-server-dev istio-injection=enabled
namespace/irs-server-dev labeled

Configurazione della distribuzione automatica di Linkerd

Per impostare l'incorporamento del sidecar Linkerd, utilizziamo le annotazioni (le ho aggiunte manualmente tramite kubectl edit):

metadata:
  annotations:
    linkerd.io/inject: enabled

$ k edit ns irs-server-dev 
namespace/irs-server-dev edited

$ k get ns irs-server-dev -o yaml
apiVersion: v1
kind: Namespace
metadata:
  annotations:
    linkerd.io/inject: enabled
  name: irs-server-dev
spec:
  finalizers:
  - kubernetes
status:
  phase: Active

Simulatore di tolleranza agli errori Istio

Abbiamo creato un simulatore di tolleranza agli errori chiamato Istio per sperimentare il traffico esclusivo di Shopify. Avevamo bisogno di uno strumento per creare una topologia personalizzata che rappresentasse una porzione specifica del nostro grafico dei servizi, configurata dinamicamente per modellare carichi di lavoro specifici.

L'infrastruttura di Shopify è sottoposta a un carico pesante durante le vendite flash. Allo stesso tempo, Shopify raccomanda ai venditori di effettuare tali vendite più spesso. I grandi clienti a volte avvertono di una vendita flash pianificata. Altri li conducono inaspettatamente per noi a qualsiasi ora del giorno e della notte.

Volevamo che il nostro simulatore di resilienza modellasse flussi di lavoro che corrispondessero alle topologie e ai carichi di lavoro che hanno sopraffatto l'infrastruttura di Shopify in passato. Lo scopo principale dell'utilizzo di una rete di servizi è che abbiamo bisogno di affidabilità e tolleranza ai guasti a livello di rete, ed è importante per noi che la rete di servizi faccia fronte in modo efficace ai carichi che in precedenza interrompevano i servizi.

Al centro del simulatore di tolleranza agli errori c'è un nodo di lavoro, che funge da nodo di rete di servizi. Il nodo di lavoro può essere configurato staticamente all'avvio o dinamicamente tramite un'API REST. Utilizziamo la configurazione dinamica dei nodi di lavoro per creare flussi di lavoro sotto forma di test di regressione.

Ecco un esempio di tale processo:

  • Lanciamo 10 server come bar servizio che restituisce una risposta 200/OK dopo 100 ms.
  • Lanciamo 10 client, ciascuno dei quali invia 100 richieste al secondo bar.
  • Ogni 10 secondi rimuoviamo 1 server e monitoriamo gli errori 5xx sul cliente.

Alla fine del flusso di lavoro, esaminiamo i log e le metriche e controlliamo se il test è stato superato. In questo modo apprendiamo le prestazioni della nostra rete di servizi ed eseguiamo un test di regressione per testare le nostre ipotesi sulla tolleranza agli errori.

(Nota: stiamo valutando la possibilità di rendere open source il simulatore di tolleranza agli errori Istio, ma non siamo ancora pronti a farlo.)

Simulatore di tolleranza agli errori Istio per il benchmark della mesh di servizi

Impostiamo diversi nodi di lavoro del simulatore:

  • irs-client-loadgen: 3 repliche che inviano 100 richieste al secondo per irs-client.
  • irs-client: 3 repliche che ricevono la richiesta, attendono 100 ms e inoltrano la richiesta a irs-server.
  • irs-server: 3 repliche che ritornano 200/OK dopo 100 ms.

Con questa configurazione, possiamo misurare un flusso di traffico stabile tra 9 endpoint. Sidecar dentro irs-client-loadgen и irs-server ricevere 100 richieste al secondo e irs-client — 200 (in entrata e in uscita).

Monitoriamo l'utilizzo delle risorse attraverso DataDogperché non abbiamo un ammasso Prometeo.

Giudizio

Pannelli di controllo

Innanzitutto, abbiamo esaminato il consumo della CPU.

Benchmark sul consumo della CPU per Istio e Linkerd
Pannello di controllo Linkerd ~22 millicore

Benchmark sul consumo della CPU per Istio e Linkerd
Pannello di controllo Istio: ~750 millicore

Il pannello di controllo Istio utilizza circa 35 volte più risorse della CPUrispetto a Linkerd. Ovviamente, tutto è installato per impostazione predefinita e qui la telemetria istio consuma molte risorse del processore (può essere disabilitata disabilitando alcune funzioni). Se rimuoviamo questo componente, otteniamo comunque più di 100 millicore 4 volte di piùrispetto a Linkerd.

Procura del sidecar

Abbiamo quindi testato l'uso di un proxy. Dovrebbe esserci una relazione lineare con il numero di richieste, ma per ogni sidecar c'è un sovraccarico che influenza la curva.

Benchmark sul consumo della CPU per Istio e Linkerd
Linkerd: ~100 millicore per irs-client, ~50 millicore per irs-client-loadgen

I risultati sembrano logici, perché il proxy client riceve il doppio del traffico rispetto al proxy loadgen: per ogni richiesta in uscita da loadgen, il client ne ha una in entrata e una in uscita.

Benchmark sul consumo della CPU per Istio e Linkerd
Istio/Envoy: ~155 millicore per irs-client, ~75 millicore per irs-client-loadgen

Vediamo risultati simili per i sidecar Istio.

Ma in generale, i proxy Istio/Envoy consumano circa il 50% in più di risorse della CPUrispetto a Linkerd.

Vediamo lo stesso schema lato server:

Benchmark sul consumo della CPU per Istio e Linkerd
Linkerd: ~50 millicore per irs-server

Benchmark sul consumo della CPU per Istio e Linkerd
Istio/Envoy: ~80 millicore per irs-server

Sul lato server, il sidecar Istio/Envoy consuma circa il 60% in più di risorse della CPUrispetto a Linkerd.

conclusione

Il proxy Istio Envoy consuma oltre il 50% di CPU in più rispetto a Linkerd sul nostro carico di lavoro simulato. Il pannello di controllo Linkerd consuma molte meno risorse di Istio, soprattutto per i componenti principali.

Stiamo ancora pensando a come ridurre questi costi. Se hai idee, condividile!

Fonte: habr.com

Aggiungi un commento