Asigna dispositivos de forma dinámica a cargas de trabajo con DRA

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

Este documento está dirigido a los operadores de aplicaciones y los ingenieros de datos que ejecutan cargas de trabajo como IA/AA 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 en tus nodos crean objetos DeviceClass en el clúster. Un DeviceClass define una categoría de dispositivos, como las GPUs, que están disponibles para solicitar cargas de trabajo. De manera opcional, un administrador de la plataforma puede implementar DeviceClasses adicionales que limiten los dispositivos que puedes solicitar en cargas de trabajo específicas.

Para solicitar dispositivos dentro de un DeviceClass, crea uno de los siguientes objetos:

  • ResourceClaim: Un ResourceClaim permite que un Pod o un usuario soliciten recursos de hardware filtrando ciertos parámetros dentro de un 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 del dispositivo especificada. Para obtener más información sobre todos los campos que puedes especificar, consulta la referencia de la API de 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 de uso compartido de GPU:
    • GPU de tiempo compartido
    • GPU de varias instancias
    • Servicio de varios procesos (MPS)

Requisitos

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

También debes conocer los siguientes requisitos y limitaciones:

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 DRA para implementar cargas de trabajo

Para solicitar la asignación de dispositivos por Pod, crea un ResourceClaimTemplate que tenga la configuración del dispositivo que solicitaste, como GPUs de un tipo específico. Cuando implementas una carga de trabajo que hace referencia a ResourceClaimTemplate, Kubernetes crea ResourceClaims para cada Pod de la carga de trabajo según el 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 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. Implementa la carga de trabajo:

    kubectl create -f dra-gpu-example.yaml
    

TPU

  1. Guarda el siguiente 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 TPU, por lo que todas las TPU 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. Implementa la carga de trabajo:

    kubectl create -f dra-tpu-example.yaml
    

Verifica la asignación de hardware

Para verificar que se haya asignado hardware a tus cargas de trabajo, revisa 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 implementaste:

    kubectl get resourceclaims
    

    El resultado es similar a lo 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
    

    Reemplaza RESOURCECLAIM por el nombre completo del objeto ResourceClaim que obtuviste del resultado del paso anterior.

    El resultado es similar a lo 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 implementaste:

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

    El resultado es similar a lo 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 asignó una GPU al contenedor.

TPU

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

    kubectl get resourceclaims | grep dra-tpu-example
    

    El resultado es similar a lo 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
    

    Reemplaza RESOURCECLAIM por el nombre completo del objeto ResourceClaim que obtuviste del resultado del paso anterior.

    El resultado es similar a lo 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 implementaste:

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

    El resultado es similar a lo 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
    

    El resultado de estos pasos indica que todas las TPU de un grupo de nodos se asignaron al Pod.

¿Qué sigue?