Optimiza el ajuste de escala automático de Pods en función de las métricas

En este instructivo, 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 instructivo, puedes configurar el ajuste de escala automático en función de una de las siguientes métricas:

Pub/Sub

Tareas pendientes de Pub/Sub

Escala en función de una métrica externa que informa la cantidad de mensajes no confirmados restantes en una suscripción a Pub/Sub. Esta opción puede reducir la latencia de manera eficaz antes de que se convierta en un problema, pero puede usar relativamente más recursos que el ajuste de escala automático basado en el uso de CPU.

Métrica personalizada

Métrica personalizada de Prometheus

Escala en función de una métrica personalizada definida por el usuario, exportada en el formato Prometheus a través de Prometheus administrado por Google. Tu métrica de Prometheus debe ser del tipo Medidor.

El ajuste de escala automático consiste, en esencia, en encontrar un equilibrio aceptable entre el costo y la latencia. Recomendamos que pruebes con una combinación de estas métricas y otras para encontrar una política que se adapte a tus necesidades.

Implementa el adaptador de métricas personalizadas

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

Pub/Sub

El procedimiento para instalar el adaptador de métricas personalizadas difiere en función de si los clústeres tienen habilitada la federación de identidades para cargas de trabajo para GKE. Selecciona la opción que coincida con la configuración que elegiste cuando creaste el clúster.

Workload Identity

Otórgale al usuario la capacidad de crear los roles de autorización requeridos:

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

Implementa 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 Kubernetes custom-metrics-stackdriver-adapter en el espacio de nombres custom-metrics. Para permitir que esta cuenta de servicio lea las métricas de Cloud Monitoring, asigna el rol de Visualizador 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 heredada

Otórgale al usuario la capacidad de crear los roles de autorización requeridos:

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

Implementa 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 difiere en función de si los clústeres tienen habilitada la federación de identidades para cargas de trabajo para GKE. Selecciona la opción que coincida con la configuración que elegiste cuando creaste el clúster.

Workload Identity

Otórgale al usuario la capacidad de crear los roles de autorización requeridos:

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

Implementa 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 Kubernetes custom-metrics-stackdriver-adapter en el espacio de nombres custom-metrics. Para permitir que esta cuenta de servicio lea las métricas de Cloud Monitoring, asigna el rol de Visualizador 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 heredada

Otórgale al usuario la capacidad de crear los roles de autorización requeridos:

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

Implementa 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

Implementa una aplicación con métricas

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

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 tiene código con el que se exportan métricas a Cloud Monitoring:

Pub/Sub

Esta aplicación sondea una suscripción de Pub/Sub para los mensajes nuevos y los confirma a medida que llegan. Cloud Monitoring recopila de forma automática 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 para la ruta de acceso /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 implementar 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 que se distribuyen entre los nodos de un clúster:

Pub/Sub

El manifiesto difiere en función de si los clústeres tienen habilitada la federación de identidades para cargas de trabajo para GKE. Selecciona la opción que coincida con la configuración que elegiste cuando creaste 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 heredada

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

Google Cloud Managed Service para Prometheus está habilitado a partir de la versión 1.27 de GKE Standard y la versión 1.25 de GKE Autopilot. Para habilitar Google Cloud Managed Service para Prometheus en clústeres en versiones anteriores, consulta Habilita la recopilación administrada.

Implementa la aplicación en el clúster:

Pub/Sub

El procedimiento para implementar tu aplicación difiere en función de si los clústeres tienen habilitada la federación de identidades para cargas de trabajo para GKE. Selecciona la opción que coincida con la configuración que elegiste cuando creaste el clúster.

Workload Identity

  1. Habilita la API de 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. Implementa la aplicación en el clúster:

    kubectl apply -f deployment/pubsub-with-workload-identity.yaml
    
  4. Esta aplicación define una cuenta de servicio de Kubernetes pubsub-sa. Asigna el rol de 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 principal, que permite que IAM haga referencia directamente a una cuenta de servicio de Kubernetes.

    Práctica recomendada:

    Usa identificadores principales, pero ten en cuenta la limitación en la descripción de un método alternativo.

Autenticación heredada

  1. Habilita la API de 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 claves 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 al clúster como un Secreto:

    kubectl create secret generic pubsub-key --from-file=key.json=./key.json
    
  6. Implementa la aplicación en el 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 tendrán 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

Visualiza métricas en Cloud Monitoring

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

Para consultar las métricas de un recurso supervisado usando el Explorador de métricas, haz lo siguiente:

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

    Acceder al Explorador de métricas

    Si usas la barra de búsqueda para encontrar esta página, selecciona el resultado cuyo subtítulo es Monitoring.

  2. En el elemento Métrica, expande el menú Seleccionar una métrica y, luego, selecciona un tipo de recurso y uno de métrica. Por ejemplo, para graficar la utilización de CPU de una máquina virtual, haz lo siguiente:
    1. Para reducir las opciones del menú, puedes ingresar parte del nombre de la métrica en la Barra de filtros (opcional). En este ejemplo, ingresa 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 Uso de CPU y, luego, 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 el uso de CPU de tus VMs en función de su zona, configura el primer menú como Media y el segundo menú como zona.

    Todas las series temporales se muestran cuando el primer menú del elemento Agregación se establece en Sin agregación. La configuración predeterminada para el elemento Agregación se define según el tipo de métrica que elegiste.

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

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

Crea un objeto HorizontalPodAutoscaler

Cuando veas tu métrica en Cloud Monitoring, puedes implementar un HorizontalPodAutoscaler para cambiar el tamaño del Deployment 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

Implementa el HorizontalPodAutoscaler en el clúster:

Pub/Sub

kubectl apply -f deployment/pubsub-hpa.yaml

Métrica personalizada

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

Genera carga

En el caso de algunas métricas, es posible que debas generar carga para observar el ajuste de escala automático:

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 que se usa en este ejemplo exporta un valor constante de 40 para la métrica personalizada. El HorizontalPodAutoscaler se establece con un valor objetivo de 20, por lo que intenta escalar verticalmente el Deployment de forma automática.

Es posible que debas esperar unos minutos para que el HorizontalPodAutoscaler responda a los cambios de la métrica.

Observa el escalamiento vertical de HorizontalPodAutoscaler

Para verificar la cantidad actual de réplicas de tu implementación, ejecuta el siguiente comando:

kubectl get deployments

Después de darle tiempo a la métrica para que se propague, el Deployment crea cinco pods para controlar las tareas pendientes.

También puedes inspeccionar el estado y la actividad reciente de HorizontalPodAutoscaler si ejecutas lo siguiente:

kubectl describe hpa