Benchmark de consumo de CPU para Istio e Linkerd

Benchmark de consumo de CPU para Istio e Linkerd

Introdução

Estamos em Shopify começou a implantar o Istio como uma malha de serviço. Em princípio está tudo bem, exceto por uma coisa: é caro.

В benchmarks publicados para Istio diz:

Com o Istio 1.1, o proxy consome aproximadamente 0,6 vCPUs (núcleos virtuais) a cada 1000 solicitações por segundo.

Para a primeira região da service mesh (2 proxies de cada lado da conexão), teremos 1200 núcleos apenas para o proxy, a uma taxa de um milhão de solicitações por segundo. De acordo com a calculadora de custos do Google, custa aproximadamente US$ 40/mês/núcleo para configuração n1-standard-64, ou seja, só esta região nos custará mais de 50 mil dólares por mês para 1 milhão de solicitações por segundo.

Ivan Sim (Ivan Sim) comparado visualmente service mesh atrasou no ano passado e prometeu o mesmo para memória e processador, mas não deu certo:

Aparentemente, values-istio-test.yaml aumentará seriamente as solicitações de CPU. Se fiz minhas contas corretamente, você precisará de aproximadamente 24 núcleos de CPU para o painel de controle e 0,5 CPU para cada proxy. Eu não tenho tanto. Repetirei os testes quando mais recursos forem alocados para mim.

Eu queria ver por mim mesmo como o desempenho do Istio é semelhante ao de outra malha de serviço de código aberto: linkerd.

Instalação de malha de serviço

Primeiro de tudo, instalei em um 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!

Usei o SuperGloo porque facilita muito a inicialização da malha de serviço. Eu não tive que fazer muito. Não utilizamos SuperGloo na produção, mas é ideal para tal tarefa. Tive que usar literalmente alguns comandos para cada malha de serviço. Usei dois clusters para isolamento - um para Istio e um para Linkerd.

O experimento foi conduzido no Google Kubernetes Engine. Eu usei Kubernetes 1.12.7-gke.7 e um conjunto de nós n1-standard-4 com escalonamento automático de nós (mínimo 4, máximo 16).

Em seguida, instalei as duas malhas de serviço na linha de comando.

Primeiro 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 |
+---------+--------------+---------+---------------------------+

Então 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      |
+---------+------------+---------+---------------------------+

O crash-loop demorou alguns minutos e então os painéis de controle se estabilizaram.

(Observação: o SuperGloo oferece suporte apenas ao Istio 1.0.x por enquanto. Repeti o experimento com o Istio 1.1.3, mas não notei nenhuma diferença perceptível.)

Configurando a implantação automática do Istio

Para fazer o Istio instalar o sidecar Envoy, usamos o injetor sidecar - MutatingAdmissionWebhook. Não falaremos sobre isso neste artigo. Deixe-me apenas dizer que este é um controlador que monitora o acesso de todos os novos pods e adiciona dinamicamente um sidecar e um initContainer, que é responsável pelas tarefas iptables.

Nós da Shopify escrevemos nosso próprio controlador de acesso para implementar sidecars, mas para este benchmark usei o controlador que vem com o Istio. O controlador injeta sidecars por padrão quando há um atalho no namespace 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

Configurando a implantação automática do Linkerd

Para configurar a incorporação do sidecar do Linkerd, usamos anotações (eu as adicionei manualmente via 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

Simulador de tolerância a falhas do Istio

Construímos um simulador de tolerância a falhas chamado Istio para experimentar o tráfego exclusivo do Shopify. Precisávamos de uma ferramenta para criar uma topologia personalizada que representasse uma parte específica do nosso gráfico de serviço, configurada dinamicamente para modelar cargas de trabalho específicas.

A infraestrutura do Shopify está sob forte carga durante as vendas relâmpago. Ao mesmo tempo, Shopify recomenda que os vendedores realizem essas vendas com mais frequência. Grandes clientes às vezes alertam sobre uma venda relâmpago planejada. Outros os conduzem inesperadamente para nós, a qualquer hora do dia ou da noite.

Queríamos que nosso simulador de resiliência modelasse fluxos de trabalho que correspondessem às topologias e cargas de trabalho que sobrecarregaram a infraestrutura do Shopify no passado. O principal objetivo do uso de uma malha de serviço é que precisamos de confiabilidade e tolerância a falhas no nível da rede, e é importante para nós que a malha de serviço lide efetivamente com cargas que anteriormente interrompiam os serviços.

No centro do simulador de tolerância a falhas está um nó de trabalho, que atua como um nó de malha de serviço. O nó do trabalhador pode ser configurado estaticamente na inicialização ou dinamicamente por meio de uma API REST. Usamos configuração dinâmica de nós de trabalho para criar fluxos de trabalho na forma de testes de regressão.

Aqui está um exemplo de tal processo:

  • Lançamos 10 servidores como bar serviço que retorna uma resposta 200/OK após 100 ms.
  • Lançamos 10 clientes - cada um envia 100 solicitações por segundo para bar.
  • A cada 10 segundos removemos 1 servidor e monitoramos erros 5xx no cliente.

No final do fluxo de trabalho, examinamos os logs e métricas e verificamos se o teste foi aprovado. Dessa forma, aprendemos sobre o desempenho da nossa malha de serviço e executamos um teste de regressão para testar nossas suposições sobre tolerância a falhas.

(Observação: estamos pensando em abrir o código-fonte do simulador de tolerância a falhas do Istio, mas ainda não estamos prontos para fazê-lo.)

Simulador de tolerância a falhas do Istio para benchmark de malha de serviço

Estamos configurando vários nós de trabalho do simulador:

  • irs-client-loadgen: 3 réplicas que enviam 100 solicitações por segundo por irs-client.
  • irs-client: 3 réplicas que recebem a requisição, aguardam 100ms e encaminham a requisição para irs-server.
  • irs-server: 3 réplicas que retornam 200/OK após 100 ms.

Com esta configuração, podemos medir um fluxo de tráfego estável entre 9 endpoints. Carros laterais em irs-client-loadgen и irs-server receber 100 solicitações por segundo e irs-client — 200 (entrada e saída).

Rastreamos o uso de recursos por meio de DataDogporque não temos um cluster Prometheus.

Descobertas

Painéis de controle

Primeiro, examinamos o consumo de CPU.

Benchmark de consumo de CPU para Istio e Linkerd
Painel de controle Linkerd ~22 milicore

Benchmark de consumo de CPU para Istio e Linkerd
Painel de controle do Istio: ~750 milicore

O painel de controle do Istio usa aproximadamente 35 vezes mais recursos de CPUdo que Linkerd. Claro, tudo é instalado por padrão, e a telemetria istio consome muitos recursos do processador aqui (pode ser desabilitada desabilitando algumas funções). Se removermos este componente, ainda teremos mais de 100 milicóres, ou seja 4 vezes maisdo que Linkerd.

Proxy secundário

Em seguida, testamos o uso de um proxy. Deveria haver uma relação linear com o número de solicitações, mas para cada sidecar existe alguma sobrecarga que afeta a curva.

Benchmark de consumo de CPU para Istio e Linkerd
Linkerd: ~100 milicores para irs-client, ~50 milicores para irs-client-loadgen

Os resultados parecem lógicos, porque o proxy do cliente recebe duas vezes mais tráfego que o proxy loadgen: para cada solicitação de saída do loadgen, o cliente tem uma entrada e uma saída.

Benchmark de consumo de CPU para Istio e Linkerd
Istio/Envoy: ~155 milicores para irs-client, ~75 milicores para irs-client-loadgen

Vemos resultados semelhantes para sidecars do Istio.

Mas, em geral, os proxies Istio/Envoy consomem aproximadamente 50% mais recursos de CPUdo que Linkerd.

Vemos o mesmo esquema no lado do servidor:

Benchmark de consumo de CPU para Istio e Linkerd
Linkerd: ~50 milicore para servidor irs

Benchmark de consumo de CPU para Istio e Linkerd
Istio/Envoy: ~80 milicore para servidor irs

No lado do servidor, o sidecar Istio/Envoy consome aproximadamente 60% mais recursos de CPUdo que Linkerd.

Conclusão

O proxy Istio Envoy consome mais de 50% de CPU do que o Linkerd em nossa carga de trabalho simulada. O painel de controle do Linkerd consome muito menos recursos que o Istio, especialmente para os componentes principais.

Ainda estamos pensando em como reduzir esses custos. Se você tiver ideias, por favor compartilhe!

Fonte: habr.com

Adicionar um comentário