Cómo asignar dispositivos de forma dinámica a cargas de trabajo con DRA


En esta página, se explica cómo implementar cargas de trabajo de asignación dinámica de recursos (DRA) en tus clústeres de Google Kubernetes Engine. En esta página, crearás un objeto ResourceClaimTemplate para solicitar hardware con DRA y, luego, implementarás una carga de trabajo básica para demostrar cómo Kubernetes asigna hardware de forma flexible en tus Pods.

Esta página está dirigida 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 asignación dinámica de recursos

La DRA es una función integrada de Kubernetes que te permite solicitar, asignar y compartir hardware de forma flexible en tu clúster entre Pods y contenedores. Para obtener más información, consulta Acerca de la asignación dinámica de recursos.

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 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 los objetos ResourceClaim y ResourceClaimTemplate, 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 información más detallada, consulta la documentación de Kubernetes.ResourceClaimTemplateSpec

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.32.1-gke.1489001 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 gcloud components update para obtener la versión más reciente.

Usa DRA para implementar cargas de trabajo

Para solicitar la asignación de dispositivos por Pod, primero debes crear un objeto ResourceClaimTemplate que genere un objeto ResourceClaim para describir tu solicitud de GPU o TPU, que Kubernetes usa como plantilla para crear nuevos objetos ResourceClaim para cada Pod en una carga de trabajo. Cuando especificas ResourceClaimTemplate en una carga de trabajo, Kubernetes asigna los recursos solicitados y programa los Pods en los nodos correspondientes.

GPU

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

    apiVersion: resource.k8s.io/v1beta1
    kind: ResourceClaimTemplate
    metadata:
      name: gpu-claim-template
    spec:
      spec:
        devices:
          requests:
          - name: single-gpu
            deviceClassName: gpu.nvidia.com
            allocationMode: ExactCount
            count: 1
    
  2. Crea 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: ["while [ 1 ]; do date; echo $(nvidia-smi -L || echo Waiting...); sleep 60; done"]
            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/v1beta1
    kind: ResourceClaimTemplate
    metadata:
      name: tpu-claim-template
    spec:
      spec:
        devices:
          requests:
          - name: all-tpus
            deviceClassName: tpu.google.com
            allocationMode: All
    

    Este ResourceClaimTemplate solicita que GKE asigne un grupo de nodo TPU completo a cada ResourceClaim.

  2. Crea 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, consulta ResourceClaim o revisa los registros de tu Pod.

GPU

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

    kubectl get resourceclaims
    

    El resultado debe parecerse al siguiente:

    NAME                                               STATE                AGE
    dra-gpu-example-64b75dc6b-x8bd6-single-gpu-jwwdh   allocated,reserved   9s
    
  2. Para obtener más detalles sobre el hardware asignado al Pod, ejecuta el siguiente comando:

    kubectl describe resourceclaims RESOURCECLAIM
    

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

    El resultado debe parecerse al siguiente:

    Name:         dra-gpu-example-64b75dc6b-x8bd6-single-gpu-jwwdh
    Namespace:    default
    Labels:       <none>
    Annotations:  resource.kubernetes.io/pod-claim-name: single-gpu
    API Version:  resource.k8s.io/v1beta1
    Kind:         ResourceClaim
    Metadata:
      Creation Timestamp:  2025-03-31T17:11:37Z
      Finalizers:
        resource.kubernetes.io/delete-protection
      Generate Name:  dra-gpu-example-64b75dc6b-x8bd6-single-gpu-
      Owner References:
        API Version:           v1
        Block Owner Deletion:  true
        Controller:            true
        Kind:                  Pod
        Name:                  dra-gpu-example-64b75dc6b-x8bd6
        UID:                   cb3cb1db-e62a-4961-9967-cdc7d599105b
      Resource Version:        12953269
      UID:                     3e0c3925-e15a-40e9-b552-d03610fff040
    Spec:
      Devices:
        Requests:
          Allocation Mode:    ExactCount
          Count:              1
          Device Class Name:  gpu.nvidia.com
          Name:               single-gpu
    Status:
      Allocation:
        Devices:
          Results:
            Admin Access:  <nil>
            Device:        gpu-0
            Driver:        gpu.nvidia.com
            Pool:          gke-cluster-gpu-pool-11026a2e-zgt1
            Request:       single-gpu
        Node Selector:
          # lines omitted for clarity
      Reserved For:
        Name:      dra-gpu-example-64b75dc6b-x8bd6
        Resource:  pods
        UID:       cb3cb1db-e62a-4961-9967-cdc7d599105b
    Events:        <none>
    
  3. Para obtener los registros de la carga de trabajo que implementaste, ejecuta el siguiente comando:

    kubectl logs deployment/dra-gpu-example --all-pods=true | grep "GPU"
    

    El resultado debe parecerse 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 asignó una GPU al Pod.

TPU

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

    kubectl get resourceclaims | grep dra-tpu-example
    

    El resultado debe parecerse al siguiente:

    NAME                                               STATE                AGE
    dra-tpu-example-64b75dc6b-x8bd6-all-tpus-jwwdh     allocated,reserved   9s
    
  2. Para obtener más detalles sobre el hardware asignado al Pod, ejecuta el siguiente comando:

    kubectl describe resourceclaims RESOURCECLAIM -o yaml
    

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

    El resultado debe parecerse 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. Para obtener los registros de la carga de trabajo que implementaste, ejecuta el siguiente comando:

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

    El resultado debe parecerse 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
    

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

¿Qué sigue?