Reduce los costos mediante el escalamiento de clústeres de GKE durante las horas de menor demanda.

Last reviewed 2022-11-24 UTC

En este instructivo, se explica cómo puedes reducir costos mediante la implementación de un escalador automático programado en Google Kubernetes Engine (GKE). Este tipo de escalador automático aumenta o reduce la escala de los clústeres en función de un programa basado en la hora del día o el día de la semana. Un escalador automático programado es útil si tu tráfico tiene una disminución y un flujo predecibles, por ejemplo, si eres un minorista regional o si tu software es para empleados cuyo horario laboral se limita a una parte específica del día,

El instructivo es para desarrolladores y operadores que deseen escalar verticalmente los clústeres de forma confiable antes de que lleguen los aumentos repentinos, y volver a reducir la escala para ahorrar dinero por la noche, los fines de semana o en cualquier otro momento en el que haya menos usuarios en línea. En el artículo, se supone que estás familiarizado con Docker, Kubernetes, los CronJobs de Kubernetes, GKE y Linux.

Introducción

Muchas aplicaciones experimentan patrones de tráfico desiguales. Por ejemplo, si los trabajadores de una organización interactúan con una aplicación solo durante el día. Como resultado, los servidores de los centros de datos para esa aplicación se encuentran inactivos por la noche.

Más allá de otros beneficios, Google Cloud puede ayudarte a ahorrar dinero, ya que asigna la infraestructura de forma dinámica según la carga de tráfico. En algunos casos, una configuración de ajuste de escala automático simple puede administrar la asignación del tráfico desigual. Si ese es tu caso, usa esa opción. Sin embargo, en otros casos, los cambios abruptos en los patrones de tráfico requieren configuraciones más precisas para el ajuste de escala automático a fin de evitar la inestabilidad del sistema durante los escalamientos verticales y de eludir el aprovisionamiento en exceso del clúster.

En este instructivo, nos enfocaremos en situaciones en las que se conocen bien los cambios abruptos en los patrones de tráfico y se busca indicarle al escalador automático que la infraestructura está a punto de experimentar aumentos repentinos. En este documento, se muestra cómo aumentar verticalmente la escala de los clústeres de GKE a la mañana y reducirla a la noche, pero puedes usar un enfoque similar para aumentar y disminuir la capacidad de cualquier evento conocido, como los eventos de escala máxima, las campañas publicitarias, el tráfico durante el fin de semana, etcétera.

Reduce verticalmente la escala de un clúster si tienes descuentos por compromiso de uso

En este instructivo, se explica cómo disminuir los costos si reduces verticalmente la escala de tus clústeres de GKE al mínimo durante las horas de menor demanda. Sin embargo, si compraste un descuento por compromiso de uso, es importante comprender cómo funcionan estos descuentos junto con el ajuste de escala automático.

Los contratos de compromiso de uso te brindan precios muy reducidos si te comprometes a pagar por una cantidad determinada de recursos (CPU virtuales, memoria y otros). Sin embargo, a fin de determinar la cantidad de recursos para los que te comprometerás, debes saber de antemano cuántos recursos usan tus cargas de trabajo a lo largo del tiempo. Para ayudarte a reducir los costos, en el siguiente diagrama, se muestran los recursos que debes incluir y los que no en la planificación.

Distribución de recursos, que muestra una base de recursos confirmados que siempre se asignan y recursos que se escalan automáticamente en respuesta a la demanda (aumentos).

Como se muestra en el diagrama, la asignación de recursos en un contrato de compromiso de uso es fija. Los recursos que incluye el contrato deben estar en uso la mayor parte del tiempo para que el compromiso valga la pena. Por lo tanto, no debes incluir recursos que se usen durante los aumentos repentinos en el cálculo de tus recursos del compromiso. Para los recursos de los aumentos, te recomendamos que uses las opciones del escalador automático de GKE. Estas opciones incluyen el escalador automático programado que se analiza en este documento y otras opciones administradas que se analizan en Prácticas recomendadas para ejecutar aplicaciones de Kubernetes con optimización de costos en GKE.

Si ya tienes un contrato de compromiso de uso para una cantidad determinada de recursos, no disminuirás los costos si reduces verticalmente la escala de tu clúster por debajo de ese mínimo. En esas situaciones, te recomendamos que intentes programar algunos trabajos para llenar los vacíos durante los períodos de baja demanda de procesamiento.

Arquitectura

En el siguiente diagrama, se muestra la arquitectura de la infraestructura y el escalador automático programado que se implementa en este instructivo. El escalador automático programado consta de un conjunto de componentes que funcionan en conjunto para administrar el escalamiento en función de un programa.

Arquitectura en la que se muestran los componentes que conforman el escalador automático programado.

En esta arquitectura, un conjunto de CronJobs de Kubernetes exporta información conocida sobre los patrones de tráfico a una métrica personalizada de Cloud Monitoring. Luego, un escalador automático horizontal de Pods (HPA) de Kubernetes lee estos datos como entrada sobre el momento en que el HPA debe escalar tu carga de trabajo. Junto con otras métricas de carga, como el uso de CPU de destino, el HPA decide cómo escalar las réplicas para una implementación determinada.

Objetivos

  • Crear un clúster de GKE.
  • Implementar una aplicación de ejemplo que use un HPA de Kubernetes
  • Configurar los componentes del escalador automático programado y actualizar tu HPA a fin de leer desde una métrica personalizada programada.
  • Configurar una alerta para que se active cuando el autoescalador programado no funcione de forma adecuada.
  • Generar una carga para la aplicación.
  • Examinar cómo el HPA responde a los aumentos normales del tráfico y a las métricas personalizadas programadas que configuras.

El código para este instructivo está disponible en un repositorio de GitHub.

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.

Antes de comenzar

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the GKE, Artifact Registry and the Cloud Monitoring APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the GKE, Artifact Registry and the Cloud Monitoring APIs.

    Enable the APIs

Prepare el entorno

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. En Cloud Shell, configura el ID del proyecto de Google Cloud, la dirección de correo electrónico, y la zona y la región de procesamiento:

    PROJECT_ID=YOUR_PROJECT_ID
    ALERT_EMAIL=YOUR_EMAIL_ADDRESS
    gcloud config set project $PROJECT_ID
    gcloud config set compute/region us-central1
    gcloud config set compute/zone us-central1-f
    

    Reemplaza lo siguiente:

    • YOUR_PROJECT_ID: Es el nombre del proyecto de Google Cloud para el proyecto que usas.
    • YOUR_EMAIL_ADDRESS: la dirección de correo electrónico para recibir notificaciones cuando el escalador automático programado no funciona como corresponde.

    Si lo deseas, puedes elegir una región y una zona diferentes para este instructivo.

  3. Clona el repositorio de GitHub kubernetes-engine-samples:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/
    cd kubernetes-engine-samples/cost-optimization/gke-scheduled-autoscaler
    

    El código de este ejemplo se organiza en las siguientes carpetas:

    • Raíz: Contiene el código que usan los CronJobs para exportar métricas personalizadas a Cloud Monitoring.
    • k8s/: Contiene un ejemplo de implementación que tiene un HPA de Kubernetes.
    • k8s/scheduled-autoscaler/: Contiene los CronJobs que exportan una métrica personalizada y una versión actualizada del HPA para leer desde una métrica personalizada.
    • k8s/load-generator/: Contiene una implementación de Kubernetes que tiene una aplicación para simular el uso por hora.
    • monitoring/: Contiene los componentes de Cloud Monitoring que configuras en este instructivo.

Crea el clúster de GKE

  1. En Cloud Shell, crea un clúster de GKE para ejecutar el escalador automático programado:

    gcloud container clusters create scheduled-autoscaler \
        --enable-ip-alias \
        --release-channel=stable \
        --machine-type=e2-standard-2 \
        --enable-autoscaling --min-nodes=1 --max-nodes=10 \
        --num-nodes=1 \
        --autoscaling-profile=optimize-utilization
    

    El resultado es similar a este:

    NAME                   LOCATION       MASTER_VERSION   MASTER_IP      MACHINE_TYPE   NODE_VERSION     NUM_NODES  STATUS
    scheduled-autoscaler   us-central1-f  1.22.15-gke.100  34.69.187.253  e2-standard-2  1.22.15-gke.100  1          RUNNING
    

    Esta no es una configuración de producción, pero es adecuada para este instructivo. En esta configuración, configuras el escalador automático del clúster con un mínimo de 1 nodo y un máximo de 10. También puedes habilitar el perfil optimize-utilization para acelerar el proceso de reducción vertical de escala.

Implementa la aplicación de ejemplo

  1. Implementa la aplicación de ejemplo sin el escalador automático programado:

    kubectl apply -f ./k8s
    
  2. Abre el archivo k8s/hpa-example.yaml.

    En la siguiente lista, se muestra el contenido del archivo.

    spec:
      maxReplicas: 20
      minReplicas: 10
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: php-apache
      metrics:
      - type: Resource
        resource:
          name: cpu
          target:
            type: Utilization
            averageUtilization: 60

    Observa que la cantidad mínima de réplicas (minReplicas) está configurada en 10. Esta configuración también establece el escalamiento del clúster en función del uso de CPU (la configuración name: cpu y type: Utilization).

  3. Espera a que la aplicación esté disponible:

    kubectl wait --for=condition=available --timeout=600s deployment/php-apache
    EXTERNAL_IP=''
    while [ -z $EXTERNAL_IP ]
    do
        EXTERNAL_IP=$(kubectl get svc php-apache -o jsonpath={.status.loadBalancer.ingress[0].ip})
        [ -z $EXTERNAL_IP ] && sleep 10
    done
    curl -w '\n' http://$EXTERNAL_IP
    

    Cuando la aplicación está disponible, el resultado es el siguiente:

    OK!
    
  4. Verifica la configuración:

    kubectl get hpa php-apache
    

    El resultado es similar a este:

    NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
    php-apache   Deployment/php-apache   9%/60%    10        20        10         6d19h
    

    En la columna REPLICAS, se muestra 10, que coincide con el valor del campo minReplicas en el archivo hpa-example.yaml.

  5. Verifica si la cantidad de nodos aumentó a 4:

    kubectl get nodes
    

    El resultado es similar a este:

    NAME                                                  STATUS   ROLES    AGE   VERSION
    gke-scheduled-autoscaler-default-pool-64c02c0b-9kbt   Ready    <none>   21S   v1.17.9-gke.1504
    gke-scheduled-autoscaler-default-pool-64c02c0b-ghfr   Ready    <none>   21s   v1.17.9-gke.1504
    gke-scheduled-autoscaler-default-pool-64c02c0b-gvl9   Ready    <none>   21s   v1.17.9-gke.1504
    gke-scheduled-autoscaler-default-pool-64c02c0b-t9sr   Ready    <none>   21s   v1.17.9-gke.1504
    

    Cuando creaste el clúster, estableciste una configuración mínima con la marca min-nodes=1. Sin embargo, la aplicación que implementaste al comienzo de este procedimiento solicita más infraestructura porque minReplicas en el archivo hpa-example.yaml está configurado en 10.

    Establecer minReplicas en un valor como 10 es una estrategia común que usan empresas como los minoristas, que esperan un aumento repentino en el tráfico durante las primeras horas del día hábil. Sin embargo, establecer valores altos para el minReplicas de HPA puede aumentar los costos porque el clúster no puede reducirse, ni siquiera por la noche, cuando el tráfico de la aplicación es bajo.

Configura un escalador automático programado

  1. En Cloud Shell, instala el adaptador de métricas personalizadas de Cloud Monitoring en tu clúster de GKE:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml
    kubectl wait --for=condition=available --timeout=600s deployment/custom-metrics-stackdriver-adapter -n custom-metrics
    

    Este adaptador habilita el ajuste de escala automático de los Pods según las métricas personalizadas de Cloud Monitoring.

  2. Crea un repositorio en Artifact Registry y otorga permisos de lectura:

    gcloud artifacts repositories create gke-scheduled-autoscaler \
      --repository-format=docker --location=us-central1
    gcloud auth configure-docker us-central1-docker.pkg.dev
    gcloud artifacts repositories add-iam-policy-binding gke-scheduled-autoscaler \
       --location=us-central1 --member=allUsers --role=roles/artifactregistry.reader
    
  3. Compila y envía el código del exportador de métricas personalizadas:

    docker build -t us-central1-docker.pkg.dev/$PROJECT_ID/gke-scheduled-autoscaler/custom-metric-exporter .
    docker push us-central1-docker.pkg.dev/$PROJECT_ID/gke-scheduled-autoscaler/custom-metric-exporter
    
  4. Implementa los CronJobs que exportan métricas personalizadas y, luego, implementa la versión actualizada del HPA que lee desde estas métricas personalizadas:

    sed -i.bak s/PROJECT_ID/$PROJECT_ID/g ./k8s/scheduled-autoscaler/scheduled-autoscale-example.yaml
    kubectl apply -f ./k8s/scheduled-autoscaler
    
  5. Abre y examina el archivo k8s/scheduled-autoscaler/scheduled-autoscale-example.yaml.

    En la siguiente lista, se muestra el contenido del archivo.

    apiVersion: batch/v1
    kind: CronJob
    metadata:
      name: scale-up
    spec:
      schedule: "50-59/1 * * * *"
      jobTemplate:
        spec:
          template:
            spec:
              containers:
              - name: custom-metric-extporter
                image: us-central1-docker.pkg.dev/PROJECT_ID/gke-scheduled-autoscaler/custom-metric-exporter
                command:
                  - /export
                  - --name=scheduled_autoscaler_example
                  - --value=10
              restartPolicy: OnFailure
          backoffLimit: 1
    ---
    apiVersion: batch/v1
    kind: CronJob
    metadata:
      name: scale-down
    spec:
      schedule: "1-49/1 * * * *"
      jobTemplate:
        spec:
          template:
            spec:
              containers:
              - name: custom-metric-extporter
                image: us-central1-docker.pkg.dev/PROJECT_ID/gke-scheduled-autoscaler/custom-metric-exporter
                command:
                  - /export
                  - --name=scheduled_autoscaler_example
                  - --value=1
              restartPolicy: OnFailure
          backoffLimit: 1

    Esta configuración especifica que los CronJobs deben exportar el recuento de réplicas de Pods sugeridas a una métrica personalizada llamada custom.googleapis.com/scheduled_autoscaler_example en función de la hora del día. Para facilitar la sección de supervisión de este instructivo, la configuración del campo de programa define los aumentos y reducciones verticales de la escala por hora. Para la producción, puedes personalizar este programa a fin de que se adapte a las necesidades de tu empresa.

  6. Abre y examina el archivo k8s/scheduled-autoscaler/hpa-example.yaml.

    En la siguiente lista, se muestra el contenido del archivo.

    spec:
      maxReplicas: 20
      minReplicas: 1
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: php-apache
      metrics:
      - type: Resource
        resource:
          name: cpu
          target:
            type: Utilization
            averageUtilization: 60
      - type: External
        external:
          metric:
            name: custom.googleapis.com|scheduled_autoscaler_example
          target:
              type: AverageValue
              averageValue: 1

    Esta configuración especifica que el objeto HPA debe reemplazar el HPA que se implementó antes. Ten en cuenta que la configuración reduce el valor de minReplicas a 1. Esto significa que la carga de trabajo se puede reducir a su valor mínimo. La configuración también agrega una métrica externa (type: External). Esta incorporación significa que el ajuste de escala automático ahora se activa por dos factores.

    En esta situación de varias métricas, el HPA calcula un recuento de réplicas propuesto para cada métrica y, luego, elige la métrica que muestra el valor más alto. Es importante comprender esto: el escalador automático programado puede proponer que, en un momento determinado, el recuento de Pods debería ser 1. Sin embargo, si el uso real de la CPU es mayor de lo esperado para un Pod, el HPA crea más réplicas.

  7. Verifica la cantidad de nodos y réplicas de HPA de nuevo mediante la ejecución de cada uno de estos comandos:

    kubectl get nodes
    kubectl get hpa php-apache
    

    El resultado que ves depende de lo que el escalador automático programado haya hecho recientemente. En particular, los valores de minReplicas y nodes serán diferentes en distintos puntos del ciclo de escalamiento.

    Por ejemplo, aproximadamente los minutos 51 a 60 de cada hora (que representa un período de tráfico máximo), el valor HPA para minReplicas será de 10 y el valor de nodes será 4.

    Por el contrario, para los minutos del 1 al 50 (que representan un período de menor tráfico), el valor minReplicas de HPA será 1 y el valor nodes será 1 o 2, según la cantidad de Pods que se asignaron y quitaron. Para los valores más bajos (los minutos del 1 a 50), el clúster puede demorar hasta 10 minutos en terminar de reducir la escala verticalmente.

Configura alertas para cuando el escalador automático programado no funcione correctamente

En un entorno de producción, por lo general, quieres saber cuándo CronJobs no propaga la métrica personalizada. Para este fin, puedes crear una alerta que se active cuando cualquier transmisión de custom.googleapis.com/scheduled_autoscaler_example esté ausente por un período de cinco minutos.

  1. En Cloud Shell, crea un canal de notificaciones:

    gcloud beta monitoring channels create \
        --display-name="Scheduled Autoscaler team (Primary)" \
        --description="Primary contact method for the Scheduled Autoscaler team lead"  \
        --type=email \
        --channel-labels=email_address=${ALERT_EMAIL}
    

    El resultado es similar a este:

    Created notification channel NOTIFICATION_CHANNEL_ID.
    

    Con este comando, se crea un canal de notificaciones de tipo email para simplificar los pasos del instructivo. En entornos de producción, te recomendamos que uses una estrategia menos asíncrona. Para ello, establece el canal de notificaciones en sms o pagerduty.

  2. Configura una variable que tenga el valor que se mostró en el marcador de posición NOTIFICATION_CHANNEL_ID:

    NOTIFICATION_CHANNEL_ID=NOTIFICATION_CHANNEL_ID
    
  3. Implementa la política de alertas:

    gcloud alpha monitoring policies create \
        --policy-from-file=./monitoring/alert-policy.yaml \
        --notification-channels=$NOTIFICATION_CHANNEL_ID
    

    El archivo alert-policy.yaml contiene la especificación para enviar una alerta si la métrica está ausente durante cinco minutos.

  4. Ve a la página Alertas de Cloud Monitoring para ver la política de alertas.

    Ve a las alertas

  5. Haz clic en Política del escalador automático programado y verifica los detalles de la política de alertas.

Genera una carga en la aplicación de ejemplo

  • En Cloud Shell, implementa el generador de cargas:

    kubectl apply -f ./k8s/load-generator
    

    En la siguiente lista, se muestra la secuencia de comandos load-generator.

    command: ["/bin/sh", "-c"]
    args:
    - while true; do
        RESP=$(wget -q -O- http://php-apache.default.svc.cluster.local);
        echo "$(date +%H)=$RESP";
        sleep $(date +%H | awk '{ print "s("$0"/3*a(1))*0.5+0.5" }' | bc -l);
      done;
    

    Esta secuencia de comandos se ejecuta en tu clúster hasta que borres la implementación load-generator. Realiza solicitudes al servicio php-apache cada pocos milisegundos. El comando sleep simula cambios en la distribución de cargas durante el día. Mediante una secuencia de comandos que genera tráfico de esta manera, puedes comprender lo que sucede cuando combinas el uso de CPU y las métricas personalizadas en la configuración del HPA.

Visualiza el escalamiento como respuesta al tráfico o las métricas programadas

En esta sección, observarás las visualizaciones que te muestran los efectos del aumento y la reducción vertical de la escala.

  1. En Cloud Shell, crea un entorno nuevo.

    gcloud monitoring dashboards create \
        --config-from-file=./monitoring/dashboard.yaml
    
  2. Ve a la página Paneles de Cloud Monitoring:

    Ir a Paneles

  3. Haz clic en Panel del escalador automático programado.

    El panel muestra tres gráficos. Debes esperar al menos 2 horas (lo ideal sería 24 horas o más) para ver la dinámica de los aumentos y reducciones verticales de la escala, y para ver cómo las diferentes distribuciones de cargas durante el día afectan el ajuste de escala automático.

    Estudia los siguientes gráficos, que presentan una vista de un día completo, para tener una idea de lo que muestran en general:

    • La métrica programada (cantidad deseada de Pods) muestra una serie temporal de la métrica personalizada que se exporta a Cloud Monitoring a través de los CronJobs que configuraste en Configura un escalador automático programado.

      Gráfico de la demanda de Pods, que muestra un aumento cada hora.

    • El Uso de CPU (solicitado o usado) muestra una serie temporal de CPU solicitada (rojo) y el uso de CPU real (azul). Cuando la carga es baja, el HPA respeta la decisión de uso del escalador automático programado. Sin embargo, cuando el tráfico aumenta, el HPA aumenta la cantidad de Pods según sea necesario, como puedes ver para los datos entre las 12:00 p.m. y las 6:00 p.m.

      Gráfico del uso de CPU, que muestra la demanda que aumenta durante el día hasta las 4:00 p.m. y, luego, disminuye.

    • La Cantidad de Pods (programados o reales) + uso de CPU promedio muestra una vista similar a las anteriores. El recuento de Pods (rojo) aumenta a 10 cada hora según lo programado (azul). El recuento de Pods aumenta y disminuye de forma natural con el tiempo como respuesta a la carga (12 p.m. y 6 p.m.). El uso de CPU promedio (naranja) permanece por debajo del objetivo que estableciste (60%).

      2 gráficos. Uno muestra la demanda de Pods con un aumento repentino en la demanda por hora. El otro muestra que el uso de CPU aumenta y disminuye, pero se completa con el valor alto configurado.

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.

Borra el proyecto

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

¿Qué sigue?