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.

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 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.

    Consulta el Destination Rule que has creado.

      kubectl get destinationrules -n onlineboutique
    

    Resultado esperado:

      NAME                    HOST                    AGE
      productcatalogservice   productcatalogservice   2m
    

    Consulta el VirtualService que has creado.

      kubectl get virtualservices -n onlineboutique
    

    Resultado esperado:

      NAME                    GATEWAYS   HOSTS                       AGE
      productcatalogservice              ["productcatalogservice"]   2m
    
  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 dirigirá a una vista general 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. Use 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

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

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 has registrado tu clúster en la flota mediante gcloud container fleet memberships (en lugar de --enable-fleet o --fleet-project durante la creación del clúster), elimina la pertenencia obsoleta:

gcloud container fleet memberships delete  MEMBERSHIP  \
  --project=PROJECT_ID

Si quieres mantener tu clúster configurado para Cloud Service Mesh, pero eliminar la muestra 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