Volve aos microservizos con Istio. Parte 2

Volve aos microservizos con Istio. Parte 2

Nota. transl.: Primeira parte Esta serie dedicouse a presentar as capacidades de Istio e demostralas en acción. Agora falaremos de aspectos máis complexos da configuración e do uso desta malla de servizo e, en particular, do enrutamento finamente axustado e da xestión do tráfico de rede.

Lembrámosche tamén que o artigo usa configuracións (manifestos para Kubernetes e Istio) do repositorio istio-dominio.

xestión do tráfico

Con Istio, aparecen novas capacidades no clúster para proporcionar:

  • Enrutamento dinámico de solicitudes: lanzamentos canarios, probas A/B;
  • Equilibrio de carga: sinxelo e consistente, baseado en hash;
  • Recuperación tras caídas: tempo de espera, reintentos, interruptores;
  • Inserción de fallos: atrasos, solicitudes abandonadas, etc.

A medida que o artigo continúa, estas capacidades ilustraranse usando a aplicación seleccionada como exemplo e introduciranse novos conceptos ao longo do camiño. O primeiro concepto deste tipo será DestinationRules (é dicir, regras sobre o destinatario do tráfico/solicitudes - aprox. traduc.), coa axuda do cal activamos as probas A/B.

Probas A/B: DestinationRules na práctica

As probas A/B úsanse nos casos en que hai dúas versións dunha aplicación (normalmente son visualmente diferentes) e non estamos seguros ao 100% de cal mellorará a experiencia do usuario. Polo tanto, executamos as dúas versións á vez e recollemos métricas.

Para implementar a segunda versión do frontend, necesaria para demostrar as probas A/B, execute o seguinte comando:

$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions/sa-frontend-green created

O manifesto de despregamento para a versión verde difire en dous lugares:

  1. A imaxe está baseada nunha etiqueta diferente - istio-green,
  2. As vainas teñen unha etiqueta version: green.

Xa que ambos despregamentos teñen unha etiqueta app: sa-frontend, solicitudes encamiñadas polo servizo virtual sa-external-services para o servizo sa-frontend, será redirixido a todas as súas instancias e a carga distribuirase a través algoritmo round-robin, o que dará lugar á seguinte situación:

Volve aos microservizos con Istio. Parte 2
Non se atoparon os ficheiros solicitados

Estes ficheiros non se atoparon porque reciben un nome diferente nas diferentes versións da aplicación. Asegurémonos disto:

$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.c7071b22.css
/static/js/main.059f8e9c.js
$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.f87cd8c9.css
/static/js/main.f7659dbb.js

Significa iso index.html, solicitando unha versión de ficheiros estáticos, pode ser enviado polo equilibrador de carga a pods que teñan unha versión diferente, onde, por razóns obvias, tales ficheiros non existen. Polo tanto, para que a aplicación funcione, necesitamos establecer unha restrición: "a mesma versión da aplicación que serviu index.html debería atender solicitudes posteriores».

Chegaremos aí cun balance de carga consistente baseado en hash (Balanceamento de carga Hash consistente)... Neste caso as solicitudes do mesmo cliente envíanse á mesma instancia de backend, para o que se usa unha propiedade predefinida, por exemplo, unha cabeceira HTTP. Implementado usando DestinationRules.

Regras de destino

Despois Servizo Virtual enviou unha solicitude ao servizo desexado, mediante DestinationRules podemos definir políticas que se aplicarán ao tráfico destinado a instancias deste servizo:

Volve aos microservizos con Istio. Parte 2
Xestión do tráfico con recursos de Istio

Nota: O impacto dos recursos de Istio no tráfico da rede preséntase aquí dun xeito doado de entender. Para ser precisos, a decisión sobre a que instancia enviar a solicitude tómaa o Envoy no Ingress Gateway configurado no CRD.

Coas regras de destino, podemos configurar o equilibrio de carga para utilizar hash coherentes e garantir que a mesma instancia de servizo responde ao mesmo usuario. A seguinte configuración permítelle conseguir isto (destinationrule-sa-frontend.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-frontend
spec:
  host: sa-frontend
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpHeaderName: version   # 1

1 - xerarase hash en función do contido da cabeceira HTTP version.

Aplique a configuración co seguinte comando:

$ kubectl apply -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io/sa-frontend created

Agora executa o seguinte comando e asegúrate de obter os ficheiros correctos cando especifiques a cabeceira version:

$ curl --silent -H "version: yogo" http://$EXTERNAL_IP/ | tr '"' 'n' | grep main

Nota: Para engadir diferentes valores na cabeceira e probar os resultados directamente no navegador, pode usar esta extensión a Chrome (Ou con este para Firefox - aprox. trad.).

En xeral, DestinationRules ten máis capacidades na área do equilibrio de carga. Comprobe os detalles en documentación oficial.

Antes de estudar máis adiante VirtualService, eliminemos a "versión verde" da aplicación e a correspondente regra de dirección de tráfico executando os seguintes comandos:

$ kubectl delete -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions “sa-frontend-green” deleted
$ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io “sa-frontend” deleted

Mirroring: servizos virtuais na práctica

Sombreado ("blindaxe") ou Espello ("reflejo") utilízase nos casos nos que queremos probar un cambio na produción sen afectar aos usuarios finais: para iso, duplicamos as solicitudes ("espello") a unha segunda instancia onde se realizaron os cambios desexados e observamos as consecuencias. En pocas palabras, é cando o teu colega escolle o problema máis crítico e fai unha solicitude de extracción en forma de gran cantidade de lixo que ninguén pode revisalo.

Para probar este escenario en acción, creemos unha segunda instancia de SA-Logic con erros (buggy) executando o seguinte comando:

$ kubectl apply -f resource-manifests/kube/shadowing/sa-logic-service-buggy.yaml
deployment.extensions/sa-logic-buggy created

E agora imos executar o comando para asegurarnos de que todas as instancias con app=sa-logic Tamén teñen etiquetas coas versións correspondentes:

$ kubectl get pods -l app=sa-logic --show-labels
NAME                              READY   LABELS
sa-logic-568498cb4d-2sjwj         2/2     app=sa-logic,version=v1
sa-logic-568498cb4d-p4f8c         2/2     app=sa-logic,version=v1
sa-logic-buggy-76dff55847-2fl66   2/2     app=sa-logic,version=v2
sa-logic-buggy-76dff55847-kx8zz   2/2     app=sa-logic,version=v2

Servizo sa-logic apunta a vainas cunha etiqueta app=sa-logic, polo que todas as solicitudes repartiranse entre todas as instancias:

Volve aos microservizos con Istio. Parte 2

... pero queremos que as solicitudes se envíen a instancias v1 e que se reflejen en instancias v2:

Volve aos microservizos con Istio. Parte 2

Conseguirémolo mediante VirtualService en combinación con DestinationRule, onde as regras determinarán os subconxuntos e rutas do VirtualService a un subconxunto específico.

Definición de subconxuntos nas regras de destino

Subconxuntos (subconxuntos) están determinadas pola seguinte configuración (sa-logic-subsets-destinationrule.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-logic
spec:
  host: sa-logic    # 1
  subsets:
  - name: v1        # 2
    labels:
      version: v1   # 3
  - name: v2
    labels:
      version: v2

  1. Anfitrión (host) define que esta regra só se aplica aos casos en que a ruta vai cara ao servizo sa-logic;
  2. Títulos (name) os subconxuntos utilízanse cando se encamiñan a instancias de subconxuntos;
  3. Etiqueta (label) define os pares clave-valor que as instancias deben coincidir para formar parte do subconxunto.

Aplique a configuración co seguinte comando:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-destinationrule.yaml
destinationrule.networking.istio.io/sa-logic created

Agora que os subconxuntos están definidos, podemos avanzar e configurar o VirtualService para aplicar regras ás solicitudes a sa-logic para que:

  1. Dirixido a un subconxunto v1,
  2. Espello nun subconxunto v2.

O seguinte manifesto permíteche conseguir os teus plans (sa-logic-subsets-shadowing-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic          
  http:
  - route:
    - destination:
        host: sa-logic  
        subset: v1      
    mirror:             
      host: sa-logic     
      subset: v2

Non se necesita explicación aquí, así que vémolo en acción:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-shadowing-vs.yaml
virtualservice.networking.istio.io/sa-logic created

Engadimos a carga chamando ao seguinte comando:

$ while true; do curl -v http://$EXTERNAL_IP/sentiment 
    -H "Content-type: application/json" 
    -d '{"sentence": "I love yogobella"}'; 
    sleep .8; done

Vexamos os resultados en Grafana, onde podes ver que a versión con erros (buggy) produce fallos para ~60 % das solicitudes, pero ningún destes fallos afecta aos usuarios finais xa que son respondidos por un servizo en execución.

Volve aos microservizos con Istio. Parte 2
Respostas exitosas de diferentes versións do servizo sa-logic

Aquí vimos por primeira vez como se aplica VirtualService aos enviados dos nosos servizos: cando sa-web-app fai unha solicitude a sa-logic, pasa polo sidecar Envoy, que -a través de VirtualService- está configurado para dirixir a solicitude ao subconxunto v1 e reflectir a solicitude ao subconxunto v2 do servizo. sa-logic.

Seino, xa podes pensar que os servizos virtuais son sinxelos. Na seguinte sección, ampliaremos isto dicindo que tamén son realmente xeniais.

Lanzamentos de Canarias

Canary Deployment é o proceso de lanzar unha nova versión dunha aplicación a un pequeno número de usuarios. Úsase para asegurarse de que non hai problemas no lanzamento e só despois diso, xa confiando na súa calidade (de lanzamento), distribúelo a outros usuarios.оaudiencia maior.

Para demostrar os lanzamentos de canarias, seguiremos traballando cun subconxunto buggy у sa-logic.

Non perdamos o tempo en bagatelas e enviemos inmediatamente o 20% dos usuarios á versión con erros (isto representará o noso lanzamento canario) e o 80% restante ao servizo normal. Para iso, use o seguinte VirtualService (subconxuntos sa-logic-canary-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic    
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 80         # 1
    - destination: 
        host: sa-logic
        subset: v2
      weight: 20 # 1

1 é o peso (weight), que especifica a porcentaxe de solicitudes que se dirixirán a un destinatario ou a un subconxunto do destinatario.

Actualicemos a configuración anterior de VirtualService para sa-logic co seguinte comando:

$ kubectl apply -f resource-manifests/istio/canary/sa-logic-subsets-canary-vs.yaml
virtualservice.networking.istio.io/sa-logic configured

... e veremos inmediatamente que algunhas solicitudes dan lugar a fallos:

$ 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

Os servizos virtuais permiten lanzamentos canarios: neste caso, reducimos o impacto potencial dos problemas ao 20% da base de usuarios. Marabilloso! Agora, en todos os casos cando non esteamos seguros do noso código (noutras palabras, sempre...), podemos usar a creación de réplicas e os lanzamentos canarios.

Tempos mortos e reintentos

Pero os erros non sempre acaban no código. Na lista de "8 Conceptos erróneos sobre a computación distribuída"En primeiro lugar está a crenza errónea de que "a rede é fiable". En realidade a rede non fiable, e por iso necesitamos tempo morto (tempos mortos) e reintentos (reintentos).

Para a demostración seguiremos usando a mesma versión do problema sa-logic (buggy), e simularemos a falta de fiabilidade da rede con fallos aleatorios.

Permite que o noso servizo con erros teña 1/3 de posibilidades de tardar demasiado en responder, 1/3 de posibilidades de rematar cun erro interno do servidor e 1/3 de posibilidades de devolver a páxina con éxito.

Para mitigar o impacto deste tipo de problemas e mellorar a vida dos usuarios, podemos:

  1. engade un tempo de espera se o servizo tarda máis de 8 segundos en responder,
  2. ténteo de novo se a solicitude falla.

Para a implementación, utilizaremos a seguinte definición de recurso (sa-logic-retries-timeouts-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 50
    - destination: 
        host: sa-logic
        subset: v2
      weight: 50
    timeout: 8s           # 1
    retries:
      attempts: 3         # 2
      perTryTimeout: 3s # 3

  1. O tempo de espera para a solicitude establécese en 8 segundos;
  2. As solicitudes reinténtanse 3 veces;
  3. E cada intento considérase infructuoso se o tempo de resposta supera os 3 segundos.

Trátase dunha optimización porque o usuario non terá que esperar máis de 8 segundos e faremos tres novos intentos para obter resposta en caso de fallos, aumentando as posibilidades de resposta satisfactoria.

Aplique a configuración actualizada co seguinte comando:

$ kubectl apply -f resource-manifests/istio/retries/sa-logic-retries-timeouts-vs.yaml
virtualservice.networking.istio.io/sa-logic configured

E comproba nos gráficos de Grafana que o número de respostas exitosas aumentou arriba:

Volve aos microservizos con Istio. Parte 2
Melloras nas estatísticas de resposta exitosa despois de engadir tempo de espera e reintentos

Antes de pasar á seguinte sección (ou mellor dito, á seguinte parte do artigo, porque neste xa non haberá máis experimentos prácticos - aprox. trad.), borrar sa-logic-buggy e VirtualService executando os seguintes comandos:

$ kubectl delete deployment sa-logic-buggy
deployment.extensions “sa-logic-buggy” deleted
$ kubectl delete virtualservice sa-logic
virtualservice.networking.istio.io “sa-logic” deleted

Patróns de interruptores e mamparos

Estamos a falar de dous patróns importantes na arquitectura de microservizos que che permiten lograr a autorecuperación (autocuración) Servizos.

Circuíto break ("interruptor") úsase para finalizar as solicitudes que chegan a unha instancia dun servizo que se considera insalubre e restauralas mentres as solicitudes dos clientes son redirixidas a instancias saudables dese servizo (o que aumenta a porcentaxe de respostas exitosas). (Nota: pódese atopar unha descrición máis detallada do patrón, por exemplo, aquí.)

Mampara ("partición") illa os fallos do servizo de afectar a todo o sistema. Por exemplo, o servizo B está roto e outro servizo (o cliente do servizo B) fai unha solicitude ao servizo B, o que fai que esgote o seu grupo de fíos e non poida atender outras solicitudes (aínda que non sexan do servizo B). (Nota: pódese atopar unha descrición máis detallada do patrón, por exemplo, aquí.)

Omitirei os detalles de implementación destes patróns porque son fáciles de atopar documentación oficial, e tamén quero mostrar autenticación e autorización, que se comentarán na seguinte parte do artigo.

PS do tradutor

Lea tamén no noso blog:

Fonte: www.habr.com

Engadir un comentario