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

En esta página, se muestra cómo optimizar la capacidad de obtención de la GPU para cargas de trabajo de IA y por lotes a gran escala con GPU usando el inicio flexible con aprovisionamiento en cola impulsado por el Programador dinámico de cargas de trabajo.

Antes de leer esta página, asegúrate de estar familiarizado con lo siguiente:

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

Cómo funciona el inicio flexible con aprovisionamiento en cola

Con el inicio flexible con aprovisionamiento en cola, GKE asigna todos los recursos solicitados al mismo tiempo. El inicio flexible con aprovisionamiento en cola usa las siguientes herramientas:

Para usar el inicio flexible con el aprovisionamiento en cola, debes agregar las marcas --flex-start y --enable-queued-provisioning cuando crees el grupo de nodos.

Práctica recomendada:

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

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

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

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 el comando gcloud components update para obtener la versión más reciente. Es posible que las versiones anteriores de gcloud CLI no admitan la ejecución de los comandos que se describen en este documento.

Usa grupos de nodos con inicio flexible y aprovisionamiento en cola

Esta sección solo se aplica a los clústeres de Standard.

Puedes usar cualquiera de los siguientes tres métodos para designar que el aprovisionamiento en cola con inicio flexible pueda funcionar con grupos de nodos específicos en tu clúster:

Crea un grupo de nodos

Crea un grupo de nodos que tenga habilitado el inicio flexible con aprovisionamiento en cola usando gcloud CLI:

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

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.

    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/AA.

De manera opcional, puedes usar las siguientes marcas:

  • --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 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 y con el aprovisionamiento en cola habilitado, y que agregue el taint cloud.google.com/gke-queued al grupo de nodos.
  • 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 --no-enable-autorepair inhabilita las reparaciones automáticas, lo que podría interrumpir las cargas de trabajo que se ejecutan en nodos reparados.

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

Puedes usar el aprovisionamiento automático de nodos para administrar los grupos de nodos para el inicio flexible con aprovisionamiento en cola para clústeres que ejecutan la versión 1.29.2-gke.1553000 o una 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, considera la siguiente configuración y completa los pasos en Configura los límites de GPU:

  • Especifica los recursos necesarios para el inicio flexible con aprovisionamiento en cola cuando habilites la función. Para enumerar 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 Instala controladores con el aprovisionamiento automático de nodos con GPU.

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.

Inicio flexible con aprovisionamiento en cola para trabajos con Kueue

En las siguientes secciones, se muestra cómo configurar el inicio flexible con aprovisionamiento en cola para trabajos con Kueue:

  • Configuración de un grupo de nodos de inicio flexible con aprovisionamiento en cola.
  • Configuración de un grupo de nodos con reserva y con inicio flexible con aprovisionamiento en cola.

En esta sección, se usan las muestras del directorio dws-examples del repositorio ai-on-gke. Publicamos las muestras en el directorio dws-examples bajo la licencia Apache2.

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

Prepara el entorno

  1. En Cloud Shell, ejecute 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 versión más reciente 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
    

    Reemplaza 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 del interruptor de función de Kueue estableciendo el interruptor de función ProvisioningACC en true. Consulta los interruptores de funciones de Kueue para obtener una explicación más detallada y los valores de los interruptores predeterminados. Para obtener más información sobre la instalación de Kueue, consulta Instalación.

Crea los recursos de Kueue para la configuración de solo el grupo de nodos del programador dinámico de cargas de trabajo

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 inicio flexible 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 la integración de flex-start con aprovisionamiento en cola está habilitada. 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 es similar a este:

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 flex-start con aprovisionamiento en cola 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 inicio flexible 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

En este manifiesto, se incluyen los siguientes campos relevantes para la configuración de inicio flexible con aprovisionamiento en cola:

  • 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 a este:

    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 de flex-start con aprovisionamiento en cola con Kueue también admite otros tipos de cargas de trabajo disponibles en el ecosistema de código abierto, como las siguientes:

  • RayJob
  • JobSet v0.5.2 o una versión posterior
  • 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.

Crea los recursos de Kueue para la configuración del grupo de nodos de Reservation y Dynamic Workload Scheduler

Con el siguiente manifiesto, crearás 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 de ClusterQueue, los Jobs entrantes intentan usar reservation-nodepool y, si no hay capacidad, estos Jobs 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: "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 la integración de flex-start con aprovisionamiento en cola está habilitada. 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 es similar a este:

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

Ejecuta tu trabajo

A diferencia de la configuración anterior, este manifiesto no incluye el campo nodeSelector porque Kueue lo completa según la capacidad libre en 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 tu trabajo:

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

    El resultado es similar a este:

    job.batch/sample-job-v8xwm created
    

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

Soluciona problemas

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

Inicio flexible con aprovisionamiento en cola para trabajos sin Kueue

Define un objeto ProvisioningRequest

Crea una solicitud a través de la solicitud de aprovisionamiento para cada trabajo. El inicio flexible con aprovisionamiento en cola no inicia los Pods, solo aprovisiona los nodos.

  1. Crea el siguiente 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
    

    Reemplaza lo siguiente:

    • API_VERSION: Es la versión de la API, que puede ser v1 o v1beta1. Recomendamos usar v1 para mayor estabilidad y acceso a 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 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 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 de GKE o una posterior.
    • COUNT: Cantidad de Pods solicitados. Los nodos se programan de forma atómica en una zona.
    • POD_TEMPLATE_NAME: El nombre de PodTemplate.
    • NODEPOOL_NAME: Es el nombre que eliges para el grupo de nodos. Quita este argumento si deseas usar un grupo de nodos aprovisionado de forma automática.

    GKE podría 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 para tus Pods. La integración de flex-start con aprovisionamiento en cola solo admite una especificación de PodSet. Si deseas mezclar diferentes plantillas de Pod, usa la plantilla que solicite la mayor cantidad de recursos. No se admite la combinación de diferentes tipos de máquinas, como VMs 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
    

    Reemplaza lo siguiente:

    • API_VERSION: Es la versión de la API, que puede ser v1 o v1beta1. Recomendamos usar v1 para mayor estabilidad y acceso a 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 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 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 de GKE o una posterior.
    • COUNT: Cantidad de Pods solicitados. Los nodos se programan de forma atómica en una zona.
    • POD_TEMPLATE_NAME: El nombre de PodTemplate.
    • GPU_TYPE: es el tipo de hardware de la GPU.

    GKE podría 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 para tus Pods.

  2. Aplica el manifiesto

    kubectl apply -f provisioning-request.yaml
    

Configura 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 del trabajo, vincula los Pods al ProvisioningRequest con 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 del Pod 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 aprovisionados por el inicio flexible con aprovisionamiento en cola.
  • Para evitar el doble recuento de las solicitudes de recursos entre los Pods y el inicio flexible con aprovisionamiento en cola 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 de una solicitud de aprovisionamiento

El estado de una solicitud de aprovisionamiento 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 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 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 de Provisioning Request nueva.
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 la solicitud de aprovisionamiento está limitada por la cuota. Este Reason solo está disponible con la versión 1.29.2-gke.1181000 de GKE o una posterior.

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

Inicia los Pods

Cuando la solicitud de aprovisionamiento 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 la solicitud de ProvisioningRequest.

Cancela la solicitud de ProvisioningRequest

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.

Soluciona problemas relacionados con las cuotas

Todas las VMs aprovisionadas por las solicitudes de Provisioning Request usan cuotas interrumpibles.

La cantidad de ProvisioningRequests que se encuentran en estado Accepted está limitada por una cuota dedicada. Configuras la cuota para cada proyecto, con una configuración de cuota por región.

Verifica la cuota en la Google Cloud consola

Para verificar 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 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 un ajuste de cuota.

Comprueba si la solicitud de aprovisionamiento está limitada por la cuota

Si tu solicitud de aprovisionamiento 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.

Migra grupos de nodos del aprovisionamiento en cola al inicio flexible

La opción de consumo flex-start crea VMs de inicio flexible. Para migrar los grupos de nodos existentes que se crearon con la marca --enable-queued-provisioning para usar el inicio flexible, 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 VMs 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 de inicio flexible.
  • Se aplica el precio de los nodos que usan VMs de inicio flexible.

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

¿Qué sigue?