Asignar dispositivos dinámicamente a cargas de trabajo con DRA

Puedes solicitar dispositivos de forma flexible para tus cargas de trabajo de Google Kubernetes Engine (GKE) mediante la asignación dinámica de recursos (DRA). En este documento se muestra cómo crear un ResourceClaimTemplate para solicitar dispositivos y, a continuación, crear una carga de trabajo para observar cómo Kubernetes asigna los dispositivos a tus pods de forma flexible.

Este documento está dirigido a operadores de aplicaciones y ingenieros de datos que ejecutan cargas de trabajo como IA/aprendizaje automático o computación de alto rendimiento (HPC).

Acerca de la solicitud de dispositivos con DRA

Cuando configuras tu infraestructura de GKE para DRA, los controladores de DRA de tus nodos crean objetos DeviceClass en el clúster. Un DeviceClass define una categoría de dispositivos, como las GPUs, que se pueden solicitar para las cargas de trabajo. Un administrador de la plataforma puede implementar de forma opcional DeviceClasses adicionales que limiten los dispositivos que puedes solicitar en cargas de trabajo específicas.

Para solicitar dispositivos de una clase de dispositivo, crea uno de los siguientes objetos:

  • ResourceClaim ResourceClaim permite que un pod o un usuario soliciten recursos de hardware filtrando determinados parámetros en una DeviceClass.
  • ResourceClaimTemplate un ResourceClaimTemplate define una plantilla que los pods pueden usar para crear automáticamente nuevos ResourceClaims por pod.

Para obtener más información sobre ResourceClaims y ResourceClaimTemplates, consulta Cuándo usar ResourceClaims y ResourceClaimTemplates.

En los ejemplos de esta página se usa un ResourceClaimTemplate básico para solicitar la configuración de dispositivo especificada. Para obtener más información sobre todos los campos que puedes especificar, consulta la referencia de la API ResourceClaimTemplate.

Limitaciones

  • No se admite el aprovisionamiento automático de nodos.
  • Los clústeres de Autopilot no admiten DRA.
  • No puedes usar las siguientes funciones para compartir la GPU:
    • GPUs de tiempo compartido
    • GPUs con varias instancias
    • Servicio multiproceso (MPS)

Requisitos

Para usar DRA, tu versión de GKE debe ser la 1.34 o una posterior.

También debe conocer los siguientes requisitos y limitaciones:

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 CLI de gcloud, obtén la versión más reciente ejecutando el comando gcloud components update. Es posible que las versiones anteriores de la interfaz de línea de comandos de gcloud no admitan la ejecución de los comandos de este documento.

Usar DRA para desplegar cargas de trabajo

Para solicitar la asignación de dispositivos por Pod, crea un ResourceClaimTemplate que tenga la configuración del dispositivo que has solicitado, como GPUs de un tipo específico. Cuando despliega una carga de trabajo que hace referencia a ResourceClaimTemplate, Kubernetes crea ResourceClaims para cada Pod de la carga de trabajo en función de ResourceClaimTemplate. Kubernetes asigna los recursos solicitados y programa los pods en los nodos correspondientes.

Para solicitar dispositivos en una carga de trabajo con DRA, selecciona una de las siguientes opciones:

GPU

  1. Guarda el siguiente archivo de manifiesto como claim-template.yaml:

    apiVersion: resource.k8s.io/v1
    kind: ResourceClaimTemplate
    metadata:
      name: gpu-claim-template
    spec:
      spec:
        devices:
          requests:
          - name: single-gpu
            exactly:
              deviceClassName: gpu.nvidia.com
              allocationMode: ExactCount
              count: 1
    
  2. Crea el ResourceClaimTemplate:

    kubectl create -f claim-template.yaml
    
  3. Para crear una carga de trabajo que haga referencia a ResourceClaimTemplate, guarda el siguiente manifiesto como dra-gpu-example.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: dra-gpu-example
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: dra-gpu-example
      template:
        metadata:
          labels:
            app: dra-gpu-example
        spec:
          containers:
          - name: ctr
            image: ubuntu:22.04
            command: ["bash", "-c"]
            args: ["echo $(nvidia-smi -L || echo Waiting...)"]
            resources:
              claims:
              - name: single-gpu
          resourceClaims:
          - name: single-gpu
            resourceClaimTemplateName: gpu-claim-template
          tolerations:
          - key: "nvidia.com/gpu"
            operator: "Exists"
            effect: "NoSchedule"
    
  4. Despliega la carga de trabajo:

    kubectl create -f dra-gpu-example.yaml
    

TPU

  1. Guarda el siguiente archivo de manifiesto como claim-template.yaml:

    apiVersion: resource.k8s.io/v1
    kind: ResourceClaimTemplate
    metadata:
      name: tpu-claim-template
    spec:
      spec:
        devices:
          requests:
          - name: all-tpus
            exactly:
              deviceClassName: tpu.google.com
              allocationMode: All
    

    Este ResourceClaimTemplate solicita todas las TPUs, por lo que todas las TPUs de un nodo se asignan a cada ResourceClaim resultante.

  2. Crea el ResourceClaimTemplate:

    kubectl create -f claim-template.yaml
    
  3. Para crear una carga de trabajo que haga referencia a ResourceClaimTemplate, guarda el siguiente manifiesto como dra-tpu-example.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: dra-tpu-example
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: dra-tpu-example
      template:
        metadata:
          labels:
            app: dra-tpu-example
        spec:
          containers:
          - name: ctr
            image: ubuntu:22.04
            command:
              - /bin/sh
              - -c
              - |
                echo "Environment Variables:"
                env
                echo "Sleeping indefinitely..."
                sleep infinity
            resources:
              claims:
              - name: all-tpus
          resourceClaims:
          - name: all-tpus
            resourceClaimTemplateName: tpu-claim-template
          tolerations:
          - key: "google.com/tpu"
            operator: "Exists"
            effect: "NoSchedule"
    
  4. Despliega la carga de trabajo:

    kubectl create -f dra-tpu-example.yaml
    

Verificar la asignación de hardware

Para comprobar que se ha asignado hardware a tus cargas de trabajo, consulta el objeto ResourceClaim o los registros de tu pod. Para verificar la asignación de GPUs o TPUs, selecciona una de las siguientes opciones:

GPU

  1. Obtén el ResourceClaim asociado a la carga de trabajo que has desplegado:

    kubectl get resourceclaims
    

    El resultado debería ser similar al siguiente:

    NAME                                               STATE                AGE
    dra-gpu-example-64b75dc6b-x8bd6-single-gpu-jwwdh   allocated,reserved   9s
    
  2. Obtén más detalles sobre el hardware asignado al pod:

    kubectl describe resourceclaims RESOURCECLAIM
    

    Sustituye RESOURCECLAIM por el nombre completo del ResourceClaim que has obtenido en el paso anterior.

    El resultado debería ser similar al siguiente:

       Name:         dra-gpu-example-68f595d7dc-prv27-single-gpu-qgjq5
       Namespace:    default
       Labels:       <none>
       Annotations:  resource.kubernetes.io/pod-claim-name: single-gpu
       API Version:  resource.k8s.io/v1
       Kind:         ResourceClaim
       Metadata:
       # Multiple lines are omitted here.
       Spec:
         Devices:
           Requests:
             Exactly:
               Allocation Mode:    ExactCount
               Count:              1
               Device Class Name:  gpu.nvidia.com
             Name:                 single-gpu
       Status:
         Allocation:
           Devices:
             Results:
               Device:   gpu-0
               Driver:   gpu.nvidia.com
               Pool:     gke-cluster-1-dra-gpu-pool-b56c4961-7vnm
               Request:  single-gpu
           Node Selector:
             Node Selector Terms:
               Match Fields:
                 Key:       metadata.name
                 Operator:  In
                 Values:
                   gke-cluster-1-dra-gpu-pool-b56c4961-7vnm
         Reserved For:
           Name:      dra-gpu-example-68f595d7dc-prv27
           Resource:  pods
           UID:       e16c2813-08ef-411b-8d92-a72f27ebf5ef
       Events:        <none>
       ```
    
  3. Obtén los registros de la carga de trabajo que has implementado:

    kubectl logs deployment/dra-gpu-example --all-pods=true
    

    El resultado debería ser similar al siguiente:

    [pod/dra-gpu-example-64b75dc6b-x8bd6/ctr] GPU 0: Tesla T4 (UUID: GPU-2087ac7a-f781-8cd7-eb6b-b00943cc13ef)
    

    El resultado de estos pasos muestra que GKE ha asignado una GPU al contenedor.

TPU

  1. Obtén el ResourceClaim asociado a la carga de trabajo que has desplegado:

    kubectl get resourceclaims | grep dra-tpu-example
    

    El resultado debería ser similar al siguiente:

    NAME                                               STATE                AGE
    dra-tpu-example-64b75dc6b-x8bd6-all-tpus-jwwdh     allocated,reserved   9s
    
  2. Obtén más detalles sobre el hardware asignado al pod:

    kubectl describe resourceclaims RESOURCECLAIM -o yaml
    

    Sustituye RESOURCECLAIM por el nombre completo del ResourceClaim que has obtenido en el paso anterior.

    El resultado debería ser similar al siguiente:

    apiVersion: resource.k8s.io/v1beta1
    kind: ResourceClaim
    metadata:
      annotations:
        resource.kubernetes.io/pod-claim-name: all-tpus
      creationTimestamp: "2025-03-04T21:00:54Z"
      finalizers:
      - resource.kubernetes.io/delete-protection
      generateName: dra-tpu-example-59b8785697-k9kzd-all-gpus-
      name: dra-tpu-example-59b8785697-k9kzd-all-gpus-gnr7z
      namespace: default
      ownerReferences:
      - apiVersion: v1
        blockOwnerDeletion: true
        controller: true
        kind: Pod
        name: dra-tpu-example-59b8785697-k9kzd
        uid: c2f4fe66-9a73-4bd3-a574-4c3eea5fda3f
      resourceVersion: "12189603"
      uid: 279b5014-340b-4ef6-9dda-9fbf183fbb71
    spec:
      devices:
        requests:
        - allocationMode: All
          deviceClassName: tpu.google.com
          name: all-tpus
    status:
      allocation:
        devices:
          results:
          - adminAccess: null
            device: "0"
            driver: tpu.google.com
            pool: gke-tpu-2ec29193-bcc0
            request: all-tpus
          - adminAccess: null
            device: "1"
            driver: tpu.google.com
            pool: gke-tpu-2ec29193-bcc0
            request: all-tpus
          - adminAccess: null
            device: "2"
            driver: tpu.google.com
            pool: gke-tpu-2ec29193-bcc0
            request: all-tpus
          - adminAccess: null
            device: "3"
            driver: tpu.google.com
            pool: gke-tpu-2ec29193-bcc0
            request: all-tpus
          - adminAccess: null
            device: "4"
            driver: tpu.google.com
            pool: gke-tpu-2ec29193-bcc0
            request: all-tpus
          - adminAccess: null
            device: "5"
            driver: tpu.google.com
            pool: gke-tpu-2ec29193-bcc0
            request: all-tpus
          - adminAccess: null
            device: "6"
            driver: tpu.google.com
            pool: gke-tpu-2ec29193-bcc0
            request: all-tpus
          - adminAccess: null
            device: "7"
            driver: tpu.google.com
            pool: gke-tpu-2ec29193-bcc0
            request: all-tpus
        nodeSelector:
          nodeSelectorTerms:
          - matchFields:
            - key: metadata.name
              operator: In
              values:
              - gke-tpu-2ec29193-bcc0
      reservedFor:
      - name: dra-tpu-example-59b8785697-k9kzd
        resource: pods
        uid: c2f4fe66-9a73-4bd3-a574-4c3eea5fda3f
    
  3. Obtén los registros de la carga de trabajo que has implementado:

    kubectl logs deployment/dra-tpu-example --all-pods=true | grep "TPU"
    

    El resultado debería ser similar al siguiente:

    [pod/dra-tpu-example-59b8785697-tm2lc/ctr] TPU_CHIPS_PER_HOST_BOUNDS=2,4,1
    [pod/dra-tpu-example-59b8785697-tm2lc/ctr] TPU_TOPOLOGY_WRAP=false,false,false
    [pod/dra-tpu-example-59b8785697-tm2lc/ctr] TPU_SKIP_MDS_QUERY=true
    [pod/dra-tpu-example-59b8785697-tm2lc/ctr] TPU_RUNTIME_METRICS_PORTS=8431,8432,8433,8434,8435,8436,8437,8438
    [pod/dra-tpu-example-59b8785697-tm2lc/ctr] TPU_WORKER_ID=0
    [pod/dra-tpu-example-59b8785697-tm2lc/ctr] TPU_WORKER_HOSTNAMES=localhost
    [pod/dra-tpu-example-59b8785697-tm2lc/ctr] TPU_TOPOLOGY=2x4
    [pod/dra-tpu-example-59b8785697-tm2lc/ctr] TPU_ACCELERATOR_TYPE=v6e-8
    [pod/dra-tpu-example-59b8785697-tm2lc/ctr] TPU_HOST_BOUNDS=1,1,1
    [pod/dra-tpu-example-59b8785697-tm2lc/ctr] TPU_TOPOLOGY_ALT=false
    [pod/dra-tpu-example-59b8785697-tm2lc/ctr] TPU_DEVICE_0_RESOURCE_CLAIM=77e68f15-fa2f-4109-9a14-6c91da1a38d3
    

    La salida de estos pasos indica que todas las TPUs de un grupo de nodos se han asignado al Pod.

Siguientes pasos