Asignar dispositivos dinámicamente a cargas de trabajo con DRA


En esta página se explica cómo desplegar 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 ResourceClaimTemplate para solicitar hardware con DRA y, a continuación, desplegarás una carga de trabajo básica para mostrar cómo Kubernetes asigna hardware de forma flexible a tus pods.

Esta página está dirigida a operadores de aplicaciones y ingenieros de datos que ejecutan cargas de trabajo como IA/ML o computación de alto rendimiento (HPC).

Acerca de la asignación dinámica de recursos

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 el artículo 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 de tus nodos crean objetos DeviceClass en el clúster. Una DeviceClass define una categoría de dispositivos, como GPUs, que se pueden solicitar para 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 en un DeviceClass, crea uno de los siguientes objetos:

  • ResourceClaim: ResourceClaim permite que un pod o un usuario soliciten recursos de hardware filtrando determinados parámetros en un DeviceClass.
  • ResourceClaimTemplate: 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 ResourceClaimTemplateSpecdocumentación de Kubernetes.

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:
    • Compartir GPUs por tiempo
    • GPUs con varias instancias
    • Servicio multiproceso (MPS)

Requisitos

Para usar DRA, tu versión de GKE debe ser la 1.32.1-gke.1489001 o una posterior.

También debe conocer los siguientes requisitos y limitaciones:

Antes de empezar

Antes de empezar, asegúrate de haber 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 DRA para desplegar cargas de trabajo

Para solicitar la asignación de dispositivos por pod, primero debes crear un ResourceClaimTemplate que genere un ResourceClaim para describir tu solicitud de GPUs o TPUs. Kubernetes usa este ResourceClaim como plantilla para crear nuevos objetos ResourceClaim para cada pod de 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 archivo de 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 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: ["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. 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/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 nodos de TPU completo a cada ResourceClaim.

  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 ResourceClaim o los registros de tu pod.

GPU

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

    kubectl get resourceclaims
    

    La salida debería ser similar a la siguiente:

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

    kubectl describe resourceclaims RESOURCECLAIM
    

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

    La salida debería ser similar a la 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 has desplegado, ejecuta el siguiente comando:

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

    La salida debería ser similar a la 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 pod.

TPU

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

    kubectl get resourceclaims | grep dra-tpu-example
    

    La salida debería ser similar a la siguiente:

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

    kubectl describe resourceclaims RESOURCECLAIM -o yaml
    

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

    La salida debería ser similar a la 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 has desplegado, ejecuta el siguiente comando:

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

    La salida debería ser similar a la 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