Cloud Service Mesh por ejemplo: implementaciones de versiones canary


En este instructivo, se explica un caso de uso común: lanzar una implementación de versiones canary con Cloud Service Mesh mediante las APIs de Istio.

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

Una implementación de versiones canary enruta un pequeño porcentaje de tráfico a una versión nueva de un microservicio y, luego, aumenta de forma gradual ese porcentaje, mientras que la versión antigua se retira de forma gradual y se retira. Si algo sale mal durante este proceso, el tráfico puede regresar a la versión anterior. Con Cloud Service Mesh, puedes enrutar el tráfico para asegurarte de que los servicios nuevos se ingresen de forma segura.

Puedes obtener más información sobre las pruebas de versiones canary en Implementación de aplicaciones y estrategias de prueba.

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. Establece el contexto actual de kubectl en el clúster en el que planeas implementar Online Boutique. El comando depende de si aprovisionaste 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 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. Para este instructivo, implementarás Online Boutique, una app de demo 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 de 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
    

    Un 2/2 en la columna READY indica que un Pod está en funcionamiento con un proxy 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 la puerta de enlace de entrada:

    kubectl get services -n GATEWAY_NAMESPACE
    

En la siguiente sección, se hace un recorrido por la IU de Cloud Service Mesh y se muestra cómo puedes ver tus métricas.

Ver tus servicios en la consola de Google Cloud

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

    Ir a los servicios de la edición Google Kubernetes Engine (GKE) Enterprise

  2. De forma predeterminada, verás tus servicios en la vista de Lista.

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

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

    Para expandir Servicios y ver las Solicitudes por segundo de cada uno de tus servicios, coloca el cursor sobre ellos.

  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.

En la siguiente sección, se explica cómo crear una v2 del servicio productcatalog.

Implementa la v2 de un servicio

  1. Para este instructivo, productcatalogservice-v2 introduce una latencia de 3 segundos en las solicitudes con el campo EXTRA_LATENCY. Esto simula una regresión en la versión nueva 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. 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. Usa DestinationRule para especificar los subconjuntos de un servicio. En este caso, hay un subconjunto para la v1 y, luego, un subconjunto separado para 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. Usa VirtualService para definir un pequeño porcentaje del tráfico que se dirigirá 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 dirige a la v1 de productcatalog y el 25%, a la 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.

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 y observa las implementaciones de productcatalogservice y productcatalogservice-v2.

  3. Regresa a la Vista de tabla.

  4. Haz clic en productcatalogservice en la tabla de servicios.

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

  6. 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 página, verás Solicitudes, Tasa de error y Métricas de latencia. Con Cloud Service Mesh, cada servicio tiene estas métricas descritas para proporcionarte métricas de observabilidad.

Lanzar o revertir a una versión

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

Lanzar

Una vez que estés conforme con el comportamiento de un servicio v2, puedes aumentar de forma incremental el porcentaje de tráfico dirigido al servicio v2. Con el tiempo, el tráfico se puede dirigir en su totalidad al servicio nuevo en el recurso VirtualService que creaste antes si quitas 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 v2 de productcatalogservice, haz lo siguiente:

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

Revertir

Si necesitas revertir al servicio v1, aplica destination-vs-v1.yaml de antes. Esto dirige 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

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 registraste tu clúster con una flota mediante gcloud container fleet memberships (en lugar de --enable-fleet o --fleet-project durante la creación del clúster), quita la membresía inactiva:

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

Si deseas mantener tu clúster configurado para Cloud Service Mesh, pero quitar la muestra de Online Boutique, haz lo siguiente:

  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?