Implementa GPU para cargas de trabajo por lotes con el programador dinámico de cargas de trabajo


En esta página, se muestra cómo optimizar la capacidad de obtención de la GPU a través del Programador dinámico de cargas de trabajo. Recomendamos el programador de cargas de trabajo dinámico para cargas de trabajo por lotes a gran escala que se puedan ejecutar durante las horas de menor demanda con las condiciones de administración de capacidad de GPU definidas. Estas cargas de trabajo pueden ser un entrenamiento de modelos de aprendizaje profundo o una simulación que necesita grandes cantidades de GPUs con un modelo de aprovisionamiento atómico, lo que significa que todos los recursos se crean al mismo tiempo.

Para ejecutar cargas de trabajo de GPU en Google Kubernetes Engine (GKE) sin el programador de cargas de trabajo dinámico, consulta Ejecuta GPU en grupos de nodos de GKE Estándar.

Cuándo usar el programador dinámico de cargas de trabajo

Te recomendamos que uses el programador de cargas de trabajo dinámico si tus cargas de trabajo cumplen con todas las siguientes condiciones:

  • Solicitas que las GPUs ejecuten tus cargas de trabajo.
  • Tienes una capacidad limitada o no reservada GPUs y deseas mejorar la capacidad de obtención de los recursos de GPU.
  • Tu carga de trabajo es flexible, y tu caso de uso puede permitirse esperar para obtener toda la capacidad solicitada, por ejemplo, cuando GKE asigna los recursos de GPU fuera de las horas de mayor actividad.
  • Tu carga de trabajo requiere varios nodos y no puede comenzar a ejecutarse hasta que todos los nodos de GPU se aprovisionen y estén listos al mismo tiempo (por ejemplo, entrenamiento de aprendizaje automático distribuido).

Antes de comenzar

Antes de comenzar, asegúrate de haber realizado las siguientes tareas:

  • Habilita la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Si deseas usar Google Cloud CLI para esta tarea, instala y, luego, inicializa gcloud CLI. Si ya instalaste gcloud CLI, ejecuta gcloud components update para obtener la versión más reciente.

Usa grupos de nodos con el programador dinámico de cargas de trabajo

Puedes usar cualquiera de los siguientes tres métodos para designar que el programador de cargas de trabajo dinámico pueda funcionar con grupos de nodos específicos en tu clúster:

Crear un grupo de nodos

Crea un grupo de nodos con el programador de cargas de trabajo dinámico habilitado mediante gcloud CLI:

gcloud beta container node-pools create NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
     --enable-queued-provisioning \
    --accelerator type=GPU_TYPE,count=AMOUNT,gpu-driver-version=DRIVER_VERSION \
    --machine-type=MACHINE_TYPE \
    --enable-autoscaling  \
    --num-nodes=0   \
    --total-max-nodes TOTAL_MAX_NODES  \
    --location-policy=ANY  \
    --reservation-affinity=none  \
    --no-enable-autorepair

Reemplaza lo siguiente:

  • NODEPOOL_NAME: Es el nombre que eliges para el grupo de nodos.
  • CLUSTER_NAME: Es el nombre del clúster.
  • LOCATION: Es la región de Compute Engine del clúster, como us-central1.
  • GPU_TYPE: Es el tipo de GPU.
  • AMOUNT: Es la cantidad de GPU que se deben adjuntar a los nodos del grupo de nodos.
  • DRIVER_VERSION: Es la versión del controlador NVIDIA que se instalará. Puede ser uno de los datos siguientes:
    • default: Instala la versión predeterminada del controlador para tu versión de GKE.
    • latest: Instala la última versión del controlador disponible para tu versión de GKE. Disponible solo para los nodos que usan Container-Optimized OS.
  • TOTAL_MAX_NODES: es la cantidad máxima de nodos que se escalarán de forma automática para todo el grupo de nodos.
  • MACHINE_TYPE: es el tipo de máquina de Compute Engine para tus nodos. Te recomendamos que elijas un tipo de máquina optimizado para aceleradores.

De manera opcional, puedes usar las siguientes marcas:

  • --no-enable-autoupgrade: Recomendado Inhabilita las actualizaciones automáticas de nodos. Solo es compatible con clústeres de GKE que no estén inscritos en un canal de versiones actualmente. Para obtener más información, consulta Inhabilita las actualizaciones automáticas de nodos para un grupo de nodos existente.
  • --node-locations=COMPUTE_ZONES: La lista separada por comas de una o más zonas en las que GKE crea los nodos de GPU. Las zonas deben estar en la misma región que el clúster. Elige zonas que tengan GPUs disponibles.
  • --enable-gvnic: Esta marca habilita a gVNIC en los grupos de nodos de GPU para aumentar la velocidad del tráfico de red.

Este comando crea un grupo de nodos con la siguiente configuración:

  • GKE permite el aprovisionamiento en cola y el ajuste de escala automático del clúster.
  • En un principio, el grupo de nodos no tiene nodos.
  • La marca --enable-queued-provisioning habilita el programador de cargas de trabajo dinámico y agrega el taint cloud.google.com/gke-queued al grupo de nodos.
  • Las marcas --no-enable-autorepair y --no-enable-autoupgrade inhabilitan la reparación y la actualización automáticas de los nodos, lo que puede interrumpir las cargas de trabajo que se ejecutan en nodos reparados o actualizados. Solo puedes inhabilitar la actualización automática de nodo en clústeres que no estén inscritos en un canal de versiones.

Actualiza un grupo de nodos existente y habilita el programador dinámico de cargas de trabajo

Habilita el programador dinámico de cargas de trabajo para un grupo de nodos existente. Revisa los requisitos para configurar el grupo de nodos de forma correcta.

Requisitos previos

  • Asegúrate de crear un grupo de nodos con la marca --reservation-affinity=none. Esta marca es obligatoria para habilitar el programador de cargas de trabajo dinámico más adelante, ya que no puedes cambiar la afinidad de reserva después de la creación del grupo de nodos.

  • Asegúrate de mantener al menos un grupo de nodos sin el control del Programador de cargas de trabajo dinámico habilitado para que el clúster funcione de forma correcta.

  • Asegúrate de que el grupo de nodos esté vacío Puedes cambiar el tamaño del grupo de nodos para que no tenga nodos.

  • Asegúrate de que el ajuste de escala automático esté habilitado y configurado de forma correcta.

  • Asegúrate de que las reparaciones automáticas estén inhabilitadas.

Habilita el programador dinámico de cargas de trabajo para el grupo de nodos existente

Puedes habilitar el programador de cargas de trabajo dinámico para un grupo de nodos existente con gcloud CLI:

gcloud beta container node-pools update NODEPOOL_NAME \
    --cluster=CLUSTER_NAME \
    --location=LOCATION \
     --enable-queued-provisioning

Reemplaza lo siguiente:

  • NODEPOOL_NAME: el nombre del grupo de nodos elegido.
  • CLUSTER_NAME: nombre del clúster
  • LOCATION: la región de Compute Engine del clúster, como us-central1.

Este comando de actualización del grupo de nodos da como resultado los siguientes cambios de configuración:

  • La marca --enable-queued-provisioning habilita el programador de cargas de trabajo dinámico y agrega el taint cloud.google.com/gke-queued al grupo de nodos.

De manera opcional, también puedes actualizar la siguiente configuración del grupo de nodos:

  • Inhabilita las actualizaciones automáticas de nodos: Te recomendamos inhabilitar las actualizaciones automáticas de nodos, ya que las actualizaciones de grupos de nodos no son compatibles cuando se usa el programador dinámico de cargas de trabajo. Para inhabilitar las actualizaciones automáticas de nodo, asegúrate de que tu clúster de GKE no esté inscrito en un canal de versiones.
  • Habilita gVNIC en los grupos de nodos de GPU: la NIC virtual de Google (gVNIC) aumenta la velocidad del tráfico de red para los nodos de GPU.

Habilita el aprovisionamiento automático de nodos a fin de crear grupos de nodos para el programador dinámico de cargas de trabajo

Puedes usar el aprovisionamiento automático de nodos a fin de administrar los grupos de nodos del programador de cargas de trabajo dinámico para clústeres que ejecutan la versión 1.29.2-gke.1553000 o una posterior. Cuando habilitas el aprovisionamiento automático de nodos y habilitas el programador de cargas de trabajo dinámicas, GKE crea grupos de nodos con los recursos necesarios para la carga de trabajo asociada.

Para habilitar el aprovisionamiento automático de nodos, considera la siguiente configuración y completa los pasos en Configura los límites de GPU:

Ejecuta tus cargas de trabajo por lotes con el programador dinámico de cargas de trabajo

Para usar el programador de cargas de trabajo dinámico, te recomendamos que uses Kueue. Kueue implementa la cola de Jobs, decide cuándo deben esperar los Jobs y cuándo deben iniciarse según las cuotas y una jerarquía para compartir recursos de manera equitativa entre los equipos. Esto simplifica la configuración necesaria para usar VMs en cola.

Puedes usar el programador de cargas de trabajo dinámico sin Kueue cuando usas tus propias herramientas o plataforma internas de programación por lotes. Si deseas configurar el programador de cargas de trabajo dinámico para trabajos sin Kueue, consulta Programador de cargas de trabajo dinámicos para trabajos sin Kueue.

Programador dinámico de cargas de trabajo para trabajos con Kueue

En la siguiente sección, se muestra cómo configurar el programador de cargas de trabajo dinámico para trabajos con Kueue. En esta sección, se usan las muestras del repositorio dws-examples. Publicamos las muestras en el repositorio dws-examples bajo la licencia Apache2.

Prepare el entorno

  1. En Cloud Shell, ejecuta el siguiente comando:

    git clone https://github.com/GoogleCloudPlatform/ai-on-gke
    cd ai-on-gke/tutorials-and-examples/workflow-orchestration/dws-examples
    
  2. Instala Kueue en tu clúster con la configuración necesaria para habilitar la integración de las solicitudes de aprovisionamiento:

    kubectl apply --server-side -f ./kueue-manifests.yaml
    

Para obtener más información sobre la instalación de Kueue, consulta Instalación.

Crea los recursos de Kueue

Con el siguiente manifiesto, creas una cola a nivel de clúster llamada dws-cluster-queue y el espacio de nombres LocalQueue llamado dws-local-queue. Los Jobs que hacen referencia a la cola dws-cluster-queue en este espacio de nombres usan el programador de cargas de trabajo dinámico para obtener los recursos de GPU.

apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: "default-flavor"
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: AdmissionCheck
metadata:
  name: dws-prov
spec:
  controllerName: kueue.x-k8s.io/provisioning-request
  parameters:
    apiGroup: kueue.x-k8s.io
    kind: ProvisioningRequestConfig
    name: dws-config
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ProvisioningRequestConfig
metadata:
  name: dws-config
spec:
  provisioningClassName: queued-provisioning.gke.io
  managedResources:
  - nvidia.com/gpu
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: "dws-cluster-queue"
spec:
  namespaceSelector: {} 
  resourceGroups:
  - coveredResources: ["cpu", "memory", "nvidia.com/gpu"]
    flavors:
    - name: "default-flavor"
      resources:
      - name: "cpu"
        nominalQuota: 10000  # Infinite quota.
      - name: "memory"
        nominalQuota: 10000Gi # Infinite quota.
      - name: "nvidia.com/gpu"
        nominalQuota: 10000  # Infinite quota.
  admissionChecks:
  - dws-prov
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  namespace: "default"
  name: "dws-local-queue"
spec:
  clusterQueue: "dws-cluster-queue"
---

Implementa LocalQueue:

kubectl create -f ./dws-queues.yaml

El resultado es similar al siguiente:

resourceflavor.kueue.x-k8s.io/default-flavor created
admissioncheck.kueue.x-k8s.io/dws-prov created
provisioningrequestconfig.kueue.x-k8s.io/dws-config created
clusterqueue.kueue.x-k8s.io/dws-cluster-queue created
localqueue.kueue.x-k8s.io/dws-local-queue created

Si deseas ejecutar Jobs que usan el Programador de cargas de trabajo dinámico en otros espacios de nombres, puedes crear LocalQueues adicionales con la plantilla anterior.

Ejecuta tu trabajo

En el siguiente manifiesto, el trabajo de muestra usa el programador de cargas de trabajo dinámico:

apiVersion: batch/v1
kind: Job
metadata:
  name: sample-job
  namespace: default
  labels:
    kueue.x-k8s.io/queue-name: dws-local-queue
  annotations:
    provreq.kueue.x-k8s.io/maxRunDurationSeconds: "600"
spec:
  parallelism: 1
  completions: 1
  suspend: true
  template:
    spec:
      nodeSelector:
        cloud.google.com/gke-nodepool: NODEPOOL_NAME
      tolerations:
      - key: "nvidia.com/gpu"
        operator: "Exists"
        effect: "NoSchedule"
      containers:
      - name: dummy-job
        image: gcr.io/k8s-staging-perf-tests/sleep:v0.0.3
        args: ["120s"]
        resources:
          requests:
            cpu: "100m"
            memory: "100Mi"
            nvidia.com/gpu: 1
          limits:
            cpu: "100m"
            memory: "100Mi"
            nvidia.com/gpu: 1
      restartPolicy: Never

En este manifiesto, se incluyen los siguientes campos relevantes para la configuración del programador de cargas de trabajo dinámicas:

  • La etiqueta kueue.x-k8s.io/queue-name: dws-local-queue le indica a GKE que Kueue es responsable de organizar ese trabajo. Esta etiqueta también define la cola en la que se pone en cola el trabajo.
  • La marca suspend: true le indica a GKE que cree el recurso de trabajo, pero que aún no programe los Pods. Kueue cambia esa marca a false cuando los nodos están listos para la ejecución del trabajo.
  • nodeSelector le dice a GKE que programe el trabajo solo en el grupo de nodos especificado. El valor debe coincidir con NODEPOOL_NAME, el nombre del grupo de nodos con el aprovisionamiento en cola habilitado.
  1. Ejecuta tu trabajo:

    kubectl create -f ./job.yaml
    

    El resultado es similar al siguiente:

    job.batch/sample-job created
    
  2. Verifica el estado de tu trabajo:

    kubectl describe job sample-job
    

    El resultado es similar al siguiente:

    Events:
      Type    Reason            Age    From                        Message
      ----    ------            ----   ----                        -------
      Normal  Suspended         5m17s  job-controller              Job suspended
      Normal  CreatedWorkload   5m17s  batch/job-kueue-controller  Created Workload: default/job-sample-job-7f173
      Normal  Started           3m27s  batch/job-kueue-controller  Admitted by clusterQueue dws-cluster-queue
      Normal  SuccessfulCreate  3m27s  job-controller              Created pod: sample-job-9qsfd
      Normal  Resumed           3m27s  job-controller              Job resumed
      Normal  Completed         12s    job-controller              Job completed
    

La integración del programador de cargas de trabajo dinámico con Kueue también admite otros tipos de cargas de trabajo disponibles en el ecosistema de código abierto, como las siguientes:

  • RayJob
  • JobSet
  • Kubeflow MPIJob, TFJob, PyTorchJob.
  • Pods de Kubernetes que los organizadores de flujos de trabajo usan con frecuencia
  • Miniclúster de Flux

Para obtener más información sobre esta asistencia, consulta Usuario por lotes de Kueue.

Programador dinámico de cargas de trabajo para trabajos sin Kueue

Crea una solicitud a través de la API de ProvisioningRequest para cada trabajo. El programador de cargas de trabajo dinámico no inicia los Pods, solo aprovisiona los nodos.

  1. Crea el siguiente manifiesto provisioning-request.yaml:

    apiVersion: v10
    kind: PodTemplate
    metadata:
      name: POD_TEMPLATE_NAME
      namespace: NAMESPACE_NAME
    template:
      spec:
        nodeSelector:
            cloud.google.com/gke-nodepool: NODEPOOL_NAME
        tolerations:
            - key: "nvidia.com/gpu"
              operator: "Exists"
              effect: "NoSchedule"
        containers:
            - name: pi
              image: perl
              command: ["/bin/sh"]
              resources:
                limits:
                  cpu: "700m"
                  nvidia.com/gpu: 1
                requests:
                  cpu: "700m"
                  nvidia.com/gpu: 1
        restartPolicy: Never
    ---
    apiVersion: autoscaling.x-k8s.io/v1beta1
    kind: ProvisioningRequest
    metadata:
      name: PROVISIONING_REQUEST_NAME
      namespace: NAMESPACE_NAME
    spec:
      provisioningClassName: queued-provisioning.gke.io
      parameters:
        maxRunDurationSeconds: "MAX_RUN_DURATION_SECONDS"
      podSets:
      - count: COUNT
        podTemplateRef:
          name: POD_TEMPLATE_NAME
    

    Reemplaza lo siguiente:

    • NAMESPACE_NAME: El nombre de tu espacio de nombres de Kubernetes. El espacio de nombres debe ser el mismo que el de los Pods.
    • PROVISIONING_REQUEST_NAME: El nombre de ProvisioningRequest. Haz referencia a este nombre en la anotación del Pod.
    • MAX_RUN_DURATION_SECONDS: De manera opcional, el tiempo de ejecución máximo de un nodo en segundos, hasta el valor predeterminado de siete días. Para obtener más información, consulta Cómo funciona el programador de cargas de trabajo dinámico. No puedes cambiar este valor después de crear la solicitud. Este campo está disponible en Vista previa en la versión 1.28.5-gke.1355000 de GKE o una posterior.
    • COUNT: Cantidad de Pods solicitados. Los nodos se programan de forma atómica en una zona.
    • POD_TEMPLATE_NAME: Un nombre estándar de Kubernetes. GKE hace referencia a este valor en el PodSet de solicitud de aprovisionamiento.
    • NODEPOOL_NAME: Es el nombre que eliges para el grupo de nodos.
  2. Aplica el manifiesto:

    kubectl apply -f provisioning-request.yaml
    

Configura los Pods

En la especificación del trabajo, vincula los Pods al ProvisioningRequest mediante las siguientes anotaciones:

apiVersion: batch/v1
kind: Job
spec:
  template:
    metadata:
      annotations:
        cluster-autoscaler.kubernetes.io/consume-provisioning-request: PROVISIONING_REQUEST_NAME
        cluster-autoscaler.kubernetes.io/provisioning-class-name: "queued-provisioning.gke.io"
    spec:
      ...

La clave de anotación del Pod cluster-autoscaler.kubernetes.io/consume-provisioning-request define qué ProvisioningRequest consumir. GKE usa las anotaciones consume-provisioning-request y provisioning-class-name para hacer lo siguiente:

  • Para programar los Pods solo en los nodos que aprovisiona el Programador dinámico de cargas de trabajo.
  • Para evitar el doble recuento de las solicitudes de recursos entre los Pods y el programador de cargas de trabajo dinámico en el escalador automático del clúster.
  • Para incorporar la anotación safe-to-evict: false, a fin de evitar que el escalador automático de clústeres mueva Pods entre nodos y interrumpa los procesamientos por lotes. Puedes cambiar este comportamiento si especificas safe-to-evict: true en las anotaciones del Pod.

Observa el estado del programador dinámico de cargas de trabajo

El estado de un programador de cargas de trabajo dinámico define si un Pod se puede programar o no. Puedes usar las observaciones de Kubernetes a fin de observar cambios de manera eficiente o, también, otras herramientas que ya usas para hacer un seguimiento de los estados de los objetos de Kubernetes. En la siguiente tabla, se describe el estado posible de un programador de cargas de trabajo dinámico y cada resultado posible:

Estado del programador de cargas de trabajo dinámicas Descripción Resultado posible
Pendiente La solicitud aún no se vio ni se procesó. Después del procesamiento, la solicitud pasa al estado Accepted o Failed.
Accepted=true Se acepta la solicitud y se espera a que los recursos estén disponibles. La solicitud debe pasar al estado Provisioned, si se encontraron recursos y se aprovisionaron nodos, o al estado Failed si eso no fue posible.
Provisioned=true Los nodos están listos. Tienes 10 minutos para iniciar los Pods a fin de consumir recursos aprovisionados. Después de este período, el escalador automático del clúster considera los nodos como no necesarios y los quita.
Failed=true Los nodos no se pueden aprovisionar debido a errores. Failed=true es un estado terminal. Soluciona el problema de la condición según la información en los campos Reason y Message de la condición. Crea y vuelve a intentar una solicitud nueva del programador dinámico de cargas de trabajo.
Provisioned=false Aún no se aprovisionaron los nodos.

Si es Reason=NotProvisioned, es un estado temporal antes de que todos los recursos estén disponibles.

Si es Reason=QuotaExceeded, soluciona el problema de la condición según este motivo y la información del campo Message de la condición. Es posible que debas solicitar más cuota. Para obtener más detalles, consulta la sección Verifica si el programador de cargas de trabajo dinámico está limitado por la cuota. Este Reason solo está disponible con la versión 1.29.2-gke.1181000 de GKE o una posterior.

Inicia los Pods

Cuando la solicitud del programador de cargas de trabajo dinámica alcanza el estado Provisioned=true, puedes ejecutar tu trabajo para iniciar los Pods. Esto evita la proliferación de Pods no programables para solicitudes pendientes o fallidas, lo que puede afectar el rendimiento de kube-scheduler y el escalador automático de clústeres.

Como alternativa, si no te importa tener Pods no programables, puedes crear Pods en paralelo con el programador de cargas de trabajo dinámico.

Cancela la solicitud del Programador de cargas de trabajo dinámico

Para cancelar la solicitud antes de que se aprovisione, puedes borrar el ProvisioningRequest:

kubectl delete provreq PROVISIONING_REQUEST_NAME -n NAMESPACE

En la mayoría de los casos, si borras ProvisioningRequest, no se crearán los nodos. Sin embargo, según el momento, por ejemplo, si los nodos ya se están aprovisionando, es posible que los nodos aún se creen. En estos casos, el escalador automático del clúster quita los nodos después de 10 minutos si no se crean Pods.

Cómo funciona el programador dinámico de cargas de trabajo

Con ProvisioningRequest API, el programador de cargas de trabajo dinámicas hace lo siguiente:

  1. Le indicas a GKE que tu carga de trabajo puede esperar, por un tiempo indeterminado, hasta que todos los nodos necesarios estén listos para usar a la vez.
  2. El escalador automático del clúster acepta tu solicitud y calcula la cantidad de nodos necesarios y los trata como una sola unidad.
  3. La solicitud espera hasta que todos los recursos necesarios estén disponibles en una sola zona.
  4. El escalador automático de clústeres aprovisiona los nodos necesarios cuando están disponibles, todo a la vez.
  5. Todos los Pods de la carga de trabajo pueden ejecutarse juntos en nodos recién aprovisionados.
  6. Los nodos aprovisionados se limitan a siete días de entorno de ejecución o antes si configuras el parámetro maxRunDurationSeconds para indicar que las cargas de trabajo necesitan menos tiempo para ejecutarse. Para obtener más información, consulta Limita el entorno de ejecución de una VM (vista previa). Esta función está disponible con la versión 1.28.5-gke.1355000 de GKE o una posterior. Después de este tiempo, los nodos y los Pods que se ejecutan en ellos se interrumpen. Si los Pods finalizan antes y los nodos no se usan, el escalador automático del clúster los quita según el perfil de ajuste de escala automático.
  7. Los nodos no se reutilizan entre el programador dinámico de cargas de trabajo. Cada ProvisioningRequest ordenará la creación de nodos nuevos con el nuevo entorno de ejecución de siete días.

Cuota

La cantidad de ProvisioningRequests que se encuentran en estado Accepted está limitada por una cuota dedicada, configurada por proyecto, de forma independiente para cada región.

Verifica la cuota en la consola de Google Cloud

Para verificar el nombre del límite de cuota y el uso actual en la consola de Google Cloud, sigue estos pasos:

  1. Dirígete a la página Cuotas en la consola de Google Cloud.

    Ir a Cuotas

  2. En la casilla Filtro, selecciona la propiedad Métrica, ingresa active_resize_requests y presiona Intro.

El valor predeterminado es 100. Para aumentar la cuota, sigue los pasos que se indican en Solicita una guía de límite de cuota más alta.

Comprueba si el programador de cargas de trabajo dinámico está limitado por la cuota

Si tu solicitud del programador dinámico de cargas de trabajo tarda más de lo esperado en completarse, verifica que la solicitud no esté limitada por la cuota. Es posible que debas solicitar más cuota.

Para los clústeres que ejecutan la versión 1.29.2-gke.1181000 o una posterior, verifica si las limitaciones de cuota específicas impiden que se complete tu solicitud:

kubectl describe provreq PROVISIONING_REQUEST_NAME \
    --namespace NAMESPACE

El resultado es similar al siguiente:

…
Last Transition Time:  2024-01-03T13:56:08Z
    Message:               Quota 'NVIDIA_P4_GPUS' exceeded. Limit: 1.0 in region europe-west4.
    Observed Generation:   1
    Reason:                QuotaExceeded
    Status:                False
    Type:                  Provisioned
…

En este ejemplo, GKE no puede implementar nodos porque no hay suficiente cuota en la región de europe-west4.

Establece la configuración de interrupción para grupos de nodos con cargas de trabajo mediante el programador dinámico de cargas de trabajo

Las cargas de trabajo que requieren la disponibilidad de todos los nodos, o de la mayoría de los nodos, en un grupo de nodos son sensibles a las expulsiones. La reparación o actualización automática de un nodo aprovisionado mediante ProvisioningRequest API no es compatible porque estas operaciones expulsan todas las cargas de trabajo que se ejecutan en ese nodo y las vuelven no programables.

Para minimizar las interrupciones en las cargas de trabajo en ejecución con el programador dinámico de cargas de trabajo, recomendamos las siguientes medidas:

  • Según la inscripción del canal de versiones de tu clúster, usa las siguientes prácticas recomendadas para evitar que las actualizaciones automáticas de nodos interrumpan tus cargas de trabajo:
  • Inhabilita la reparación automática de nodos.
  • Usa las exclusiones y los períodos de mantenimiento para minimizar las interrupciones para ejecutar cargas de trabajo, a la vez que garantizas que haya un período en el que GKE pueda interrumpir el grupo de nodos para el mantenimiento automático. Si usas estas herramientas de mantenimiento, debes establecer un período específico en el que GKE pueda interrumpir el grupo de nodos, por lo que te recomendamos que configures este período para cuando no haya cargas de trabajo en ejecución.
  • Para garantizar que tu grupo de nodos permanezca actualizado, te recomendamos que actualices de forma manual tu grupo de nodos cuando no haya solicitudes activas del programador de cargas de trabajo dinámicas y el nodo el grupo está vacío.

Limitaciones

  • No se admite la antiafinidad entre Pods. El escalador automático del clúster no tiene en cuenta las reglas de antiafinidad entre Pods durante el aprovisionamiento de nodos, lo que puede generar cargas de trabajo no programables. Esto puede ocurrir cuando se aprovisionan nodos para dos o más objetos del Programador de cargas de trabajo dinámicos en el mismo grupo de nodos.
  • Solo se admiten los nodos de GPU.
  • Las reservas no son compatibles con el programador dinámico de cargas de trabajo. Debes especificar --reservation-affinity=none cuando creas el grupo de nodos. El programador de cargas de trabajo dinámicas solo requiere y admite la política de ubicación ANY para el ajuste de escala automático del clúster.
  • Una sola solicitud del programador dinámico de cargas de trabajo puede crear hasta 1,000 VM, que es la cantidad máxima de nodos por zona para un solo grupo de nodos.
  • GKE usa la cuota ACTIVE_RESIZE_REQUESTS de Compute Engine para controlar la cantidad de solicitudes del programador dinámico de cargas de trabajo pendientes en una cola. De forma predeterminada, esta cuota tiene un límite de 100 a nivel de proyecto de Google Cloud. Si intentas crear una solicitud de Dynamic Workload Scheduler superior a esta cuota, la solicitud nueva fallará.
  • Los grupos de nodos que usan el programador dinámico de Workload son sensibles a las interrupciones, ya que los nodos se aprovisionan juntos. Si quieres obtener más información, consulta Establece la configuración de interrupción para grupos de nodos con cargas de trabajo mediante el programador dinámico de cargas de trabajo.
  • Es posible que veas VMs adicionales de corta duración adicionales en la consola de Google Cloud. Este comportamiento está previsto porque Compute Engine podría crear y quitar VMs de forma oportuna hasta que la capacidad de aprovisionar todas las máquinas necesarias esté disponible.
  • La integración del programador de cargas de trabajo dinámico solo admite un PodSet. Si deseas mezclar diferentes plantillas de pod, usa la que tenga más recursos solicitados. No se admite la combinación de diferentes tipos de máquinas, como VM con diferentes tipos de GPU.

¿Qué sigue?