Cloud Service Mesh mediante un ejemplo: implementaciones de versiones canary


En este instructivo, se explicará un caso de uso común que consiste en lanzar una implementación de versiones canary con Cloud Service Mesh.

¿Qué es una implementación de versiones canary?

Una implementación de versiones canary enruta un pequeño porcentaje del tráfico a una nueva versión de un microservicio. Luego, te permite lanzar de forma gradual a toda la base de usuarios, a la vez que elimina y retira la versión anterior. Si algo sale mal durante este proceso, se puede volver a cambiar el tráfico a la versión anterior. Con Cloud Service Mesh, puedes enrutar el tráfico para asegurarte de que se ingresen los servicios nuevos de forma segura.

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Cuando completes el instructivo puedes borrar los recursos que hayas creado para evitar que se te sigan cobrando. Para obtener más información, consulta Cómo realizar una limpieza.

Antes de comenzar

Implementa Online Boutique

  1. Configura el contexto actual de kubectl en el clúster en el que implementaste 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 muestra y la puerta de enlace de entrada:

    kubectl create namespace onlineboutique
    
  3. Etiqueta el espacio de nombres onlineboutique para insertar de forma automática los proxies de Envoy. Sigue los pasos sobre cómo habilitar la inserción automática de sidecar.

  4. Implementa la app de muestra. En este instructivo, implementarás Online Boutique, una app 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. Para agregar una etiqueta version=v1 a la implementación productcatalog, ejecuta el siguiente comando:

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

    Visualiza los servicios que implementaste:

    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 en funcionamiento, con un 2/2 en la columna READY. Esto indica que los Pods tienen un proxy de sidecar de Envoy insertado de forma correcta.

  6. Implementa tu VirtualService y DestinationRule para la v1 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 Ingress:

    kubectl get services -n GATEWAY_NAMESPACE
    

En la siguiente sección, exploraremos la IU de Cloud Service Mesh y te mostraremos cómo ver tus métricas.

Implementa y ve tus servicios en la consola de Google Cloud

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

    Ir a Servicios de GKE Enterprise

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

    La descripción general de la tabla te permite observar todos tus servicios y las métricas importantes con facilidad.

    Todas las cargas de trabajo de servicios

  3. En la esquina superior derecha, haz clic en Topología. Aquí puedes ver tus servicios y su interacción entre sí.

    Puedes expandir los servicios y ver las solicitudes por segundo para cada uno de tus servicios si colocas el cursor sobre ellos con el cursor.

    Topología de todas las cargas de trabajo de servicios

  4. Regresa a la Vista de tabla.

  5. En la Tabla de servicios, selecciona productcatalogservice. Esto te llevará a una descripción general de tu servicio.

  6. En el lado izquierdo de la pantalla, haz clic en Tráfico.

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

    Tráfico de svc de productcatalog

En la siguiente sección, se creará una v2 del servicio productcatalog.

Implementa la v2 de un servicio

  1. En este instructivo, productcatalogservice-v2 agregará una latencia de 3 segundos a 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. Verifica 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 enumerados.

  3. DestinationRule es la forma de especificar los subconjuntos de un servicio. En este caso, hay un subconjunto para la v1 y la v2 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

    Observa el campo labels. Las versiones de productcatalogservice se distinguen después de que VirtualService enruta el tráfico.

    Aplica DestinationRule:

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

Divide el tráfico entre v1 y v2

  1. Un VirtualService es la manera de ingresar un pequeño porcentaje del tráfico para dirigirlo a la v2 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 del subconjunto indica la versión, y el campo de peso indica la división porcentual del tráfico. El 75% del tráfico se dirigirá a v1 de productcatalog y el 25% a v2.

    Aplica VirtualService:

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

Si visitas la EXTERNAL_IP de la entrada del clúster, deberías notar que, periódicamente, el frontend es más lento para cargar.

En la siguiente sección, explorarás la división del tráfico en la consola de Google Cloud de GKE Enterprise.

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

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

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

    Expande la carga de trabajo productcatalogservice. Verás las implementaciones productcatalogservice y productcatalogservice-v2.

    Tipología de tráfico de productcatalog svc v1 v2

  3. Regresa a la Vista de tabla. Haz clic en productcatalogservice en la tabla de servicios. Regrese a Tráfico en la barra de navegación izquierda.

  4. Ten en cuenta que el tráfico entrante se divide entre v1 y v2 según el porcentaje especificado en el archivo VirtualService y que hay 2 cargas de trabajo del servicio productcatalog.

    En el lado derecho de la pantalla, verás Solicitudes, Tasa de error y Métricas de latencia. Con Cloud Service Mesh, cada servicio tendrá estas métricas descritas para proporcionarte la observabilidad.

    Tráfico de productcatalog svc v1 v2

Lanza o revierte a una versión

Después de observar las métricas durante una implementación de versiones canary, puedes lanzar al nuevo servicio o revertir al servicio anterior aprovechando el recurso VirtualService.

Lanzamiento

Una vez que estés satisfecho con el comportamiento de un servicio v2, aumenta de forma gradual el comportamiento del tráfico al servicio v2. Finalmente, el 100% del tráfico se puede dirigir al servicio nuevo.

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 v2 de productcatalogservice, haz lo siguiente:

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

Revertir

Si necesitas revertir al servicio v1, solo aplica el destination-vs-v1.yaml anterior. Esto dirigirá el tráfico solo a la v1 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 v1 de productcatalogservice, haz lo siguiente:

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

Limpia

Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.

Para evitar que se apliquen cargos continuos a tu cuenta de Google Cloud por los recursos que se usaron en este instructivo, puedes borrar el proyecto o borrar los recursos individuales.

Borra el proyecto

  1. En Cloud Shell, borra el proyecto:

    gcloud projects delete PROJECT_ID
    

Borra recursos

  • Si deseas evitar cargos adicionales, borra el clúster:

    gcloud container clusters delete  CLUSTER_NAME  \
    --project=PROJECT_ID \
    --zone=CLUSTER_LOCATION 
    
  • Si deseas conservar el clúster y quitar la muestra de Online Retail, realiza la siguiente acción:

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

      kubectl delete -f namespace onlineboutique
      

      Resultado esperado:

      namespace "onlineboutique" deleted
      
    2. Borra 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
      

¿Qué sigue?