Cloud Service Mesh mediante ejemplo: despliegues canary


En este tutorial, se explica un caso práctico habitual de lanzamiento de un despliegue canario con Cloud Service Mesh.

¿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, te permite lanzar gradualmente la nueva versión a toda la base de usuarios, mientras que la versión antigua se va retirando. Si algo va mal durante este proceso, el tráfico puede volver 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.

Costes

En este documento, se utilizan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costes basada en el uso previsto, utiliza la calculadora de precios.

Los usuarios nuevos Google Cloud pueden disfrutar de una prueba gratuita.

Cuando termines este tutorial, puedes evitar costes continuos eliminando los recursos que hayas creado. Para obtener más información, consulta la sección Limpiar.

Antes de empezar

Desplegar Online Boutique

  1. Define el contexto actual de kubectl en el clúster en el que has desplegado Online Boutique:

    gcloud container clusters get-credentials CLUSTER_NAME  \
    --project=PROJECT_ID \
    --zone=CLUSTER_LOCATION 
    
  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
    

    Para ver los servicios que has implementado, sigue estos pasos:

    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
    

    Todos los pods de tu aplicación deben estar operativos y tener un 2/2 en la columna READY. Esto indica que los pods tienen un proxy sidecar de Envoy insertado correctamente.

  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 recurso Ingress:

    kubectl get services -n GATEWAY_NAMESPACE
    

En la siguiente sección se hará un recorrido por la interfaz de usuario de Cloud Service Mesh y se mostrará cómo puedes ver tus métricas.

Desplegar y ver tus servicios en la Google Cloud consola

  1. En la consola, ve a la página Servicios empresariales de GKE. Google Cloud

    Ir a Servicios de GKE Enterprise

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

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

    Cargas de trabajo de todos los servicios

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

    Puedes ampliar los servicios y ver las solicitudes por segundo de cada uno de ellos colocando el cursor sobre ellos.

    Topología de cargas de trabajo de todos los servicios

  4. Vuelve a la vista de tabla.

  5. En la tabla de servicios, selecciona productcatalogservice. Se mostrará una vista general del 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.

    Tráfico de productcatalog svc

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 introducirá una latencia de 3 segundos en las solicitudes con el campo EXTRA_LATENCY.

    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. DestinationRule es la forma de 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. Una VirtualService es la forma de dirigir un pequeño porcentaje del tráfico a la versión 2 de la 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 dirigirá 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, veremos cómo se divide el tráfico en la consola de GKE Enterprise. Google Cloud

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

  1. Vuelve a la Google Cloud consola 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. Verás las implementaciones de productcatalogservice y productcatalogservice-v2.

    productcatalog svc v1 v2 traffic tpoplogy

  3. Vuelve a la vista de tabla. En la tabla de servicios, haz clic en productcatalogservice. Vuelva a Tráfico en la barra de navegación de la izquierda.

  4. 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 pantalla, verá las métricas de solicitudes, tasa de error y latencia. Con Cloud Service Mesh, cada servicio tendrá estas métricas definidas para proporcionarte la observabilidad.

    productcatalog svc v1 v2 traffic

Lanzar o restaurar una versión

Después de observar las métricas durante una implementación canary, puedes implementar el nuevo servicio o volver al antiguo mediante el recurso VirtualService.

Lanzamiento

Cuando estés satisfecho con el comportamiento de un servicio de la versión 2, aumenta gradualmente el tráfico a ese servicio. Finalmente, el tráfico se puede dirigir al 100% al nuevo servicio.

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

Restauración

Si necesitas volver al servicio de la versión 1, solo tienes que aplicar el destination-vs-v1.yaml anterior. De esta forma, el tráfico se dirigirá ú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

Limpieza

Para evitar que los recursos utilizados en este tutorial se cobren en tu cuenta de Google Cloud, elimina el proyecto que contiene los recursos o conserva el proyecto y elimina los recursos.

Para evitar que se sigan aplicando cargos a tu cuenta Google Cloud por los recursos utilizados en este tutorial, puedes eliminar el proyecto o los recursos.

Eliminar el proyecto

  1. En Cloud Shell, elimina el proyecto:

    gcloud projects delete PROJECT_ID
    

Eliminar los recursos

  • Si quieres evitar cargos adicionales, elimina el clúster:

    gcloud container clusters delete  CLUSTER_NAME  \
    --project=PROJECT_ID \
    --zone=CLUSTER_LOCATION 
    
  • Si quieres conservar tu clúster y eliminar la muestra de Online Boutique, sigue estos pasos:

    1. Elimina los espacios de nombres de la aplicación:

      kubectl delete -f namespace onlineboutique
      

      Resultado esperado:

      namespace "onlineboutique" deleted
      
    2. Elimina las entradas de servicio:

      kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/istio-manifests/frontend.yaml -n onlineboutique
      kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/istio-manifests/frontend-gateway.yaml -n onlineboutique
      

      Resultado esperado:

      serviceentry.networking.istio.io "allow-egress-googleapis" deleted
      serviceentry.networking.istio.io "allow-egress-google-metadata" deleted
      

Siguientes pasos