Punto de referencia de consumo de CPU para Istio y Linkerd

Punto de referencia de consumo de CPU para Istio y Linkerd

introducción

Estamos en Shopify Comenzó a implementar Istio como una malla de servicios. En principio todo está bien, excepto una cosa: es caro.

В puntos de referencia publicados para Istio dice:

Con Istio 1.1, el proxy consume aproximadamente 0,6 vCPU (núcleos virtuales) por cada 1000 solicitudes por segundo.

Para la primera región de la malla de servicios (2 proxies a cada lado de la conexión), tendremos 1200 núcleos solo para el proxy, a una velocidad de un millón de solicitudes por segundo. Según la calculadora de costos de Google, la configuración cuesta aproximadamente $40/mes/núcleo. n1-standard-64, es decir, solo esta región nos costará más de 50 mil dólares al mes por 1 millón de solicitudes por segundo.

Iván Sim (Iván Sim) comparado visualmente Service Mesh se retrasó el año pasado y prometió lo mismo para la memoria y el procesador, pero no funcionó:

Aparentemente, value-istio-test.yaml aumentará seriamente las solicitudes de CPU. Si hice mis cálculos correctamente, necesitas aproximadamente 24 núcleos de CPU para el panel de control y 0,5 CPU para cada proxy. No tengo tanto. Repetiré las pruebas cuando me asignen más recursos.

Quería ver por mí mismo qué tan similar es el rendimiento de Istio al de otra malla de servicios de código abierto: Linkerd.

Instalación de malla de servicio.

Primero que nada, lo instalé en un clúster. 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!

Utilicé SuperGloo porque facilita mucho el arranque de la malla de servicios. No tuve que hacer mucho. No utilizamos SuperGloo en producción, pero es ideal para tal tarea. Tuve que usar literalmente un par de comandos para cada malla de servicio. Utilicé dos clústeres para el aislamiento: uno para Istio y uno para Linkerd.

El experimento se realizó en Google Kubernetes Engine. Yo usé Kubernetes 1.12.7-gke.7 y un grupo de nodos n1-standard-4 con escalado automático de nodos (mínimo 4, máximo 16).

Luego instalé ambas mallas de servicio desde la línea de comando.

Primer enlace:

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

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

El bucle de choque tardó unos minutos y luego los paneles de control se estabilizaron.

(Nota: SuperGloo solo es compatible con Istio 1.0.x por ahora. Repetí el experimento con Istio 1.1.3, pero no noté ninguna diferencia notable).

Configurar la implementación automática de Istio

Para hacer que Istio instale el sidecar Envoy, usamos el inyector de sidecar: MutatingAdmissionWebhook. No hablaremos de ello en este artículo. Permítanme decirles que este es un controlador que monitorea el acceso de todos los pods nuevos y agrega dinámicamente un sidecar y un initContainer, que es responsable de las tareas. iptables.

Nosotros en Shopify escribimos nuestro propio controlador de acceso para implementar sidecars, pero para este punto de referencia utilicé el controlador que viene con Istio. El controlador inyecta sidecars de forma predeterminada cuando hay un acceso directo en el espacio de nombres 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

Configurar la implementación automática de Linkerd

Para configurar la incrustación de sidecar de Linkerd, usamos anotaciones (las agregué manualmente a través de 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 tolerancia a fallas de Istio

Creamos un simulador de tolerancia a fallas llamado Istio para experimentar con el tráfico exclusivo de Shopify. Necesitábamos una herramienta para crear una topología personalizada que representara una parte específica de nuestro gráfico de servicios, configurada dinámicamente para modelar cargas de trabajo específicas.

La infraestructura de Shopify está sometida a una gran carga durante las ventas flash. Al mismo tiempo, Shopify recomienda a los vendedores realizar dichas ventas con más frecuencia. Los grandes clientes a veces advierten sobre una venta flash planificada. Otros los realizan inesperadamente para nosotros en cualquier momento del día o de la noche.

Queríamos que nuestro simulador de resiliencia modelara flujos de trabajo que coincidieran con las topologías y cargas de trabajo que han abrumado la infraestructura de Shopify en el pasado. El objetivo principal del uso de una malla de servicios es que necesitamos confiabilidad y tolerancia a fallas a nivel de red, y para nosotros es importante que la malla de servicios haga frente de manera efectiva a las cargas que anteriormente interrumpían los servicios.

En el corazón del simulador de tolerancia a fallas se encuentra un nodo trabajador, que actúa como un nodo de malla de servicios. El nodo trabajador se puede configurar estáticamente al inicio o dinámicamente a través de una API REST. Utilizamos la configuración dinámica de nodos trabajadores para crear flujos de trabajo en forma de pruebas de regresión.

Aquí hay un ejemplo de tal proceso:

  • Lanzamos 10 servidores como bar servicio que devuelve una respuesta 200/OK después de 100 ms.
  • Lanzamos 10 clientes: cada uno envía 100 solicitudes por segundo a bar.
  • Cada 10 segundos eliminamos 1 servidor y monitoreamos errores 5xx en el cliente.

Al final del flujo de trabajo, examinamos los registros y las métricas y comprobamos si la prueba pasó. De esta manera aprendemos sobre el rendimiento de nuestra malla de servicios y ejecutamos una prueba de regresión para probar nuestras suposiciones sobre la tolerancia a fallas.

(Nota: estamos considerando el acceso abierto al simulador de tolerancia a fallas de Istio, pero aún no estamos listos para hacerlo).

Simulador de tolerancia a fallas de Istio para pruebas comparativas de malla de servicios

Estamos configurando varios nodos de trabajo del simulador:

  • irs-client-loadgen: 3 réplicas que envían 100 solicitudes por segundo por irs-client.
  • irs-client: 3 réplicas que reciben la solicitud, esperan 100 ms y reenvían la solicitud a irs-server.
  • irs-server: 3 réplicas que regresan 200/OK después de 100 ms.

Con esta configuración podemos medir un flujo de tráfico estable entre 9 puntos finales. Sidecares en irs-client-loadgen и irs-server recibir 100 solicitudes por segundo, y irs-client — 200 (entrantes y salientes).

Realizamos un seguimiento del uso de recursos a través de DataDogporque no tenemos un clúster Prometheus.

resultados

Paneles de control

Primero, examinamos el consumo de CPU.

Punto de referencia de consumo de CPU para Istio y Linkerd
Panel de control Linkerd ~22 milicore

Punto de referencia de consumo de CPU para Istio y Linkerd
Panel de control de Istio: ~750 milicore

El panel de control de Istio utiliza aproximadamente 35 veces más recursos de CPUque Linkerd. Por supuesto, todo está instalado de forma predeterminada e istio-telemetry consume muchos recursos del procesador aquí (se puede desactivar desactivando algunas funciones). Si eliminamos este componente, todavía obtenemos más de 100 milicores, es decir Tiempos 4que Linkerd.

Proxy de sidecar

Luego probamos el uso de un proxy. Debería haber una relación lineal con el número de solicitudes, pero para cada sidecar hay una sobrecarga que afecta la curva.

Punto de referencia de consumo de CPU para Istio y Linkerd
Linkerd: ~100 milicores para irs-client, ~50 milicores para irs-client-loadgen

Los resultados parecen lógicos, porque el proxy del cliente recibe el doble de tráfico que el proxy de loadgen: por cada solicitud saliente de loadgen, el cliente tiene una entrante y otra saliente.

Punto de referencia de consumo de CPU para Istio y Linkerd
Istio/Envoy: ~155 milicores para irs-client, ~75 milicores para irs-client-loadgen

Vemos resultados similares para los sidecars Istio.

Pero en general, los proxies Istio/Envoy consumen aproximadamente un 50% más de recursos de CPUque Linkerd.

Vemos el mismo esquema en el lado del servidor:

Punto de referencia de consumo de CPU para Istio y Linkerd
Linkerd: ~50 milicores para el servidor irs

Punto de referencia de consumo de CPU para Istio y Linkerd
Istio/Envoy: ~80 milicores para irs-server

En el lado del servidor, el sidecar Istio/Envoy consume aproximadamente un 60% más de recursos de CPUque Linkerd.

Conclusión

El proxy Istio Envoy consume más de un 50% más CPU que Linkerd en nuestra carga de trabajo simulada. El panel de control de Linkerd consume muchos menos recursos que Istio, especialmente para los componentes principales.

Todavía estamos pensando en cómo reducir estos costos. Si tienes ideas, ¡compártelas!

Fuente: habr.com

Añadir un comentario