Benchmark del consumo della CPU per Istio e Linkerd

Benchmark del consumo della CPU per Istio e Linkerd

Introduzione

Noi di Shopify ci siamo occupati dell'implementazione di Istio come service mesh. In linea generale, tutto va bene, tranne per una cosa: è costoso.

In benchmark pubblicati per Istio si dice:

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

Per la prima regione nel service mesh (2 proxy da ciascun lato della connessione) avremo bisogno di 1200 core solo per i proxy, basandoci su un milione di richieste al secondo. Secondo il calcolatore dei costi di Google, circa $40/mese/core per la configurazione n1-standard-64, il che significa che questa regione ci costerà più di 50.000 dollari al mese per un milione di richieste al secondo.

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

Sembra che values-istio-test.yaml aumenterà notevolmente le richieste alla CPU. Se ho calcolato correttamente, servono circa 24 core per il pannello di controllo e 0,5 CPU per ogni proxy. Non ho così tante risorse. Ripeterò i test quando riceverò più risorse.

Volevo vedere di persona quanto i risultati di Istio somigliassero ad un'altra service mesh open source: Linkerd.

Installazione della service mesh

Per prima cosa, ho installato nel cluster SuperGloo:

$ supergloo init
installazione della versione 0.3.12 di supergloo
utilizzando 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 utilizzato SuperGloo perché semplifica notevolmente il setup iniziale del service mesh. Non ho dovuto fare quasi nulla. In produzione, non usiamo SuperGloo, ma per compiti come questo è perfetto. Ho dovuto utilizzare letteralmente un paio di comandi per ogni service mesh. Ho utilizzato due cluster per l'isolamento — uno per Istio e uno per Linkerd.

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

Dopo, ho installato entrambe le service mesh dalla riga di comando.

Prima Linkerd:

$ 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 ha impiegato diversi minuti, poi i pannelli di controllo si sono stabilizzati.

(Nota. SuperGloo attualmente supporta 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

Perché Istio installi il sidecar Envoy, utilizziamo l'iniettore di sidecar — MutatingAdmissionWebhook. Non ne parleremo in questo articolo. Dico solo che è un controller che monitora l'accesso di tutti i nuovi pod e aggiunge dinamicamente sidecar e initContainer, il quale è responsabile delle operazioni iptables.

Noi di Shopify abbiamo scritto il nostro controller di accesso per l'inserimento dei sidecar, ma in questo benchmark ho utilizzato il controller fornito con Istio. Il controller di default inserisce i sidecar quando nell'namespace c'è un'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

Configurazione dell'inserimento automatico di Linkerd

Per configurare l'inserimento 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: Active

Simulatore di resilienza di Istio

Abbiamo creato un simulatore di tolleranza ai guasti di Istio per sperimentare con il traffico specifico per Shopify. Avevamo bisogno di uno strumento per creare topologie arbitrarie che rappresentassero una parte specifica del grafo del nostro servizio con configurazioni dinamiche per simulare carichi di lavoro specifici.

L'infrastruttura di Shopify subisce un grande carico durante le vendite flash. In questo contesto, Shopify raccomanda ai venditori di organizzare più spesso tali vendite. Grandi clienti talvolta avvisano di una vendita flash programmata. Altri le organizzano inaspettatamente, in qualsiasi momento della giornata e della notte.

Volevamo che il nostro simulatore di tolleranza ai guasti riproducesse flussi di lavoro che corrispondessero a topologie e carichi di lavoro che in passato avevano causato sovraccarichi all'infrastruttura di Shopify. L'obiettivo principale dell'uso del service mesh è garantire la resilienza e la tolleranza ai guasti a livello di rete, ed è importante che il service mesh gestisca efficacemente i carichi che in precedenza avevano disturbato il funzionamento dei servizi.

Alla base del simulatore di tolleranza agli errori c'è un nodo di lavoro che agisce come nodo di service mesh. Il nodo di lavoro può essere configurato staticamente all'avvio o dinamicamente tramite API REST. Utilizziamo la configurazione dinamica dei nodi di lavoro per creare flussi di lavoro sotto forma di test regressivi.

Ecco un esempio di questo processo:

  • Avviamo 10 server come bar servizio che restituisce una risposta 200/OK dopo 100 ms.
  • Avviamo 10 client, ciascuno 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 flusso di lavoro, esaminiamo i log e le metriche e verifichiamo se il test è stato superato. In questo modo possiamo valutare le performance della nostra service mesh e condurre un test regressivo per verificare le nostre ipotesi sulla tolleranza agli errori.

(Nota. Stiamo pensando di rendere pubblico il codice sorgente del simulatore di tolleranza agli errori di Istio, ma non siamo ancora pronti per farlo.)

Simulatore di tolleranza agli errori di Istio per il benchmarking della service mesh

Configuriamo diversi nodi di lavoro per il 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 stabile di traffico tra 9 endpoint. I sidecar in irs-client-loadgen e irs-server ricevono 100 richieste al secondo, mentre irs-client — 200 (in ingresso e in uscita).

Monitoriamo l'uso delle risorse tramite DataDog, poiché non abbiamo un cluster Prometheus.

Risultati

Pannelli di controllo

Inizialmente, abbiamo esaminato il consumo della CPU.

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

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

Il pannello di controllo Istio utilizza circa 35 volte più risorse di CPU, rispetto a Linkerd. Ovviamente, tutto è impostato per default e molto delle risorse CPU sono consumate da istio-telemetry (che può essere disattivato rinunciando ad alcune funzionalità). Anche senza questo componente, si ottiene comunque più di 100 millisecondi, cioè 4 volte di più, rispetto a Linkerd.

Proxy sidecar

Poi abbiamo controllato l'uso del proxy. Qui dovrebbe esserci una dipendenza lineare dal numero di richieste, ma per ogni sidecar ci sono alcune spese generali che influenzano la curva.

Benchmark del consumo della CPU per Istio e Linkerd
Linkerd: ~100 millisecondi per irs-client, ~50 millisecondi 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 da parte del client.

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

Osserviamo risultati simili per i sidecar di Istio.

Tuttavia, in generale, il proxy Istio/Envoy consuma circa il 50% di risorse CPU in più, rispetto a Linkerd.

La stessa situazione si verifica sul lato server:

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

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

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

Conclusione

Il proxy Istio Envoy consuma oltre il 50% di CPU in più rispetto a Linkerd, sulla nostra simulazione di carico di lavoro. La dashboard di Linkerd utilizza molte meno risorse rispetto a Istio, in particolare per quanto riguarda i componenti principali.

Stiamo ancora valutando 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