Benchmark del consumo di CPU per Istio e Linkerd

Benchmark del consumo di CPU per Istio e Linkerd

Introduzione

Noi di Shopify abbiamo iniziato a implementare Istio come service mesh. In linea di principio, siamo soddisfatti, tranne per una cosa: è costoso.

In benchmark pubblicati per Istio si dice:

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

Per la prima regione nella service mesh (due proxy per ogni lato della connessione), avremo 1200 nuclei solo per i proxy, calcolando un milione di richieste al secondo. Secondo il calcolatore dei costi di Google, il costo è di circa $40/al mese/per nucleo per la configurazione n1-standard-64, quindi questa regione ci costerà oltre 50 mila dollari al mese per 1 milione di richieste al secondo.

Ivan Sim (Ivan Sim) ha confrontato visivamente le latenze della service mesh dell'anno scorso e ha promesso lo stesso per la memoria e la CPU, ma non è riuscito:

A quanto pare, il file values-istio-test.yaml aumenterà notevolmente le richieste alla CPU. Se ho calcolato bene, servono circa 24 nuclei di CPU per il pannello di controllo e 0,5 CPU per ogni proxy. Non ne ho così tanti. Ripeterò i test quando mi verranno dati più risorse.

Volevo verificare di persona quanto siano simili le prestazioni di Istio rispetto a un'altra service mesh open source: Linkerd.

Installazione della service mesh

Per prima cosa, ho installato nel cluster SuperGloo:

$ supergloo init
installando la versione supergloo 0.3.12
usando l'URI del chart https://storage.googleapis.com/supergloo-helm/charts/supergloo-0.3.12.tgz
configmap/sidecar-injection-resources creato
serviceaccount/supergloo creato
serviceaccount/discovery creato
serviceaccount/mesh-discovery creato
clusterrole.rbac.authorization.k8s.io/discovery creato
clusterrole.rbac.authorization.k8s.io/mesh-discovery creato
clusterrolebinding.rbac.authorization.k8s.io/supergloo-role-binding creato
clusterrolebinding.rbac.authorization.k8s.io/discovery-role-binding creato
clusterrolebinding.rbac.authorization.k8s.io/mesh-discovery-role-binding creato
deployment.extensions/supergloo creato
deployment.extensions/discovery creato
deployment.extensions/mesh-discovery creato
installazione riuscita!

Ho usato SuperGloo perché semplifica notevolmente l'impostazione iniziale della service mesh. Non ho dovuto fare quasi nulla. In produzione non usiamo SuperGloo, ma per un compito simile è perfetto. Ho dovuto eseguire solo un paio di comandi su ciascuna service mesh. Ho utilizzato due cluster per l'isolamento: uno per Istio e l'altro per 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).

Poi ho installato entrambe le service mesh dalla riga di comando.

Per prima cosa Linkerd:

$ supergloo install linkerd --name linkerd
+---------+--------------+---------+---------------------------+
| INSTALL |     TYPE     | STATUS  |          DETAILS          |
+---------+--------------+---------+---------------------------+
| linkerd | Linkerd Mesh | In attesa | abilitato: vero            |
|         |              |         | versione: stable-2.3.0     |
|         |              |         | namespace: linkerd        |
|         |              |         | mtls abilitato: vero      |
|         |              |         | auto inject abilitato: vero |
+---------+--------------+---------+---------------------------+

Poi Istio:

$ supergloo install istio --name istio --installation-namespace istio-system --mtls=true --auto-inject=true
+---------+------------+---------+---------------------------+
| INSTALL |    TYPE    | STATUS  |          DETAILS          |
+---------+------------+---------+---------------------------+
| istio   | Istio Mesh | In attesa | abilitato: vero            |
|         |            |         | versione: 1.0.6            |
|         |            |         | namespace: istio-system   |
|         |            |         | mtls abilitato: vero      |
|         |            |         | auto inject abilitato: vero |
|         |            |         | grafana abilitato: vero   |
|         |            |         | prometheus abilitato: vero |
|         |            |         | jaeger abilitato: vero    |
+---------+------------+---------+---------------------------+

Il crash-loop ha preso alcuni minuti, e poi i pannelli di controllo si sono stabilizzati.

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

Impostazione dell'iniezione automatica di Istio

Per far sì che Istio installi il sidecar Envoy, utilizziamo il sidecar-injector — MutatingAdmissionWebhook. Non ne parleremo in questo articolo. Dirò solo che è un controllore che monitora l'accesso di tutti i nuovi pod e aggiunge dinamicamente sidecar e initContainer, che si occupa dei compiti iptables.

In Shopify abbiamo scritto il nostro controllore di accesso per l'iniezione dei sidecar, ma in questo benchmark ho utilizzato il controllore fornito con Istio. Il controllore di default inietta i sidecar quando nel namespace è presente l'etichetta istio-injection: enabled:

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

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

Impostazione dell'iniezione automatica di Linkerd

Per configurare l'iniezione dei sidecar di 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 modificato

$ 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: Attivo

Simulatore di tolleranza ai guasti di Istio

Abbiamo sviluppato un simulatore di resilienza di Istio per sperimentare traffico specifico per Shopify. Avevamo bisogno di uno strumento per creare una topologia arbitraria che rappresentasse una parte specifica del grafo del nostro servizio, con impostazioni dinamiche per modellare carichi di lavoro specifici.

L'infrastruttura di Shopify subisce una grande pressione durante le vendite lampo. In questo contesto, Shopify consiglia ai venditori di effettuare vendite lampo più spesso. I grandi clienti a volte avvisano in anticipo riguardo a vendite lampo programmati. Altri le effettuano inaspettatamente, a qualsiasi ora del giorno e della notte.

Volevamo che il nostro simulatore di resilienza modellasse i flussi di lavoro che corrispondevano a topologie e carichi di lavoro che in passato avevano causato sovraccarichi all'infrastruttura di Shopify. L'obiettivo principale nell'utilizzare un service mesh è che abbiamo bisogno di affidabilità e resilienza a livello di rete, ed è importante per noi che il service mesh gestisca efficacemente i carichi che in passato hanno compromesso il funzionamento dei servizi.

Al centro del simulatore di resilienza c'è un nodo di lavoro che funge da nodo del service mesh. Il nodo di lavoro può essere configurato staticamente all'avvio o dinamicamente tramite REST API. Utilizziamo la configurazione dinamica dei nodi di lavoro per creare flussi di lavoro come test di regressione.

Ecco un esempio di tale processo:

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

Alla fine del ciclo di lavoro, analizziamo i log e le metriche per verificare se il test è stato superato. In questo modo, scopriamo le prestazioni del nostro service mesh e eseguiamo un test di regressione per confermare le nostre ipotesi sulla resilienza.

(Nota. Stiamo pensando di aprire il codice sorgente del simulatore di resilienza di Istio, ma non siamo ancora pronti per farlo.)

Simulatore di resilienza di Istio per il benchmark del service mesh

Stiamo configurando diversi nodi di lavoro del simulatore:

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

Con questa configurazione possiamo misurare un flusso di traffico stabile tra 9 punti finali. I sidecar in irs-client-loadgen e irs-server ricevono 100 richieste al secondo, e irs-client — 200 (in entrata e in uscita).

Monitoriamo l'utilizzo delle risorse tramite DataDog, perché non abbiamo un cluster Prometheus.

Risultati

Pannelli di controllo

Inizialmente abbiamo studiato il consumo della CPU.

Benchmark del consumo di CPU per Istio e Linkerd
Pannello di controllo Linkerd ~22 miliardi

Benchmark del consumo di CPU per Istio e Linkerd
Pannello di controllo Istio: ~750 miliardi

Il pannello di controllo Istio utilizza circa 35 volte più risorse della CPU, rispetto a Linkerd. Ovviamente, tutto è impostato di default e molte risorse della CPU sono consumate da istio-telemetry (può essere disattivato rinunciando ad alcune funzionalità). Anche rimuovendo questo componente, otteniamo ancora più di 100 miliardi, cioè 4 volte di più, rispetto a Linkerd.

Proxy sidecar

Poi abbiamo verificato l'utilizzo del proxy. Qui dovrebbe esserci una relazione lineare con il numero di richieste, ma per ogni sidecar ci sono alcune spese generali che influenzano la curva.

Benchmark del consumo di CPU per Istio e Linkerd
Linkerd: ~100 miliardi per irs-client, ~50 miliardi per irs-client-loadgen

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

Benchmark del consumo di CPU per Istio e Linkerd
Istio/Envoy: ~155 miliardi per irs-client, ~75 miliardi per irs-client-loadgen

Vediamo risultati simili per i sidecar di Istio.

Ma nel complesso, il proxy Istio/Envoy consuma circa il 50% in più di risorse della CPU, rispetto a Linkerd.

La stessa tendenza è visibile sul lato server:

Benchmark del consumo di CPU per Istio e Linkerd
Linkerd: ~50 miliardi per irs-server

Benchmark del consumo di CPU per Istio e Linkerd
Istio/Envoy: ~80 miliardi per irs-server

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

Conclusione

Il proxy Istio Envoy consuma oltre il 50% di CPU in più rispetto a Linkerd, sulla nostra workload simulata. Il pannello di controllo Linkerd consuma molto meno risorse rispetto a Istio, soprattutto per quanto riguarda i componenti principali.

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

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster