Atribua dinamicamente dispositivos a cargas de trabalho com a DRA


Esta página explica como implementar cargas de trabalho de atribuição dinâmica de recursos (DRA) nos seus clusters do Google Kubernetes Engine. Nesta página, vai criar um ResourceClaimTemplate para pedir hardware com DRA e, em seguida, implementar uma carga de trabalho básica para demonstrar como o Kubernetes atribui hardware de forma flexível aos seus pods.

Esta página destina-se a operadores de aplicações e engenheiros de dados que executam cargas de trabalho como IA/ML ou computação de alto desempenho (HPC).

Acerca da atribuição dinâmica de recursos

A DRA é uma funcionalidade do Kubernetes incorporada que lhe permite pedir, atribuir e partilhar hardware de forma flexível no seu cluster entre pods e contentores. Para mais informações, consulte o artigo Acerca da atribuição dinâmica de recursos.

Acerca do pedido de dispositivos com DRA

Quando configura a sua infraestrutura do GKE para o DRA, os controladores do DRA nos seus nós criam objetos DeviceClass no cluster. Uma DeviceClass define uma categoria de dispositivos, como GPUs, que estão disponíveis para pedido para cargas de trabalho. O administrador da plataforma pode implementar opcionalmente DeviceClasses adicionais que limitam os dispositivos que pode pedir em cargas de trabalho específicas.

Para pedir dispositivos num DeviceClass, crie um dos seguintes objetos:

  • ResourceClaim: Uma ResourceClaim permite que um Pod ou um utilizador peça recursos de hardware filtrando determinados parâmetros numa DeviceClass.
  • ResourceClaimTemplate: Um ResourceClaimTemplate define um modelo que os Pods podem usar para criar automaticamente novos ResourceClaims por Pod.

Para mais informações sobre os objetos ResourceClaim e ResourceClaimTemplate, consulte Quando usar ResourceClaims e ResourceClaimTemplates.

Os exemplos nesta página usam um ResourceClaimTemplate básico para pedir a configuração do dispositivo especificada. Para obter informações mais detalhadas, consulte a ResourceClaimTemplateSpec documentação do Kubernetes.

Limitações

  • A administração de contas automática de nós não é suportada.
  • Os clusters do Autopilot não suportam o DRA.
  • Não pode usar as seguintes funcionalidades de partilha de GPU:
    • GPUs de partilha de tempo
    • GPUs de várias instâncias
    • Serviço multiprocessos (MPS)

Requisitos

Para usar o DRA, a versão do GKE tem de ser a 1.32.1-gke.1489001 ou posterior.

Também deve conhecer os seguintes requisitos e limitações:

Antes de começar

Antes de começar, certifique-se de que realizou as seguintes tarefas:

  • Ative a API Google Kubernetes Engine.
  • Ative a API Google Kubernetes Engine
  • Se quiser usar a CLI gcloud para esta tarefa, instale-a e, em seguida, inicialize-a. Se instalou anteriormente a CLI gcloud, execute gcloud components update para obter a versão mais recente.

Use o DRA para implementar cargas de trabalho

Para pedir a atribuição de dispositivos por pod, primeiro, cria um ResourceClaimTemplate que produz um ResourceClaim para descrever o seu pedido de GPUs ou TPUs, que o Kubernetes usa como um modelo para criar novos objetos ResourceClaim para cada pod numa carga de trabalho. Quando especifica o ResourceClaimTemplate numa carga de trabalho, o Kubernetes atribui os recursos pedidos e agenda os pods nos nós correspondentes.

GPU

  1. Guarde o seguinte manifesto 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. Crie o ResourceClaimTemplate:

    kubectl create -f claim-template.yaml
    
  3. Para criar uma carga de trabalho que faça referência ao ResourceClaimTemplate, guarde o seguinte manifesto 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. Implemente a carga de trabalho:

    kubectl create -f dra-gpu-example.yaml
    

TPU

  1. Guarde o seguinte manifesto 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 comando ResourceClaimTemplate pede ao GKE que atribua um conjunto de nós da TPU inteiro a cada ResourceClaim.

  2. Crie o ResourceClaimTemplate:

    kubectl create -f claim-template.yaml
    
  3. Para criar uma carga de trabalho que faça referência ao ResourceClaimTemplate, guarde o seguinte manifesto 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. Implemente a carga de trabalho:

    kubectl create -f dra-tpu-example.yaml
    

Valide a atribuição de hardware

Pode verificar se as suas cargas de trabalho receberam hardware consultando o ResourceClaim ou analisando os registos do seu pod.

GPU

  1. Obtenha o ResourceClaim associado à carga de trabalho que implementou:

    kubectl get resourceclaims
    

    O resultado deve ser semelhante ao seguinte:

    NAME                                               STATE                AGE
    dra-gpu-example-64b75dc6b-x8bd6-single-gpu-jwwdh   allocated,reserved   9s
    
  2. Para obter mais detalhes sobre o hardware atribuído ao Pod, execute o seguinte comando:

    kubectl describe resourceclaims RESOURCECLAIM
    

    Substitua RESOURCECLAIM pelo nome completo do ResourceClaim que obteve do resultado do passo anterior.

    O resultado deve ser semelhante ao seguinte:

    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 obter registos da carga de trabalho que implementou, execute o seguinte comando:

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

    O resultado deve ser semelhante ao seguinte:

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

    O resultado destes passos mostra que o GKE atribuiu uma GPU ao pod.

TPU

  1. Obtenha o ResourceClaim associado à carga de trabalho que implementou:

    kubectl get resourceclaims | grep dra-tpu-example
    

    O resultado deve ser semelhante ao seguinte:

    NAME                                               STATE                AGE
    dra-tpu-example-64b75dc6b-x8bd6-all-tpus-jwwdh     allocated,reserved   9s
    
  2. Para obter mais detalhes sobre o hardware atribuído ao Pod, execute o seguinte comando:

    kubectl describe resourceclaims RESOURCECLAIM -o yaml
    

    Substitua RESOURCECLAIM pelo nome completo do ResourceClaim que obteve do resultado do passo anterior.

    O resultado deve ser semelhante ao seguinte:

    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 obter registos da carga de trabalho que implementou, execute o seguinte comando:

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

    O resultado deve ser semelhante ao seguinte:

    [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
    

    O resultado destes passos indica que todas as TPUs num conjunto de nós foram atribuídas ao pod.

O que se segue?