Cloud Service Mesh mediante ejemplo: implementaciones canary

En este tutorial, se explica un caso práctico habitual: implementar una versión canary con Cloud Service Mesh mediante las APIs de Istio.

¿Qué es un despliegue canary?

Un despliegue canary dirige un pequeño porcentaje del tráfico a una nueva versión de un microservicio y, a continuación, aumenta gradualmente ese porcentaje mientras elimina la versión antigua. Si algo va mal durante este proceso, el tráfico se puede volver a cambiar a la versión anterior. Con Cloud Service Mesh, puedes enrutar el tráfico para asegurarte de que los nuevos servicios se introduzcan de forma segura.

Desplegar Online Boutique

  1. Define el contexto actual de kubectl en el clúster en el que quieras implementar Online Boutique. El comando depende de si has aprovisionado Cloud Service Mesh en un clúster de GKE o en un clúster de Kubernetes fuera de GKE:

    GKE en Google Cloud

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    

    GKE fuera de Google Cloud

    kubectl config use-context CLUSTER_NAME 
    
  2. Crea el espacio de nombres para la aplicación de ejemplo y la pasarela de entrada:

    kubectl create namespace onlineboutique
    
  3. Etiqueta el espacio de nombres onlineboutique para insertar automáticamente proxies de Envoy. Sigue los pasos para habilitar la inyección automática de sidecar.

  4. Despliega la aplicación de ejemplo. En este tutorial, desplegarás Online Boutique, una aplicación de demostración de microservicios.

    kubectl apply \
    -n onlineboutique \
    -f https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-service-mesh-samples/main/docs/shared/online-boutique/kubernetes-manifests.yaml
    
  5. Añade una etiqueta version=v1 al despliegue productcatalog ejecutando el siguiente comando:

    kubectl patch deployments/productcatalogservice -p '{"spec":{"template":{"metadata":{"labels":{"version":"v1"}}}}}' \
    -n onlineboutique
    

    Consulta los servicios que has implementado:

    kubectl get pods -n onlineboutique
    

    Resultado esperado:

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-m84m6               2/2     Running   0          2m7s
    cartservice-c77f6b866-m67vd              2/2     Running   0          2m8s
    checkoutservice-654c47f4b6-hqtqr         2/2     Running   0          2m10s
    currencyservice-59bc889674-jhk8z         2/2     Running   0          2m8s
    emailservice-5b9fff7cb8-8nqwz            2/2     Running   0          2m10s
    frontend-77b88cc7cb-mr4rp                2/2     Running   0          2m9s
    loadgenerator-6958f5bc8b-55q7w           2/2     Running   0          2m8s
    paymentservice-68dd9755bb-2jmb7          2/2     Running   0          2m9s
    productcatalogservice-84f95c95ff-c5kl6   2/2     Running   0          114s
    recommendationservice-64dc9dfbc8-xfs2t   2/2     Running   0          2m9s
    redis-cart-5b569cd47-cc2qd               2/2     Running   0          2m7s
    shippingservice-5488d5b6cb-lfhtt         2/2     Running   0          2m7s
    

    El símbolo 2/2 en la columna READY indica que un pod está en funcionamiento y que se ha insertado correctamente un proxy de Envoy.

  6. Implementa tu VirtualService y DestinationRule para la versión 1 de productcatalog:

     kubectl apply -f destination-vs-v1.yaml -n onlineboutique
    
    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: productcatalogservice
    spec:
      host: productcatalogservice
      subsets:
      - labels:
          version: v1
        name: v1
    ---
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: productcatalogservice
    spec:
      hosts:
      - productcatalogservice
      http:
      - route:
        - destination:
            host: productcatalogservice
            subset: v1

    Ten en cuenta que solo v1 está presente en los recursos.

  7. Visita la aplicación en tu navegador con la dirección IP externa de tu pasarela de entrada:

    kubectl get services -n GATEWAY_NAMESPACE
    

En la siguiente sección se muestra la interfaz de usuario de Cloud Service Mesh y cómo puedes ver tus métricas.

Ver tus servicios en la consola de Google Cloud

  1. En la consola, ve a la página Servicios de la edición Enterprise de Google Kubernetes Engine (GKE). Google Cloud

    Ve a Servicios de la edición Enterprise de Google Kubernetes Engine (GKE).

  2. De forma predeterminada, los servicios se muestran en la vista Lista.

    La vista general de la tabla le permite observar todos sus servicios, así como métricas importantes de un vistazo.

  3. En la parte superior derecha, haz clic en Topología. Aquí puedes ver tus servicios y cómo interactúan entre sí.

    Puedes desplegar Servicios y ver las Solicitudes por segundo de cada uno de tus servicios colocando el cursor sobre ellos.

  4. Vuelve a la vista de tabla.

  5. En la tabla de servicios, selecciona productcatalogservice. Se te mostrará un resumen de tu servicio.

  6. En la parte izquierda de la pantalla, haz clic en Tráfico.

  7. Asegúrate de que el 100% del tráfico entrante a productcatalogservice se dirija al servicio de carga de trabajo.

En la siguiente sección se explica cómo crear la versión 2 del servicio productcatalog.

Desplegar la versión 2 de un servicio

  1. En este tutorial, productcatalogservice-v2 introduce una latencia de 3 segundos en las solicitudes con el campo EXTRA_LATENCY. De esta forma, se simula una regresión en la nueva versión del servicio.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: productcatalogservice-v2
    spec:
      selector:
        matchLabels:
          app: productcatalogservice
      template:
        metadata:
          labels:
            app: productcatalogservice
            version: v2
        spec:
          containers:
          - env:
            - name: PORT
              value: '3550'
            - name: EXTRA_LATENCY
              value: 3s
            name: server
            image: gcr.io/google-samples/microservices-demo/productcatalogservice:v0.3.6
            livenessProbe:
              exec:
                command: ["/bin/grpc_health_probe", "-addr=:3550"]
            ports:
            - containerPort: 3550
            readinessProbe:
              exec:
                command: ["/bin/grpc_health_probe", "-addr=:3550"]
            resources:
              limits:
                cpu: 200m
                memory: 128Mi
              requests:
                cpu: 100m
                memory: 64Mi
          terminationGracePeriodSeconds: 5

    Aplica este recurso al espacio de nombres onlineboutique.

    kubectl apply -f productcatalog-v2.yaml -n onlineboutique
    
  2. Comprueba los pods de tu aplicación.

    kubectl get pods -n onlineboutique
    

    Resultado esperado:

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-8wqfd                  2/2     Running   0          25h
    cartservice-c77f6b866-7jwcr                 2/2     Running   0          25h
    checkoutservice-654c47f4b6-n8c6x            2/2     Running   0          25h
    currencyservice-59bc889674-l5xw2            2/2     Running   0          25h
    emailservice-5b9fff7cb8-jjr89               2/2     Running   0          25h
    frontend-77b88cc7cb-bwtk4                   2/2     Running   0          25h
    loadgenerator-6958f5bc8b-lqmnw              2/2     Running   0          25h
    paymentservice-68dd9755bb-dckrj             2/2     Running   0          25h
    productcatalogservice-84f95c95ff-ddhjv      2/2     Running   0          25h
    productcatalogservice-v2-6df4cf5475-9lwjb   2/2     Running   0          8s
    recommendationservice-64dc9dfbc8-7s7cx      2/2     Running   0          25h
    redis-cart-5b569cd47-vw7lw                  2/2     Running   0          25h
    shippingservice-5488d5b6cb-dj5gd            2/2     Running   0          25h
    

    Ten en cuenta que ahora hay dos productcatalogservices.

  3. Usa DestinationRule para especificar los subconjuntos de un servicio. En este caso, hay un subconjunto para la versión 1 y otro para la versión 2 de productcatalogservice.

    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: productcatalogservice
    spec:
      host: productcatalogservice
      subsets:
      - labels:
          version: v1
        name: v1
      - labels:
          version: v2
        name: v2

    Fíjate en el campo labels. Las versiones de productcatalogservice se distinguen después de que el tráfico se haya enrutado por el VirtualService.

    Aplica la DestinationRule:

    kubectl apply -f destination-v1-v2.yaml -n onlineboutique
    

Dividir el tráfico entre las versiones 1 y 2

  1. Usa VirtualService para definir un pequeño porcentaje del tráfico que se dirigirá a la versión 2 de productcatalogservice.

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: productcatalogservice
    spec:
      hosts:
      - productcatalogservice
      http:
      - route:
        - destination:
            host: productcatalogservice
            subset: v1
          weight: 75
        - destination:
            host: productcatalogservice
            subset: v2
          weight: 25

    El campo de subconjunto indica la versión, y el campo de asignación porcentual indica el porcentaje de división del tráfico. El 75% del tráfico se dirige a la versión 1 de productcatalog y el 25% a la versión 2.

    Aplica la VirtualService:

    kubectl apply -f vs-split-traffic.yaml -n onlineboutique
    

Si visitas el EXTERNAL_IP del ingreso del clúster, deberías observar que, periódicamente, el frontend tarda más en cargarse.

En la siguiente sección, se explica cómo consultar la división del tráfico en la Google Cloud consola.

Observa la división del tráfico en la consola Google Cloud .

  1. Vuelve a la consola Google Cloud y ve a la página Servicios de GKE Enterprise. Ir a Servicios de GKE Enterprise

  2. En la parte superior derecha, haz clic en Topología.

    Despliega la carga de trabajo productcatalogservice y anota los despliegues productcatalogservice y productcatalogservice-v2.

  3. Vuelve a la vista de tabla.

  4. En la tabla de servicios, haz clic en productcatalogservice.

  5. Vuelva a Tráfico en la barra de navegación de la izquierda.

  6. Ten en cuenta que el tráfico entrante se divide entre las versiones 1 y 2 según el porcentaje especificado en el archivo VirtualService y que hay dos cargas de trabajo del servicio productcatalog.

    En la parte derecha de la página, verá Solicitudes, Tasa de errores y Métricas de latencia. Con Cloud Service Mesh, cada servicio tiene estas métricas definidas para proporcionarte métricas de observabilidad.

Lanzar o restaurar una versión

Después de observar las métricas durante una implementación canary, puedes completar la implementación de la nueva versión del servicio o volver a la versión original del servicio mediante el recurso VirtualService.

Lanzamiento

Cuando estés satisfecho con el comportamiento de un servicio de la versión 2, puedes aumentar gradualmente el porcentaje de tráfico dirigido al servicio de la versión 2. Finalmente, puedes dirigir el 100% del tráfico al nuevo servicio en el recurso VirtualService que has creado anteriormente. Para ello, elimina la división del tráfico de ese recurso.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: productcatalogservice
spec:
  hosts:
  - productcatalogservice
  http:
  - route:
    - destination:
        host: productcatalogservice
        subset: v2

Para dirigir todo el tráfico a la versión 2 de productcatalogservice, haz lo siguiente:

kubectl apply -f vs-v2.yaml -n onlineboutique

Restaurar

Si necesitas volver al servicio de la versión 1, aplica el destination-vs-v1.yaml anterior. De esta forma, el tráfico se dirige únicamente a la versión 1 de productcatalogservice.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: productcatalogservice
spec:
  hosts:
  - productcatalogservice
  http:
  - route:
    - destination:
        host: productcatalogservice
        subset: v1

Para dirigir todo el tráfico a la versión 1 de productcatalogservice, haz lo siguiente:

kubectl apply -f vs-v1.yaml -n onlineboutique