Optimizar el autoescalado de pods en función de las métricas


En este tutorial se muestra cómo escalar automáticamente tus cargas de trabajo de Google Kubernetes Engine (GKE) en función de las métricas disponibles en Cloud Monitoring.

En este tutorial, puedes configurar el autoescalado en función de una de las siguientes métricas:

Pub/Sub

Retraso de Pub/Sub

Escala en función de una métrica externa que informa del número de mensajes no confirmados que quedan en una suscripción de Pub/Sub. De esta forma, se puede reducir la latencia antes de que se convierta en un problema, pero es posible que se utilicen relativamente más recursos que con el autoescalado basado en el uso de la CPU.

Métrica personalizada

Métrica de Prometheus personalizada

Escalar en función de una métrica personalizada definida por el usuario, exportada en formato Prometheus a través de Google Managed Prometheus. Tu métrica de Prometheus debe ser de tipo Gauge.

El autoescalado consiste básicamente en encontrar un equilibrio aceptable entre el coste y la latencia. Te recomendamos que pruebes a combinar estas métricas y otras para encontrar una política que te funcione.

Objetivos

En este tutorial se explican las siguientes tareas:

  1. Cómo implementar el adaptador de métricas personalizadas.
  2. Cómo exportar métricas desde el código de tu aplicación.
  3. Cómo ver las métricas en la interfaz de Cloud Monitoring.
  4. Cómo desplegar un recurso HorizontalPodAutoscaler (HPA) para escalar tu aplicación en función de las métricas de Cloud Monitoring.

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 las tareas que se describen en este documento, puedes evitar que se te siga facturando eliminando los recursos que has creado. Para obtener más información, consulta la sección Limpiar.

Antes de empezar

Sigue estos pasos para habilitar la API de Kubernetes Engine:
  1. Ve a la página de Kubernetes Engine en la Google Cloud consola.
  2. Crea o selecciona un proyecto.
  3. Espera a que la API y los servicios relacionados se habiliten. Este proceso puede tardar varios minutos.
  4. Verify that billing is enabled for your Google Cloud project.

Puedes seguir este tutorial con Cloud Shell, que viene preinstalado con las herramientas de línea de comandos gcloud y kubectl que se usan en este tutorial. Si usas Cloud Shell, no tienes que instalar estas herramientas de línea de comandos en tu estación de trabajo.

Para usar Cloud Shell, sigue estos pasos:

  1. Ve a la Google Cloud consola.
  2. Haz clic en el botón Activar Cloud Shell Activar botón Shell situado en la parte superior de la ventana de la consola Google Cloud .

    Se abrirá una sesión de Cloud Shell dentro de un nuevo marco en la parte inferior de la consola de Google Cloud y se mostrará en ella un mensaje de la línea de comandos.

    Sesión de Cloud Shell

Configurar un entorno

  1. Define la zona predeterminada de Google Cloud CLI:

    gcloud config set compute/zone zone
    

    Haz los cambios siguientes:

    • zone: elige la zona que esté más cerca de ti. Para obtener más información, consulta Regiones y zonas.
  2. Asigna a las variables de entorno PROJECT_ID y PROJECT_NUMBER el Google Cloud ID y el número de tu proyecto:

    export PROJECT_ID=project-id
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format 'get(projectNumber)')
    
  3. Define la zona predeterminada de Google Cloud CLI:

    gcloud config set project $PROJECT_ID
    
  4. Crea un clúster de GKE.

    Práctica recomendada:

    Para mejorar la seguridad al acceder a los servicios de Google Cloud , habilita Workload Identity Federation for GKE en tu clúster. Aunque esta página incluye ejemplos que usan el método antiguo (con la federación de Workload Identity para GKE inhabilitada), habilitarlo mejora la protección.

    Workload Identity

    Para crear un clúster con Workload Identity Federation for GKE habilitado, ejecuta el siguiente comando:

    gcloud container clusters create metrics-autoscaling --workload-pool=$PROJECT_ID.svc.id.goog
    

    Autenticación antigua

    Para crear un clúster con Workload Identity Federation para GKE inhabilitado, ejecuta el siguiente comando:

    gcloud container clusters create metrics-autoscaling
    

Desplegar el adaptador de métricas personalizadas

El adaptador de métricas personalizadas permite que tu clúster envíe y reciba métricas con Cloud Monitoring.

Pub/Sub

El procedimiento para instalar el adaptador de métricas personalizadas es diferente en los clústeres con o sin la federación de identidades de carga de trabajo para GKE habilitada. Selecciona la opción que coincida con la configuración que elegiste al crear el clúster.

Workload Identity

Conceda a su usuario la capacidad de crear los roles de autorización necesarios:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

Despliega el adaptador de métricas personalizadas en tu clúster:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

El adaptador usa la cuenta de servicio de custom-metrics-stackdriver-adapter Kubernetes en el espacio de nombres custom-metrics. Permite que esta cuenta de servicio lea métricas de Cloud Monitoring asignándole el rol Lector de Monitoring:

gcloud projects add-iam-policy-binding projects/$PROJECT_ID \
  --role roles/monitoring.viewer \
  --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapter

Autenticación antigua

Conceda a su usuario la capacidad de crear los roles de autorización necesarios:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

Despliega el adaptador de métricas personalizadas en tu clúster:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

Métrica personalizada

El procedimiento para instalar el adaptador de métricas personalizadas es diferente en los clústeres con o sin la federación de identidades de carga de trabajo para GKE habilitada. Selecciona la opción que coincida con la configuración que elegiste al crear el clúster.

Workload Identity

Conceda a su usuario la capacidad de crear los roles de autorización necesarios:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

Despliega el adaptador de métricas personalizadas en tu clúster:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

El adaptador usa la cuenta de servicio de custom-metrics-stackdriver-adapter Kubernetes en el espacio de nombres custom-metrics. Permite que esta cuenta de servicio lea métricas de Cloud Monitoring asignándole el rol Lector de Monitoring:

gcloud projects add-iam-policy-binding projects/$PROJECT_ID \
  --role roles/monitoring.viewer \
  --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapter

Autenticación antigua

Conceda a su usuario la capacidad de crear los roles de autorización necesarios:

kubectl create clusterrolebinding cluster-admin-binding \
    --clusterrole cluster-admin --user "$(gcloud config get-value account)"

Despliega el adaptador de métricas personalizadas en tu clúster:

kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml

Desplegar una aplicación con métricas

Descarga el repositorio que contiene el código de la aplicación de este tutorial:

Pub/Sub

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
cd kubernetes-engine-samples/databases/cloud-pubsub

Métrica personalizada

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
cd kubernetes-engine-samples/observability/custom-metrics-autoscaling/google-managed-prometheus

El repositorio contiene código que exporta métricas a Cloud Monitoring:

Pub/Sub

Esta aplicación sondea una suscripción de Pub/Sub para buscar mensajes nuevos y los confirma a medida que llegan. Cloud Monitoring recoge automáticamente las métricas de suscripción de Pub/Sub.

from google import auth
from google.cloud import pubsub_v1


def main():
    """Continuously pull messages from subsciption"""

    # read default project ID
    _, project_id = auth.default()
    subscription_id = 'echo-read'

    subscriber = pubsub_v1.SubscriberClient()
    subscription_path = subscriber.subscription_path(
        project_id, subscription_id)

    def callback(message: pubsub_v1.subscriber.message.Message) -> None:
        """Process received message"""
        print(f"Received message: ID={message.message_id} Data={message.data}")
        print(f"[{datetime.datetime.now()}] Processing: {message.message_id}")
        time.sleep(3)
        print(f"[{datetime.datetime.now()}] Processed: {message.message_id}")
        message.ack()

    streaming_pull_future = subscriber.subscribe(
        subscription_path, callback=callback)
    print(f"Pulling messages from {subscription_path}...")

    with subscriber:
        try:
            streaming_pull_future.result()
        except Exception as e:
            print(e)

Métrica personalizada

Esta aplicación responde a cualquier solicitud web a la ruta /metrics con una métrica de valor constante que usa el formato Prometheus.

metric := prometheus.NewGauge(
	prometheus.GaugeOpts{
		Name: *metricName,
		Help: "Custom metric",
	},
)
prometheus.MustRegister(metric)
metric.Set(float64(*metricValue))

http.Handle("/metrics", promhttp.Handler())
log.Printf("Starting to listen on :%d", *port)
err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)

El repositorio también contiene un manifiesto de Kubernetes para desplegar la aplicación en tu clúster. Un Deployment es un objeto de la API de Kubernetes que te permite ejecutar varias réplicas de pods distribuidas entre los nodos de un clúster:

Pub/Sub

El manifiesto es diferente en los clústeres en los que Workload Identity Federation for GKE está habilitado y en los que no. Selecciona la opción que coincida con la configuración que elegiste al crear el clúster.

Workload Identity

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      serviceAccountName: pubsub-sa
      containers:
      - name: subscriber
        image: us-docker.pkg.dev/google-samples/containers/gke/pubsub-sample:v2

Autenticación antigua

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pubsub
spec:
  selector:
    matchLabels:
      app: pubsub
  template:
    metadata:
      labels:
        app: pubsub
    spec:
      volumes:
      - name: google-cloud-key
        secret:
          secretName: pubsub-key
      containers:
      - name: subscriber
        image: us-docker.pkg.dev/google-samples/containers/gke/pubsub-sample:v2
        volumeMounts:
        - name: google-cloud-key
          mountPath: /var/secrets/google
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: /var/secrets/google/key.json

Métrica personalizada

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: custom-metrics-gmp
  name: custom-metrics-gmp
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      run: custom-metrics-gmp
  template:
    metadata:
      labels:
        run: custom-metrics-gmp
    spec:
      containers:
      # sample container generating custom metrics
      - name: prometheus-dummy-exporter
        image: us-docker.pkg.dev/google-samples/containers/gke/prometheus-dummy-exporter:v0.2.0
        command: ["./prometheus-dummy-exporter"]
        args:
        - --metric-name=custom_prometheus
        - --metric-value=40
        - --port=8080

Con el recurso PodMonitoring, Google Cloud Managed Service para Prometheus exporta las métricas de Prometheus a Cloud Monitoring:

apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
  name: "custom-metrics-exporter"
spec:
  selector:
    matchLabels:
      run: custom-metrics-gmp
  endpoints:
  - port: 8080
    path: /metrics
    interval: 15s

A partir de la versión 1.27 de GKE Standard o de la versión 1.25 de GKE Autopilot, Google Cloud Managed Service para Prometheus está habilitado. Para habilitar Google Cloud Managed Service para Prometheus en clústeres de versiones anteriores, consulta Habilitar la recogida gestionada.

Despliega la aplicación en tu clúster:

Pub/Sub

El procedimiento para desplegar tu aplicación varía en función de si los clústeres tienen habilitada la federación de identidades de carga de trabajo para GKE. Selecciona la opción que coincida con la configuración que elegiste al crear el clúster.

Workload Identity

  1. Habilita la API Pub/Sub en tu proyecto:

    gcloud services enable cloudresourcemanager.googleapis.com pubsub.googleapis.com
    
  2. Crea un tema y una suscripción de Pub/Sub:

    gcloud pubsub topics create echo
    gcloud pubsub subscriptions create echo-read --topic=echo
    
  3. Despliega la aplicación en tu clúster:

    kubectl apply -f deployment/pubsub-with-workload-identity.yaml
    
  4. Esta aplicación define una pubsub-sacuenta de servicio de Kubernetes. Asigna el rol Suscriptor de Pub/Sub para que la aplicación pueda publicar mensajes en el tema de Pub/Sub.

    gcloud projects add-iam-policy-binding projects/$PROJECT_ID \
      --role=roles/pubsub.subscriber \
      --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/default/sa/pubsub-sa
    

    El comando anterior usa un identificador de principal, que permite a la gestión de identidades y accesos hacer referencia directamente a una cuenta de servicio de Kubernetes.

    Práctica recomendada:

    Usa identificadores de Principal, pero ten en cuenta la limitación que se indica en la descripción de un método alternativo.

Autenticación antigua

  1. Habilita la API Pub/Sub en tu proyecto:

    gcloud services enable cloudresourcemanager.googleapis.com pubsub.googleapis.com
    
  2. Crea un tema y una suscripción de Pub/Sub:

    gcloud pubsub topics create echo
    gcloud pubsub subscriptions create echo-read --topic=echo
    
  3. Crea una cuenta de servicio con acceso a Pub/Sub:

    gcloud iam service-accounts create autoscaling-pubsub-sa
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member "serviceAccount:autoscaling-pubsub-sa@$PROJECT_ID.iam.gserviceaccount.com" \
      --role "roles/pubsub.subscriber"
    
  4. Descarga el archivo de clave de la cuenta de servicio:

    gcloud iam service-accounts keys create key.json \
      --iam-account autoscaling-pubsub-sa@$PROJECT_ID.iam.gserviceaccount.com
    
  5. Importa la clave de la cuenta de servicio a tu clúster como Secret:

    kubectl create secret generic pubsub-key --from-file=key.json=./key.json
    
  6. Despliega la aplicación en tu clúster:

    kubectl apply -f deployment/pubsub-with-secret.yaml
    

Métrica personalizada

kubectl apply -f custom-metrics-gmp.yaml

Después de esperar un momento a que se implemente la aplicación, todos los pods alcanzan el estado Ready:

Pub/Sub

kubectl get pods

Resultado:

NAME                     READY   STATUS    RESTARTS   AGE
pubsub-8cd995d7c-bdhqz   1/1     Running   0          58s

Métrica personalizada

kubectl get pods

Resultado:

NAME                                  READY   STATUS    RESTARTS   AGE
custom-metrics-gmp-865dffdff9-x2cg9   1/1     Running   0          49s

Ver métricas en Cloud Monitoring

Mientras se ejecuta tu aplicación, escribe tus métricas en Cloud Monitoring.

Para ver las métricas de un recurso monitorizado con el explorador de métricas, haz lo siguiente:

  1. En la Google Cloud consola, ve a la página  Explorador de métricas:

    Ve al explorador de métricas.

    Si usas la barra de búsqueda para encontrar esta página, selecciona el resultado cuya sección sea Monitorización.

  2. En el elemento Métrica, despliega el menú Seleccionar una métrica y, a continuación, selecciona un tipo de recurso y un tipo de métrica. Por ejemplo, para representar gráficamente la utilización de la CPU de una máquina virtual, haz lo siguiente:
    1. (Opcional) Para reducir las opciones del menú, introduce parte del nombre de la métrica en la barra de filtro. En este ejemplo, introduce utilization.
    2. En el menú Recursos activos, selecciona Instancia de VM.
    3. En el menú Categorías de métricas activas, selecciona Instancia.
    4. En el menú Métricas activas, selecciona Utilización de CPU y, a continuación, haz clic en Aplicar.
  3. Para filtrar las series temporales que se muestran, usa el elemento Filtro.

  4. Para combinar series temporales, usa los menús del elemento "Agregación". Por ejemplo, para mostrar la utilización de la CPU de tus VMs en función de su zona, define el primer menú como Media y el segundo como zona.

    Todas las series temporales se muestran cuando el primer menú del elemento Agregación está configurado como Sin agregar. Los ajustes predeterminados del elemento Agregación se determinan en función del tipo de métrica que hayas seleccionado.

El tipo de recurso y las métricas son los siguientes:

Pub/Sub

Explorador de métricas

Tipo de recurso: pubsub_subscription

Métrica: pubsub.googleapis.com/subscription/num_undelivered_messages

Métrica personalizada

Explorador de métricas

Tipo de recurso: prometheus_target

Métrica: prometheus.googleapis.com/custom_prometheus/gauge

En función de la métrica, es posible que aún no veas mucha actividad en el Explorador de métricas de Cloud Monitoring. No te sorprendas si tu métrica no se actualiza.

Crear un objeto HorizontalPodAutoscaler

Cuando veas tu métrica en Cloud Monitoring, podrás desplegar un HorizontalPodAutoscaler para cambiar el tamaño de tu despliegue en función de la métrica.

Pub/Sub

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: pubsub
spec:
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - external:
      metric:
       name: pubsub.googleapis.com|subscription|num_undelivered_messages
       selector:
         matchLabels:
           resource.labels.subscription_id: echo-read
      target:
        type: AverageValue
        averageValue: 2
    type: External
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: pubsub

Métrica personalizada

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: custom-metrics-gmp-hpa
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: custom-metrics-gmp
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: Pods
    pods:
      metric:
        name: prometheus.googleapis.com|custom_prometheus|gauge
      target:
        type: AverageValue
        averageValue: 20

Despliega el HorizontalPodAutoscaler en tu clúster:

Pub/Sub

kubectl apply -f deployment/pubsub-hpa.yaml

Métrica personalizada

kubectl apply -f custom-metrics-gmp-hpa.yaml

Generar carga

En algunas métricas, puede que tengas que generar carga para ver el autoescalado:

Pub/Sub

Publica 200 mensajes en el tema de Pub/Sub:

for i in {1..200}; do gcloud pubsub topics publish echo --message="Autoscaling #${i}"; done

Métrica personalizada

No aplicable: el código usado en este ejemplo exporta un valor constante de 40 para la métrica personalizada. El HorizontalPodAutoscaler se define con un valor objetivo de 20, por lo que intenta aumentar la escala de la implementación automáticamente.

Es posible que tengas que esperar un par de minutos para que HorizontalPodAutoscaler responda a los cambios en las métricas.

Observar el escalado horizontal de pods

Puedes consultar el número actual de réplicas de tu Deployment ejecutando el siguiente comando:

kubectl get deployments

Después de esperar un tiempo para que la métrica se propague, la implementación crea cinco pods para gestionar el trabajo pendiente.

También puedes inspeccionar el estado y la actividad reciente de HorizontalPodAutoscaler ejecutando el siguiente comando:

kubectl describe hpa

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.

Pub/Sub

  1. Elimina la suscripción y el tema Pub/Sub:

    gcloud pubsub subscriptions delete echo-read
    gcloud pubsub topics delete echo
    
  2. Elimina el clúster de GKE:

    gcloud container clusters delete metrics-autoscaling
    

Métrica personalizada

Elimina el clúster de GKE:

 gcloud container clusters delete metrics-autoscaling

Siguientes pasos