Cómo escalar cargas de trabajo de GKE a cero y desde cero con HPA

En este instructivo, se muestra cómo optimizar el uso de recursos en Google Kubernetes Engine (GKE) configurando cargas de trabajo para que se escale automáticamente a cero réplicas cuando estén inactivas y se vuelvan a escalar a medida que aumente la demanda. Este enfoque integra el escalador automático horizontal de Pods (HPA) con la infraestructura de ajuste de escala automático administrada de GKE para administrar el ajuste de escala en función de métricas externas.

Configura tu implementación para que se escale a cero. Para ello, establece el valor del campo minReplicas en 0 y define una métrica con el tipo External o Object en tu manifiesto de HPA. GKE supervisa estas métricas a través del recurso personalizado AutoscalingMetric, que ayuda a garantizar una administración eficiente de los recursos para tus aplicaciones.

Con esta configuración, no necesitas usar adaptadores de métricas de terceros, como KEDA, para ajustar la escala de las cargas de trabajo de GKE. Esta solución administra la transferencia de métricas y las recomendaciones de ajuste de escala directamente en el plano de control de GKE, lo que reduce la sobrecarga de administración del clúster.

En este instructivo, implementarás una aplicación de trabajador asíncrono de ejemplo que procesa mensajes de una cola de Pub/Sub. Configuras un escalador automático horizontal de Pods para supervisar la profundidad de la cola (pubsub.googleapis.com:num_undelivered_messages) con un recurso personalizado AutoscalingMetric:

  • Cuando llegan mensajes a la suscripción: GKE escala verticalmente los Pods de trabajador para procesar la cola.
  • Cuando la cola está vacía: GKE reduce automáticamente la escala de la Deployment de trabajadores a cero réplicas.

Este instructivo está dirigido a desarrolladores de aplicaciones, administradores y operadores de plataformas, y profesionales de DevOps que deseen optimizar el uso de recursos en GKE escalando las cargas de trabajo a cero cuando estén inactivas.

Consideraciones

Antes de configurar las cargas de trabajo para que se escale a cero, revisa las siguientes consideraciones:

  • Para escalar cargas de trabajo a cero y desde cero con el HPA, el plano de control y los nodos del clúster de GKE deben ejecutar la versión 1.37 o una posterior en los clústeres nuevos y en los existentes actualizados. Si usas un clúster existente, verifica su versión o actualiza el clúster o sus nodos a la versión 1.37 o posterior.
  • Tu manifiesto de HPA debe usar la configuración de apiVersion: autoscaling/v2 para admitir el parámetro de configuración de minReplicas: 0 y las métricas externas.
  • Antes de cambiar a una versión anterior los grupos de nodos a una versión anterior a la 1.37, actualiza todos los manifiestos de HPA configurados para escalar a cero y desde cero estableciendo el campo minReplicas en 1 o un valor mayor. Las versiones anteriores a la 1.37 no admiten el parámetro de configuración minReplicas: 0, lo que puede hacer que las cargas de trabajo permanezcan atascadas en cero réplicas.
  • Debes configurar al menos una métrica de External o Object (como la profundidad de la cola) en tu Horizontal Pod Autoscaler. GKE no puede recopilar métricas de CPU o memoria (Resource) cuando una carga de trabajo tiene cero Pods, por lo que las métricas de recursos por sí solas no pueden activar el ajuste de escala vertical desde cero.
  • Los objetos AutoscalingMetric, HorizontalPodAutoscaler y Deployment de destino deben residir en el mismo espacio de nombres de Kubernetes.

Antes de comenzar

  1. Instala Google Cloud CLI.

  2. Configura gcloud CLI para usar tu identidad federada.

    Para obtener más información, consulta Accede a la gcloud CLI con tu identidad federada.

  3. Para inicializar gcloud CLI, ejecuta el siguiente comando:

    gcloud init
  4. Crea o selecciona un Google Cloud proyecto.

    Roles necesarios para seleccionar o crear un proyecto

    • Selecciona un proyecto: Para seleccionar un proyecto, no se requiere un rol de IAM específico. Puedes seleccionar cualquier proyecto en el que se te haya otorgado un rol.
    • Crear un proyecto: Para crear un proyecto, necesitas el rol de Creador de proyectos (roles/resourcemanager.projectCreator), que contiene el permiso resourcemanager.projects.create. Obtén más información para otorgar roles.
    • Crea un proyecto de Google Cloud :

      gcloud projects create PROJECT_ID

      Reemplaza PROJECT_ID por un nombre para el proyecto Google Cloud que estás creando.

    • Selecciona el proyecto Google Cloud que creaste:

      gcloud config set project PROJECT_ID

      Reemplaza PROJECT_ID por el nombre de tu proyecto de Google Cloud .

  5. Verifica que la facturación esté habilitada para tu proyecto de Google Cloud .

  6. Habilita las APIs de GKE y Pub/Sub:

    Roles necesarios para habilitar las APIs

    Para habilitar APIs, necesitas el permiso serviceusage.services.enable. Si creaste el proyecto, es probable que ya tengas este permiso a través del rol de propietario (roles/owner). De lo contrario, puedes obtener este permiso a través del rol de administrador de Service Usage (roles/serviceusage.serviceUsageAdmin). Obtén más información para otorgar roles.

    gcloud services enable container.googleapis.com pubsub.googleapis.com

Roles obligatorios

Si quieres obtener los permisos que necesitas para completar este instructivo, pídele a tu administrador que te otorgue los siguientes roles de IAM en tu proyecto:

Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

También puedes obtener los permisos necesarios a través de roles personalizados o cualquier otro rol predefinido.

Configura tu entorno

Para mayor simplicidad, los comandos de este instructivo crean todos los recursos (el clúster de GKE, y el tema y la suscripción de Pub/Sub) dentro de un solo proyecto Google Cloud (PROJECT_ID).

Para configurar tu entorno, sigue estos pasos:

  1. Establece las variables de entorno:

    export PROJECT_ID=PROJECT_ID
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format 'get(projectNumber)')
    export LOCATION=LOCATION
    

    Reemplaza lo siguiente:

    • PROJECT_ID: Es el Google Cloud ID del proyecto.
    • LOCATION: La región o zona en la que deseas crear tu clúster de GKE, como us-central1. Para los clústeres de Autopilot, especifica una región.
  2. Crea un clúster de GKE que ejecute la versión 1.37 o posterior con la Workload Identity Federation for GKE habilitada. Te recomendamos que uses un clúster de Autopilot para una experiencia de Kubernetes completamente administrada y para maximizar el ahorro de costos cuando las cargas de trabajo se reducen a cero. Para elegir el modo de operación que se adapte mejor a tus cargas de trabajo, consulta Elige un modo de operación de GKE:

    Autopilot

    Crea un clúster de Autopilot:

    gcloud container clusters create-auto scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    

    Workload Identity Federation for GKE está habilitada de forma predeterminada en los clústeres de Autopilot.

    Estándar

    Crea un clúster de Standard con la federación de identidades para cargas de trabajo para GKE habilitada:

    gcloud container clusters create scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION} \
        --workload-pool=${PROJECT_ID}.
    
  3. Configura kubectl para comunicarse con tu clúster:

    gcloud container clusters get-credentials scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    

Crea recursos de Pub/Sub

En este instructivo, se usa la profundidad de la cola de Pub/Sub como ejemplo de fuente de métricas externas.

Para crear un tema y una suscripción de Pub/Sub, sigue estos pasos:

  1. Crea un tema de Pub/Sub:

    gcloud pubsub topics create my-worker-topic \
        --project=${PROJECT_ID}
    
  2. Crea una suscripción adjunta al tema:

    gcloud pubsub subscriptions create my-worker-subscription \
        --topic=my-worker-topic \
        --project=${PROJECT_ID}
    

Configura la federación de identidades para cargas de trabajo para GKE

Configura Workload Identity Federation for GKE para permitir que tu aplicación de trabajador se autentique con las APIs de Google Cloud y consuma mensajes de Pub/Sub.

GKE controla automáticamente la autenticación con Cloud Monitoring para los recursos de AutoscalingMetric en el mismo proyecto. Para obtener más información sobre cómo definir métricas para el ajuste de escala automático, consulta Cómo recuperar métricas externas o personalizadas de Cloud Monitoring.

Para configurar Workload Identity Federation for GKE para tu carga de trabajo de trabajador, sigue estos pasos:

  1. Crea una cuenta de servicio de Kubernetes para tu aplicación de trabajador en el espacio de nombres default:

    kubectl create serviceaccount async-worker-sa \
        --namespace default
    
  2. Otorga el rol roles/pubsub.subscriber a la cuenta de servicio de Kubernetes para que la aplicación pueda recibir mensajes de tu suscripción a 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}./subject/ns/default/sa/async-worker-sa
    

Si deseas obtener más información, consulta Configura las aplicaciones para usar la federación de identidades para cargas de trabajo para GKE.

Crea la implementación de ejemplo

Antes de poder crear un objeto HPA, debes crear la carga de trabajo que supervisará.

Para crear el Deployment de ejemplo, sigue estos pasos:

  1. Guarda el siguiente manifiesto como async-worker.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: async-worker
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: async-worker
      template:
        metadata:
          labels:
            app: async-worker
        spec:
          containers:
          - name: async-worker
            image: nginx:latest
            ports:
            - containerPort: 80
            resources:
              limits:
                memory: 100Mi
              requests:
                cpu: 50m
                memory: 100Mi
    
  2. Aplica la Deployment de async-worker.yaml:

    kubectl apply -f async-worker.yaml
    

Configura una carga de trabajo para que se escale a cero y desde cero

En esta sección, configurarás la Deployment de async-worker para que se reduzca la escala verticalmente a cero cuando la cola de Pub/Sub esté vacía y vuelva a aumentar a medida que lleguen mensajes nuevos.

Crea el recurso AutoscalingMetric

Para definir el indicador externo que supervisa GKE, crea el recurso personalizado AutoscalingMetric. En el siguiente manifiesto de ejemplo, la métrica consulta Cloud Monitoring para obtener la cantidad de mensajes de Pub/Sub no entregados en la suscripción my-worker-subscription.

Para crear el recurso AutoscalingMetric, sigue estos pasos:

  1. Guarda el siguiente manifiesto como el archivo pubsub-metric.yaml:

    apiVersion: autoscaling.gke.io/v1beta1
    kind: AutoscalingMetric
    metadata:
      name: pubsub-queue-depth
      namespace: default
    spec:
      metrics:
      - promql:
          name: pubsub-undelivered
          query: >
              {
                "pubsub.googleapis.com/subscription/num_undelivered_messages",
                subscription_id="my-worker-subscription"
              }
    
  2. Aplica el manifiesto pubsub-metric.yaml:

    kubectl apply -f pubsub-metric.yaml
    
  3. Verifica el estado de la métrica y recupera su identificador:

    kubectl describe autoscalingmetric pubsub-queue-depth
    

    En la sección Status del resultado, verifica que no se muestre ningún error y anota el valor de Hpa Name que se encuentra en el formato autoscaling.gke.io|CUSTOM_RESOURCE_NAME|METRIC_NAME. Harás referencia a este identificador de métrica externa cuando crees el objeto HorizontalPodAutoscaler en la siguiente sección. Si la sección Status informa errores de configuración o no se recuperan las métricas según lo esperado, consulta Soluciona problemas relacionados con las métricas que se recuperan para el ajuste de escala automático.

Configura el escalador automático horizontal de Pods

Para configurar el comportamiento del ajuste de escala automático, crea un recurso HorizontalPodAutoscaler que apunte al Deployment.

Para configurar el escalador automático horizontal de Pods, sigue estos pasos:

  1. Guarda el siguiente manifiesto como el archivo worker-hpa.yaml:

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: async-worker-hpa
      namespace: default
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: async-worker
      minReplicas: 0
      maxReplicas: 20
      metrics:
      - type: External
        external:
          metric:
            name: autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered
          target:
            type: AverageValue
            averageValue: "10"
    

    Este manifiesto configura los siguientes campos clave:

    • minReplicas: 0: Habilita la reducción de escala a cero, ya que permite que el controlador reduzca la escala de la Deployment a 0 réplicas cuando la demanda disminuye a cero.
    • type: External: Configura una fuente de métricas externa para que el HPA pueda activar el aumento de escala cuando la carga de trabajo no tenga Pods.
    • name: autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered: Asigna el HPA directamente al recurso AutoscalingMetric creado en el paso anterior con el formato del identificador autoscaling.gke.io|CUSTOM_RESOURCE_NAME|METRIC_NAME.
  2. Aplica el manifiesto worker-hpa.yaml:

    kubectl apply -f worker-hpa.yaml
    

Verifica el comportamiento y las condiciones de la escala cero

Cuando se procesan todos los mensajes de la suscripción a Pub/Sub, el escalador automático horizontal de Pods evalúa la demanda nula y reduce la cantidad de réplicas de la Deployment a 0.

Para verificar que el escalador automático horizontal de Pods activó el estado cero, inspecciona las condiciones de estado del recurso async-worker-hpa ejecutando el siguiente comando:

kubectl describe hpa async-worker-hpa

El resultado es similar a lo siguiente:

Name:             async-worker-hpa
Namespace:        default
Reference:        Deployment/async-worker
Metrics:          ( current / target )
  "autoscaling.gke.io|pubsub-queue-depth|pubsub-undelivered" (external metric):  0 / 10
Min replicas:     0
Max replicas:     20
Deployment pods:  0 current / 0 desired
Conditions:
  Type            Status  Reason               Message
  ----            ------  ------               -------
  AbleToScale     True    SucceededGetScale    the HPA controller was able to get the target's current scale
  ScalingActive   True    ValidMetricFound     the HPA was able to successfully calculate a replica count from external metric
  ScaledToZero    True    ScaledToZero         the HPA has scaled the target resource to 0 replicas due to zero metric demand

Comprende la condición ScaledToZero

La condición ScaledToZero indica si el escalador automático de Pods horizontal redujo la escala de la carga de trabajo a cero réplicas:

  • ScaledToZero: True (Reason: ScaledToZero): Indica que el controlador de HPA escaló correctamente tu carga de trabajo a 0 réplicas porque la demanda de la métrica externa se redujo a cero. El HPA permanece activo (ScalingActive: True) y sondea continuamente GKE para detectar cuándo aumenta la demanda de la carga de trabajo.
  • ScaledToZero: False: Indica que la carga de trabajo se amplió a una o más réplicas.

Si ajustas la escala de una Deployment a cero réplicas de forma manual, por ejemplo, con el comando kubectl scale --replicas=0, el HPA pausa el ajuste de escala automático (ScalingActive: False) para evitar cambios en conflicto. Para reanudar el ajuste de escala automático, vuelve a ajustar la escala de la implementación a una o más réplicas (kubectl scale deployment async-worker --replicas=1).

Para solucionar problemas en situaciones en las que las cargas de trabajo no se pueden escalar a cero o no se pueden escalar verticalmente desde cero, consulta Soluciona problemas de escalamiento de cargas de trabajo de GKE a cero y desde cero con HPA. Si el escalador automático de Pods horizontal informa que faltan métricas externas o que no son válidas, consulta Soluciona problemas relacionados con las métricas que se recuperan para el ajuste de escala automático.

Realiza una limpieza

Sigue estos pasos para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos que usaste en este instructivo:

  1. Borra el clúster de GKE:

    gcloud container clusters delete scale-to-zero \
        --project=${PROJECT_ID} \
        --location=${LOCATION}
    
  2. Borra el tema y la suscripción de Pub/Sub:

    gcloud pubsub subscriptions delete my-worker-subscription \
        --project=${PROJECT_ID}
    gcloud pubsub topics delete my-worker-topic \
        --project=${PROJECT_ID}
    

¿Qué sigue?