Ejecutar una carga de trabajo a gran escala con inicio flexible y aprovisionamiento en cola

En esta página se muestra cómo optimizar la disponibilidad de GPUs para cargas de trabajo de IA y por lotes a gran escala con GPUs mediante el inicio flexible con aprovisionamiento en cola, que se basa en Dynamic Workload Scheduler.

Antes de leer esta página, asegúrese de que conoce los siguientes conceptos:

Esta guía está dirigida a ingenieros de aprendizaje automático, administradores y operadores de plataformas, y especialistas en datos e IA que estén interesados en usar las funciones de orquestación de contenedores de Kubernetes para ejecutar cargas de trabajo por lotes. Para obtener más información sobre los roles habituales y las tareas de ejemplo a las que hacemos referencia en el contenido, consulta Roles y tareas habituales de los usuarios de GKE. Google Cloud

Cómo funciona la opción de inicio flexible con aprovisionamiento en cola

Con la opción de inicio flexible con aprovisionamiento en cola, GKE asigna todos los recursos solicitados al mismo tiempo. Flex-start con aprovisionamiento en cola usa las siguientes herramientas:

  • La función de inicio flexible con aprovisionamiento en cola se basa en Dynamic Workload Scheduler, combinado con la definición de recurso personalizado (CRD) Provisioning Request. Estas herramientas gestionan la capacidad asignada en función de los recursos disponibles y los requisitos de tu carga de trabajo.
  • (Opcional) Kueue automatiza el ciclo de vida de flex-start con solicitudes de aprovisionamiento en cola. Kueue implementa la cola de trabajos y gestiona automáticamente el ciclo de vida de las solicitudes de aprovisionamiento.

Para usar flex-start con el aprovisionamiento en cola, debes añadir las marcas --flex-start y --enable-queued-provisioning al crear el grupo de nodos.

Práctica recomendada:

Usa flex-start con aprovisionamiento en cola para cargas de trabajo de IA y por lotes a gran escala cuando tus cargas de trabajo cumplan los siguientes criterios:

  • Tus cargas de trabajo tienen horas de inicio flexibles.
  • Tus cargas de trabajo deben ejecutarse en varios nodos simultáneamente.

Para cargas de trabajo más pequeñas que se pueden ejecutar en un solo nodo, usa máquinas virtuales de inicio flexible. Para obtener más información sobre el aprovisionamiento de GPUs en GKE, consulta Obtener aceleradores para cargas de trabajo de IA.

Antes de empezar

Antes de empezar, asegúrate de que has realizado las siguientes tareas:

  • Habilita la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Si quieres usar Google Cloud CLI para esta tarea, instálala y, a continuación, inicialízala. Si ya has instalado la gcloud CLI, obtén la versión más reciente ejecutando gcloud components update.

Usar grupos de nodos con flex-start con aprovisionamiento en cola

Esta sección solo se aplica a los clústeres estándar.

Puede usar cualquiera de los siguientes métodos para indicar que flex-start con aprovisionamiento en cola puede funcionar con grupos de nodos específicos de su clúster:

Crear un grupo de nodos

Crea un grupo de nodos que tenga flex-start con el aprovisionamiento en cola habilitado mediante la CLI de gcloud:

gcloud 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 \
    --flex-start \
    --enable-autoscaling  \
    --num-nodes=0   \
    --total-max-nodes TOTAL_MAX_NODES  \
    --location-policy=ANY  \
    --reservation-affinity=none  \
    --no-enable-autorepair

Haz los cambios siguientes:

  • NODEPOOL_NAME: el nombre que elijas para el grupo de nodos.
  • CLUSTER_NAME: el nombre del clúster.
  • LOCATION: la región de Compute Engine del clúster, como us-central1.
  • GPU_TYPE: el tipo de GPU.
  • AMOUNT: número de GPUs que se van a asociar a los nodos del grupo de nodos.
  • DRIVER_VERSION: la versión del controlador de NVIDIA que se va a instalar. Puede ser uno de los siguientes:
    • default: instala la versión predeterminada del controlador para tu versión de GKE.
    • latest: instala la versión más reciente del controlador disponible para tu versión de GKE. Solo disponible para los nodos que usan Container-Optimized OS.
  • TOTAL_MAX_NODES: número máximo de nodos que se pueden escalar automáticamente en todo el grupo de nodos.
  • MACHINE_TYPE: el tipo de máquina de Compute Engine de tus nodos.

    Práctica recomendada:

    Usa un tipo de máquina optimizado para aceleradores para mejorar el rendimiento y la eficiencia de las cargas de trabajo de IA y aprendizaje automático.

También puedes usar las siguientes marcas:

  • --node-locations=COMPUTE_ZONES: lista separada por comas de una o varias 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 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:

  • La marca --flex-start combinada con la marca --enable-queued-provisioning indica a GKE que cree un grupo de nodos con inicio flexible con el aprovisionamiento en cola habilitado y que añada el taint cloud.google.com/gke-queued al grupo de nodos.
  • GKE permite el aprovisionamiento en cola y el autoescalado de clústeres.
  • El grupo de nodos tiene inicialmente cero nodos.
  • La marca --no-enable-autorepair inhabilita las reparaciones automáticas, lo que podría interrumpir las cargas de trabajo que se ejecutan en los nodos reparados.

Habilitar el aprovisionamiento automático de nodos para crear grupos de nodos de inicio flexible con aprovisionamiento en cola

Puedes usar el aprovisionamiento automático de nodos para gestionar grupos de nodos de inicio flexible con aprovisionamiento en cola en clústeres que ejecuten la versión 1.29.2-gke.1553000 o posterior. Cuando habilitas el aprovisionamiento automático de nodos, GKE crea grupos de nodos con los recursos necesarios para la carga de trabajo asociada.

Para habilitar el aprovisionamiento automático de nodos, ten en cuenta los siguientes ajustes y completa los pasos que se indican en Configurar límites de GPU:

  • Especifica los recursos necesarios para el inicio flexible con aprovisionamiento en cola cuando habilites la función. Para ver una lista de los resourceTypes disponibles, ejecuta el comando gcloud compute accelerator-types list.
  • Usa la marca --no-enable-autoprovisioning-autorepair para inhabilitar la reparación automática de nodos.
  • Permite que GKE instale automáticamente los controladores de GPU en los nodos de GPU aprovisionados automáticamente. Para obtener más información, consulta Instalar controladores mediante el aprovisionamiento automático de nodos con GPUs.

Ejecuta tus cargas de trabajo por lotes y de IA con inicio flexible y aprovisionamiento en cola

Para ejecutar cargas de trabajo por lotes con inicio flexible y aprovisionamiento en cola, usa cualquiera de las siguientes configuraciones:

Práctica recomendada:

Usa Kueue para ejecutar tus cargas de trabajo por lotes y de IA con inicio flexible y aprovisionamiento en cola.

Flex-start con aprovisionamiento en cola para trabajos con Kueue

En las siguientes secciones se muestra cómo configurar flex-start con aprovisionamiento en cola para los trabajos con Kueue:

  • Empieza con la configuración de un grupo de nodos de aprovisionamiento en cola.
  • Reserva e inicio flexible con configuración de grupo de nodos de aprovisionamiento en cola.

En esta sección se usan los ejemplos del directorio dws-examples del repositorio ai-on-gke. Hemos publicado las muestras en el directorio dws-examples con la licencia Apache 2.

Debes tener permisos de administrador para instalar Kueue. Para obtenerlos, asegúrate de que se te ha concedido el rol de gestión de identidades y accesos roles/container.admin. Para obtener más información sobre los roles de gestión de identidades y accesos de GKE, consulta la guía para crear políticas de permisos de gestión de identidades y accesos.

Prepara tu 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 la última versión de Kueue en tu clúster:

    VERSION=KUEUE_VERSION
    kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/$VERSION/manifests.yaml
    

    Sustituye KUEUE_VERSION por la versión más reciente de Kueue.

Si usas Kueue en una versión anterior a 0.7.0, cambia la configuración de la función de Kueue definiendo la función ProvisioningACC en true. Consulta los feature gates de Kueue para obtener una explicación más detallada y los valores predeterminados de los gates. Para obtener más información sobre la instalación de Kueue, consulta Instalación.

Crear los recursos de Kueue para la configuración solo del grupo de nodos de Dynamic Workload Scheduler

Con el siguiente manifiesto, se crea una cola a nivel de clúster llamada dws-cluster-queue y el espacio de nombres LocalQueue llamado dws-local-queue. Los trabajos que hacen referencia a la cola dws-cluster-queue de este espacio de nombres usan flex-start con aprovisionamiento en cola 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", "ephemeral-storage"]
      flavors:
        - name: "default-flavor"
          resources:
            - name: "cpu"
              nominalQuota: 1000000000 # "Infinite" quota
            - name: "memory"
              nominalQuota: 1000000000Gi # "Infinite" quota
            - name: "nvidia.com/gpu"
              nominalQuota: 1000000000 # "Infinite" quota
            - name: "ephemeral-storage"
              nominalQuota: 1000000000Ti # "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"
---
apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
  labels:
    control-plane: controller-manager
  name: controller-manager-metrics-monitor
  namespace: kueue-system
spec:
  endpoints:
    - path: /metrics
      port: 8080
      scheme: http
      interval: 30s
  selector:
    matchLabels:
      control-plane: controller-manager
---

La cola de este clúster tiene límites de cuota altos y solo está habilitada la integración de inicio flexible con aprovisionamiento en cola. Para obtener más información sobre las APIs de Kueue y cómo configurar los límites, consulta Conceptos de Kueue.

Implementa LocalQueue:

kubectl create -f ./dws-queues.yaml

El resultado debería ser 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 quieres ejecutar trabajos que usen flex-start con aprovisionamiento en cola en otros espacios de nombres, puedes crear LocalQueues adicionales con la plantilla anterior.

Ejecutar una tarea

En el siguiente manifiesto, el trabajo de ejemplo usa flex-start con aprovisionamiento en cola:

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

Este manifiesto incluye los siguientes campos, que son relevantes para la configuración de inicio flexible con aprovisionamiento en cola:

  • La etiqueta kueue.x-k8s.io/queue-name: dws-local-queue indica a GKE que Kueue es responsable de orquestar ese trabajo. Esta etiqueta también define la cola en la que se pone en cola el trabajo.
  • La marca suspend: true indica a GKE que cree el recurso Job, pero que aún no programe los pods. Kueue cambia esa marca a false cuando los nodos están listos para ejecutar el trabajo.
  • nodeSelector indica 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 la tarea:

    kubectl create -f ./job.yaml
    

    El resultado debería ser similar al siguiente:

    job.batch/sample-job created
    
  2. Comprueba el estado de tu tarea:

    kubectl describe job sample-job
    

    El resultado debería ser 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 opción de inicio flexible con aprovisionamiento en cola con integración de Kueue también admite otros tipos de cargas de trabajo disponibles en el ecosistema de código abierto, como los siguientes:

  • RayJob
  • JobSet v0.5.2 o versiones posteriores
  • Kubeflow MPIJob, TFJob y PyTorchJob.
  • Pods de Kubernetes que usan con frecuencia los orquestadores de flujo de trabajo
  • Miniclúster de Flux

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

Crear los recursos de Kueue para configurar la reserva y el grupo de nodos de Dynamic Workload Scheduler

Con el siguiente manifiesto, se crean dos ResourceFlavors vinculados a dos grupos de nodos diferentes: reservation-nodepool y dws-nodepool. Los nombres de estos grupos de nodos son solo ejemplos. Modifica estos nombres según la configuración de tu grupo de nodos. Además, con la configuración ClusterQueue, los trabajos entrantes intentan usar reservation-nodepool y, si no hay capacidad, estos trabajos usan Dynamic Workload Scheduler para obtener los recursos de GPU.

apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: "reservation"
spec:
  nodeLabels:
    cloud.google.com/gke-nodepool: "reservation-nodepool" # placeholder value
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ResourceFlavor
metadata:
  name: "dws"
spec:
  nodeLabels:
    cloud.google.com/gke-nodepool: "dws-nodepool" # placeholder value
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
  name: "cluster-queue"
spec:
  namespaceSelector: {} # match all.
  resourceGroups:
    - coveredResources: ["cpu", "memory", "nvidia.com/gpu"]
      flavors:
        - name: "reservation" # first we try reservation
          resources:
            - name: "cpu"
              nominalQuota: 9
            - name: "memory"
              nominalQuota: 36Gi
            - name: "nvidia.com/gpu"
              nominalQuota: 9
        - name: "dws" # if reservation is saturated we try dws
          resources:
            - name: "cpu"
              nominalQuota: 1000000000 # "Infinite" quota
            - name: "memory"
              nominalQuota: 1000000000Gi # "Infinite" quota
            - name: "nvidia.com/gpu"
              nominalQuota: 1000000000 # "Infinite" quota
  admissionChecksStrategy:
    admissionChecks:
      - name: "dws-prov"
        onFlavors: [dws]
---
apiVersion: kueue.x-k8s.io/v1beta1
kind: LocalQueue
metadata:
  namespace: "default"
  name: "user-queue"
spec:
  clusterQueue: "cluster-queue"
---
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

La cola de este clúster tiene límites de cuota altos y solo está habilitada la integración de inicio flexible con aprovisionamiento en cola. Para obtener más información sobre las APIs de Kueue y cómo configurar los límites, consulta Conceptos de Kueue.

Implementa el manifiesto con el siguiente comando:

kubectl create -f ./dws_and_reservation.yaml

El resultado debería ser similar al siguiente:

resourceflavor.kueue.x-k8s.io/reservation created
resourceflavor.kueue.x-k8s.io/dws created
clusterqueue.kueue.x-k8s.io/cluster-queue created
localqueue.kueue.x-k8s.io/user-queue created
admissioncheck.kueue.x-k8s.io/dws-prov created
provisioningrequestconfig.kueue.x-k8s.io/dws-config created

Ejecutar una tarea

A diferencia de la configuración anterior, este manifiesto no incluye el campo nodeSelector porque lo rellena Kueue en función de la capacidad libre del ClusterQueue.

apiVersion: batch/v1
kind: Job
metadata:
  generateName: sample-job-
  namespace: default
  labels:
    kueue.x-k8s.io/queue-name: user-queue
  annotations:
    provreq.kueue.x-k8s.io/maxRunDurationSeconds: "600"
spec:
  parallelism: 1
  completions: 1
  suspend: true
  template:
    spec:
      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
  1. Ejecuta la tarea:

    kubectl create -f ./job-without-node-selector.yaml
    

    El resultado debería ser similar al siguiente:

    job.batch/sample-job-v8xwm created
    

Para identificar qué grupo de nodos usa tu trabajo, debes averiguar qué ResourceFlavor usa tu trabajo.

Solución de problemas

Para obtener más información sobre la solución de problemas de Kueue, consulta Solucionar problemas de solicitudes de aprovisionamiento en Kueue.

Inicio flexible con aprovisionamiento en cola para trabajos sin Kueue

Definir un objeto ProvisioningRequest

Crea una solicitud a través de la Provisioning Request (Solicitud de aprovisionamiento) para cada trabajo. La función de inicio flexible con aprovisionamiento en cola no inicia los pods, solo aprovisiona los nodos.

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

    Estándar

    apiVersion: v1
    kind: PodTemplate
    metadata:
      name: POD_TEMPLATE_NAME
      namespace: NAMESPACE_NAME
      labels:
        cloud.google.com/apply-warden-policies: "true"
    template:
      spec:
        nodeSelector:
          cloud.google.com/gke-nodepool: NODEPOOL_NAME
          cloud.google.com/gke-flex-start: "true"
        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/API_VERSION
    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
    

    Haz los cambios siguientes:

    • API_VERSION: la versión de la API, v1 o v1beta1. Te recomendamos que uses v1 para disfrutar de la estabilidad y de las funciones más recientes.
    • 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 del ProvisioningRequest. Lo mencionará en la anotación de Pod.
    • MAX_RUN_DURATION_SECONDS: opcionalmente, 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 la opción de inicio flexible con aprovisionamiento en cola. No puedes cambiar este valor después de crear la solicitud. Este campo está disponible en la versión 1.28.5-gke.1355000 o posterior de GKE.
    • COUNT: número de pods solicitados. Los nodos se programan de forma atómica en una zona.
    • POD_TEMPLATE_NAME: el nombre del PodTemplate.
    • NODEPOOL_NAME: el nombre que elijas para el grupo de nodos. Elimínalo si quieres usar un grupo de nodos aprovisionado automáticamente.

    GKE puede aplicar validaciones y mutaciones a los pods durante su creación. La etiqueta cloud.google.com/apply-warden-policies permite que GKE aplique las mismas validaciones y mutaciones a los objetos PodTemplate. Esta etiqueta es necesaria para que GKE calcule los requisitos de recursos de los nodos de tus pods. La integración de flex-start con aprovisionamiento en cola solo admite una especificación PodSet. Si quieres combinar diferentes plantillas de Pod, usa la plantilla que solicite más recursos. No se admite la combinación de diferentes tipos de máquinas, como las máquinas virtuales con diferentes tipos de GPU.

    Aprovisionamiento automático de nodos

    apiVersion: v1
    kind: PodTemplate
    metadata:
      name: POD_TEMPLATE_NAME
      namespace: NAMESPACE_NAME
      labels:
        cloud.google.com/apply-warden-policies: "true"
    template:
      spec:
        nodeSelector:
          cloud.google.com/gke-accelerator: GPU_TYPE
          cloud.google.com/gke-flex-start: "true"
        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/API_VERSION
    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
    

    Haz los cambios siguientes:

    • API_VERSION: la versión de la API, v1 o v1beta1. Te recomendamos que uses v1 para disfrutar de la estabilidad y de las funciones más recientes.
    • 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 del ProvisioningRequest. Lo mencionará en la anotación de Pod.
    • MAX_RUN_DURATION_SECONDS: opcionalmente, 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 la opción de inicio flexible con aprovisionamiento en cola. No puedes cambiar este valor después de crear la solicitud. Este campo está disponible en la versión 1.28.5-gke.1355000 o posterior de GKE.
    • COUNT: número de pods solicitados. Los nodos se programan de forma atómica en una zona.
    • POD_TEMPLATE_NAME: el nombre del PodTemplate.
    • GPU_TYPE: el tipo de hardware de GPU.

    GKE puede aplicar validaciones y mutaciones a los pods durante su creación. La etiqueta cloud.google.com/apply-warden-policies permite que GKE aplique las mismas validaciones y mutaciones a los objetos PodTemplate. Esta etiqueta es necesaria para que GKE calcule los requisitos de recursos de los nodos de tus pods.

  2. Aplica el archivo de manifiesto:

    kubectl apply -f provisioning-request.yaml
    

Configurar los pods

En esta sección se usan trabajos de Kubernetes para configurar los pods. Sin embargo, también puedes usar un JobSet de Kubernetes o cualquier otro framework, como Kubeflow, Ray o controladores personalizados. En la especificación Job, vincula los pods a ProvisioningRequest mediante las siguientes anotaciones:

apiVersion: batch/v1
kind: Job
spec:
  template:
    metadata:
      annotations:
        autoscaling.x-k8s.io/consume-provisioning-request: PROVISIONING_REQUEST_NAME
        autoscaling.x-k8s.io/provisioning-class-name: "queued-provisioning.gke.io"
    spec:
      ...

La clave de anotación de Pod consume-provisioning-request define qué ProvisioningRequest se va a consumir. GKE usa las anotaciones consume-provisioning-request y provisioning-class-name para hacer lo siguiente:

  • Para programar los pods solo en los nodos aprovisionados por flex-start con aprovisionamiento en cola.
  • Para evitar que se contabilicen dos veces las solicitudes de recursos entre los pods y el inicio flexible con aprovisionamiento en cola en el autoescalador de clústeres.
  • Para insertar la anotación safe-to-evict: false, para evitar que el escalador automático de clústeres mueva pods entre nodos e interrumpa los cálculos por lotes. Puedes cambiar este comportamiento especificando safe-to-evict: true en las anotaciones de Pod.

Consultar el estado de una solicitud de aprovisionamiento

El estado de una solicitud de aprovisionamiento define si se puede programar un pod o no. Puedes usar observaciones de Kubernetes para monitorizar los cambios de forma eficiente u otras herramientas que ya utilices para hacer un seguimiento del estado de los objetos de Kubernetes. En la siguiente tabla se describe el estado posible de una solicitud de aprovisionamiento y cada resultado posible:

Estado de la solicitud de aprovisionamiento Descripción Resultado posible
Pendiente La solicitud aún no se ha visto ni procesado. Una vez procesada, la solicitud pasa al estado Accepted o Failed.
Accepted=true La solicitud se ha aceptado y está esperando a que haya recursos disponibles. La solicitud debe pasar al estado Provisioned si se han encontrado recursos y se han aprovisionado nodos, o al estado Failed si no ha sido posible.
Provisioned=true Los nodos están listos. Tienes 10 minutos para iniciar los pods y consumir los recursos aprovisionados. Después de este tiempo, la herramienta de adaptación dinámica del clúster considera que los nodos no son necesarios y los elimina.
Failed=true No se pueden aprovisionar los nodos debido a errores. Failed=true es un estado final. Soluciona el problema de la condición en función de la información de los campos Reason y Message de la condición. Crea y vuelve a intentar una nueva solicitud ProvisioningRequest.
Provisioned=false Los nodos aún no se han aprovisionado.

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

Si Reason=QuotaExceeded, soluciona el problema de la condición en función de este motivo y de la información del campo Message de la condición. Es posible que tengas que solicitar más cuota. Para obtener más información, consulta la sección Comprobar si la solicitud de aprovisionamiento está limitada por la cuota. Esta Reason solo está disponible en GKE 1.29.2-gke.1181000 o versiones posteriores.

Si Reason=ResourcePoolExhausted y Message contiene Expected time is indefinite, selecciona otra zona u otra región, o bien ajusta los recursos solicitados.

Iniciar los pods

Cuando la solicitud Provisioning Request alcance el estado Provisioned=true, puedes ejecutar tu trabajo para iniciar los pods. De esta forma, se evita la proliferación de pods que no se pueden programar para solicitudes pendientes o fallidas, lo que puede afectar al rendimiento de kube-scheduler y de la herramienta de ajuste automático de clústeres.

Si no te importa tener pods que no se puedan programar, puedes crear pods en paralelo con la solicitud Provisioning Request.

Cancelar la solicitud ProvisioningRequest

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

kubectl delete provreq PROVISIONING_REQUEST_NAME -n NAMESPACE

En la mayoría de los casos, al eliminar ProvisioningRequest se impide que se creen nodos. Sin embargo, en función de los tiempos, por ejemplo, si los nodos ya se estaban aprovisionando, es posible que se creen igualmente. En estos casos, el escalador automático de clústeres elimina los nodos al cabo de 10 minutos si no se crea ningún pod.

Solucionar problemas de cuota

Todas las VMs aprovisionadas por solicitudes de aprovisionamiento usan cuotas de recursos preemptibles.

El número de ProvisioningRequests que están en estado Accepted está limitado por una cuota específica. Configura la cuota de cada proyecto, una configuración de cuota por región.

Consultar la cuota en la Google Cloud consola

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

  1. Ve a la página Cuotas de la Google Cloud consola:

    Ir a Cuotas

  2. En el cuadro Filtro, seleccione la propiedad Métrica, introduzca active_resize_requests y pulse Intro.

El valor predeterminado es 100. Para aumentar la cuota, sigue los pasos que se indican en Solicitar un ajuste de cuota.

Comprobar si la solicitud Provisioning Request está limitada por la cuota

Si tu solicitud de aprovisionamiento tarda más de lo previsto en completarse, comprueba que no esté limitada por una cuota. Es posible que tengas que solicitar más cuota.

En el caso de los clústeres que ejecutan la versión 1.29.2-gke.1181000 o posterior, comprueba si hay limitaciones de cuota específicas que impidan que se cumpla tu solicitud:

kubectl describe provreq PROVISIONING_REQUEST_NAME \
    --namespace NAMESPACE

La salida es similar a la 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 desplegar nodos porque no hay suficiente cuota en la región europe-west4.

Migrar grupos de nodos del aprovisionamiento en cola al inicio flexible

La opción de consumo inicio flexible crea VMs de inicio flexible. Para migrar los grupos de nodos que se hayan creado con la marca --enable-queued-provisioning para usar flex-start, sigue estos pasos:

  1. Asegúrate de que el grupo de nodos esté vacío:

    kubectl get nodes -l cloud.google.com/gke-nodepool=NODEPOOL_NAME
    
  2. Actualiza el grupo de nodos a máquinas virtuales de inicio flexible:

    gcloud container node-pools update NODEPOOL_NAME \
      --cluster=CLUSTER_NAME --flex-start
    

Esta operación hace lo siguiente:

  • Actualiza el grupo de nodos a un grupo de nodos de VMs Flex-start.
  • Aplica los precios de los nodos que usan máquinas virtuales de inicio flexible.

Todos los nodos de los clústeres que se ejecutan en la versión 1.32.2-gke.1652000 o posterior, que es la versión mínima de los nodos que usan máquinas virtuales de inicio flexible, usan actualizaciones de corta duración.

Siguientes pasos