Nota. traducir: La primera parte Esta serie estuvo dedicada a presentar las capacidades de Istio y demostrarlas en acción. Ahora hablaremos sobre aspectos más complejos de la configuración y el uso de esta malla de servicios y, en particular, sobre el enrutamiento y la gestión del tráfico de red.
También te recordamos que el artículo utiliza configuraciones (manifiestos para Kubernetes e Istio) del repositorio. istio-maestría.
la gestión del tráfico
Con Istio, aparecen nuevas capacidades en el clúster para proporcionar:
Enrutamiento de solicitudes dinámicas: implementaciones canary, pruebas A/B;
Balanceo de carga: simple y consistente, basado en hashes;
Recuperación después de caídas: tiempos de espera, reintentos, disyuntores;
Insertar fallos: retrasos, solicitudes abandonadas, etc.
A medida que avance el artículo, estas capacidades se ilustrarán utilizando la aplicación seleccionada como ejemplo y se introducirán nuevos conceptos a lo largo del camino. El primer concepto de este tipo será DestinationRules(es decir, reglas sobre el destinatario del tráfico/solicitudes - traducción aproximada), con cuya ayuda activamos las pruebas A/B.
Pruebas A/B: DestinationRules en la práctica
Las pruebas A/B se utilizan en los casos en los que existen dos versiones de una aplicación (normalmente son visualmente diferentes) y no estamos 100% seguros de cuál mejorará la experiencia del usuario. Por lo tanto, ejecutamos ambas versiones simultáneamente y recopilamos métricas.
Para implementar la segunda versión de la interfaz, necesaria para demostrar las pruebas A/B, ejecute el siguiente comando:
$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions/sa-frontend-green created
El manifiesto de implementación de la versión verde difiere en dos lugares:
La imagen se basa en una etiqueta diferente: istio-green,
Las vainas tienen una etiqueta. version: green.
Dado que ambas implementaciones tienen una etiqueta app: sa-frontend,solicitudes enrutadas por servicio virtual sa-external-services para servicio sa-frontend, será redirigido a todas sus instancias y la carga se distribuirá a través de algoritmo de turnos, lo que conducirá a la siguiente situación:
Los archivos solicitados no fueron encontrados.
Estos archivos no se encontraron porque tienen nombres diferentes en diferentes versiones de la aplicación. Asegurémonos de esto:
Esto significa que index.html, que solicita una versión de archivos estáticos, puede ser enviado por el balanceador de carga a pods que tienen una versión diferente, donde, por razones obvias, dichos archivos no existen. Por lo tanto, para que la aplicación funcione, debemos establecer una restricción: “la misma versión de la aplicación que sirvió index.html debería atender solicitudes posteriores".
Lo lograremos con un equilibrio de carga consistente basado en hash (Equilibrio de carga de hash consistente). En este caso Las solicitudes del mismo cliente se envían a la misma instancia de backend., para el cual se utiliza una propiedad predefinida, por ejemplo, un encabezado HTTP. Implementado utilizando DestinationRules.
DestinoReglas
Después Servicio Virtual envió una solicitud al servicio deseado, usando DestinationRules podemos definir políticas que se aplicarán al tráfico destinado a instancias de este servicio:
Gestión del tráfico con recursos de Istio
Nota: El impacto de los recursos de Istio en el tráfico de la red se presenta aquí de una manera fácil de entender. Para ser precisos, la decisión sobre a qué instancia enviar la solicitud la toma el Envoy en el Ingress Gateway configurado en el CRD.
Con las reglas de destino, podemos configurar el equilibrio de carga para utilizar hashes coherentes y garantizar que la misma instancia de servicio responda al mismo usuario. La siguiente configuración le permite lograr esto (regla de destino-sa-frontend.yaml):
Nota: Para agregar diferentes valores en el encabezado y probar los resultados directamente en el navegador, puede usar esta extensión a Chrome (o con este para Firefox: aprox. trad.).
En general, DestinationRules tiene más capacidades en el área de equilibrio de carga; consulte los detalles en documentación oficial.
Antes de seguir estudiando VirtualService, eliminemos la "versión verde" de la aplicación y la regla de dirección del tráfico correspondiente ejecutando los siguientes comandos:
Sombra (“blindaje”) o Duplicación ("reflejo") Se utiliza en los casos en los que queremos probar un cambio en la producción sin afectar a los usuarios finales: para hacer esto, duplicamos (“reflejamos”) las solicitudes en una segunda instancia donde se han realizado los cambios deseados y observamos las consecuencias. En pocas palabras, esto es cuando su colega elige el problema más crítico y realiza una solicitud de extracción en forma de un montón de basura tan grande que nadie puede revisarlo.
Para probar este escenario en acción, creemos una segunda instancia de SA-Logic con errores (buggy) ejecutando el siguiente comando:
$ kubectl apply -f resource-manifests/kube/shadowing/sa-logic-service-buggy.yaml
deployment.extensions/sa-logic-buggy created
Y ahora ejecutemos el comando para asegurarnos de que todas las instancias con app=sa-logic También disponen de etiquetas con las versiones correspondientes:
Servicio sa-logic apunta a vainas con una etiqueta app=sa-logic, por lo que todas las solicitudes se distribuirán entre todas las instancias:
... pero queremos que las solicitudes se envíen a instancias v1 y se reflejen en instancias v2:
Esto lo lograremos a través de VirtualService en combinación con DestinationRule, donde las reglas determinarán los subconjuntos y rutas del VirtualService a un subconjunto específico.
No se necesita explicación aquí, así que veámoslo en acción:
$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-shadowing-vs.yaml
virtualservice.networking.istio.io/sa-logic created
Agreguemos la carga llamando al siguiente comando:
$ while true; do curl -v http://$EXTERNAL_IP/sentiment
-H "Content-type: application/json"
-d '{"sentence": "I love yogobella"}';
sleep .8; done
Veamos los resultados en Grafana, donde puedes ver que la versión con errores (buggy) genera fallas en aproximadamente el 60 % de las solicitudes, pero ninguna de estas fallas afecta a los usuarios finales, ya que son respondidas por un servicio en ejecución.
Respuestas exitosas de diferentes versiones del servicio sa-logic
Aquí vimos por primera vez cómo se aplica VirtualService a los Envoys de nuestros servicios: cuando sa-web-app hace una solicitud a sa-logic, pasa por el sidecar Envoy, que, a través de VirtualService, está configurado para enrutar la solicitud al subconjunto v1 y reflejar la solicitud en el subconjunto v2 del servicio. sa-logic.
Lo sé, quizás ya pienses que los Servicios Virtuales son simples. En la siguiente sección, ampliaremos esto diciendo que también son realmente geniales.
Lanzamientos canarios
Canary Deployment es el proceso de implementar una nueva versión de una aplicación para una pequeña cantidad de usuarios. Se utiliza para asegurarse de que no haya problemas en la versión y solo después de eso, ya confiando en su calidad (de la versión), distribuirlo a otros usuarios.оaudiencia más grande.
Para demostrar las implementaciones canary, continuaremos trabajando con un subconjunto buggy у sa-logic.
No perdamos el tiempo en nimiedades y enviemos inmediatamente al 20% de los usuarios a la versión con errores (esto representará nuestro lanzamiento canario) y al 80% restante al servicio normal. Para hacer esto, use el siguiente servicio virtual (sa-logic-subsets-canary-vs.yaml):
... e inmediatamente veremos que algunas solicitudes conducen a fallas:
$ while true; do
curl -i http://$EXTERNAL_IP/sentiment
-H "Content-type: application/json"
-d '{"sentence": "I love yogobella"}'
--silent -w "Time: %{time_total}s t Status: %{http_code}n"
-o /dev/null; sleep .1; done
Time: 0.153075s Status: 200
Time: 0.137581s Status: 200
Time: 0.139345s Status: 200
Time: 30.291806s Status: 500
Los servicios virtuales permiten implementaciones canary: en este caso, hemos reducido el impacto potencial de los problemas al 20 % de la base de usuarios. ¡Maravilloso! Ahora, en todos los casos en los que no estemos seguros de nuestro código (en otras palabras, siempre...), podemos usar mirroring y canary rollouts.
Tiempos de espera y reintentos
Pero los errores no siempre terminan en el código. En la lista de "8 conceptos erróneos sobre la informática distribuida“En primer lugar está la creencia errónea de que “la red es confiable”. En realidad la red no confiable, y por esta razón necesitamos tiempos de espera (tiempos de espera) y reintentos (reintentos).
Para demostración continuaremos usando la misma versión del problema. sa-logic (buggy), y simularemos la falta de confiabilidad de la red con fallas aleatorias.
Deje que nuestro servicio con errores tenga 1/3 de posibilidades de tardar demasiado en responder, 1/3 de posibilidades de finalizar con un error interno del servidor y 1/3 de posibilidades de devolver la página con éxito.
Para mitigar el impacto de tales problemas y mejorar la vida de los usuarios, podemos:
agregue un tiempo de espera si el servicio tarda más de 8 segundos en responder,
El tiempo de espera de la solicitud se establece en 8 segundos;
Las solicitudes se reintentan 3 veces;
Y cada intento se considera fallido si el tiempo de respuesta supera los 3 segundos.
Esto es una optimización porque el usuario no tendrá que esperar más de 8 segundos y realizaremos tres nuevos intentos para obtener una respuesta en caso de fallas, aumentando las posibilidades de una respuesta exitosa.
Aplique la configuración actualizada con el siguiente comando:
Y compruebe en los gráficos de Grafana que el número de respuestas exitosas ha aumentado arriba:
Mejoras en las estadísticas de respuestas exitosas después de agregar tiempos de espera y reintentos
Antes de pasar a la siguiente sección (o mejor dicho, a la siguiente parte del artículo, porque en esto no habrá más experimentos prácticos - aprox. traducción.), borrar sa-logic-buggy y VirtualService ejecutando los siguientes comandos:
Estamos hablando de dos patrones importantes en la arquitectura de microservicios que le permiten lograr la autorrecuperación. (autosanación) servicios.
Cortacircuitos("cortacircuitos") se utiliza para finalizar las solicitudes que llegan a una instancia de un servicio que se considera en mal estado y restaurarlo mientras las solicitudes de los clientes se redirigen a instancias en buen estado de ese servicio (lo que aumenta el porcentaje de respuestas exitosas). (Nota: Puede encontrar una descripción más detallada del patrón, por ejemplo, aquí.)
Mamparo("dividir") Aísla las fallas del servicio para que no afecten a todo el sistema. Por ejemplo, el Servicio B está roto y otro servicio (el cliente del Servicio B) realiza una solicitud al Servicio B, lo que hace que agote su grupo de subprocesos y no pueda atender otras solicitudes (incluso si no son del Servicio B). (Nota: Puede encontrar una descripción más detallada del patrón, por ejemplo, aquí.)
Omitiré los detalles de implementación de estos patrones porque son fáciles de encontrar en documentación oficialY también quiero mostrar autenticación y autorización, que se analizarán en la siguiente parte del artículo.