הקצאה דינמית של מכשירים לעומסי עבודה באמצעות DRA

אתם יכולים לבקש מכשירים באופן גמיש לעומסי העבודה שלכם ב-Google Kubernetes Engine‏ (GKE) באמצעות הקצאת משאבים דינמית (DRA). במסמך הזה מוסבר איך ליצור ResourceClaimTemplate כדי לבקש מכשירים, ואז ליצור עומס עבודה כדי לראות איך Kubernetes מקצה את המכשירים בצורה גמישה ל-Pods.

המסמך הזה מיועד למפעילים של אפליקציות ולמהנדסי נתונים שמריצים עומסי עבודה כמו AI/ML או מחשוב עתיר ביצועים (HPC).

מידע על בקשת מכשירים באמצעות DRA

כשמגדירים את התשתית של GKE ל-DRA, מנהלי ההתקנים של DRA בצמתים יוצרים אובייקטים מסוג DeviceClass באשכול. ה-DeviceClass מגדיר קטגוריה של מכשירים, כמו GPUs, שאפשר לבקש עבור עומסי עבודה. אדמין בפלטפורמה יכול גם לפרוס DeviceClasses נוספים שמגבילים את המכשירים שאפשר לבקש בעומסי עבודה ספציפיים.

כדי לבקש מכשירים ב-DeviceClass, יוצרים אחד מהאובייקטים הבאים:

  • ResourceClaim: ‫ResourceClaim מאפשר ל-Pod או למשתמש לבקש משאבי חומרה על ידי סינון פרמטרים מסוימים בתוך DeviceClass.
  • ResourceClaimTemplate: תבנית ResourceClaimTemplate מגדירה תבנית שרכיבי Pod יכולים להשתמש בה כדי ליצור באופן אוטומטי ResourceClaim חדש לכל Pod.

מידע נוסף על ResourceClaims ו-ResourceClaimTemplates זמין במאמר מתי כדאי להשתמש ב-ResourceClaims וב-ResourceClaimTemplates.

בדוגמאות שבדף הזה נעשה שימוש ב-ResourceClaimTemplate בסיסי כדי לבקש את הגדרת המכשיר שצוינה. מידע נוסף על כל השדות שאפשר לציין זמין בהפניית API של ResourceClaimTemplate.

מגבלות

  • אין תמיכה בהקצאת צמתים אוטומטית.
  • אשכולות Autopilot לא תומכים ב-DRA.
  • אי אפשר להשתמש בתכונות הבאות של שיתוף GPU:
    • שיתוף זמן ב-GPU
    • יחידות GPU עם כמה מופעים במקביל
    • שירות מרובה תהליכים (MPS)

דרישות

כדי להשתמש ב-DRA, גרסת ה-GKE צריכה להיות גרסה 1.34 ואילך.

חשוב גם להכיר את הדרישות והמגבלות הבאות:

לפני שמתחילים

לפני שמתחילים, חשוב לוודא שביצעתם את הפעולות הבאות:

  • מפעילים את ממשק Google Kubernetes Engine API.
  • הפעלת Google Kubernetes Engine API
  • אם רוצים להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז להפעיל את ה-CLI של gcloud. אם התקנתם בעבר את ה-CLI של gcloud, מריצים את הפקודה gcloud components update כדי לקבל את הגרסה העדכנית. יכול להיות שגרסאות קודמות של ה-CLI של gcloud לא יתמכו בהרצת הפקודות שמופיעות במסמך הזה.

שימוש ב-DRA לפריסת עומסי עבודה

כדי לבקש הקצאת מכשיר לכל Pod, יוצרים ResourceClaimTemplate עם הגדרת המכשיר המבוקשת, כמו מעבדי GPU מסוג מסוים. כשפורסים עומס עבודה שמפנה אל ResourceClaimTemplate, ‏ Kubernetes יוצר ResourceClaims לכל Pod בעומס העבודה על סמך ResourceClaimTemplate. ‫Kubernetes מקצה את המשאבים המבוקשים ומתזמן את ה-Pods בצמתים המתאימים.

כדי לבקש מכשירים בעומס עבודה עם DRA, בוחרים באחת מהאפשרויות הבאות:

GPU

  1. שומרים את קובץ המניפסט הבא בשם 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. יוצרים את ResourceClaimTemplate:

    kubectl create -f claim-template.yaml
    
  3. כדי ליצור עומס עבודה שמפנה אל ResourceClaimTemplate, שומרים את המניפסט הבא בתור 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. פורסים את עומס העבודה:

    kubectl create -f dra-gpu-example.yaml
    

TPU

  1. שומרים את קובץ המניפסט הבא בשם 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
    

    התבנית ResourceClaimTemplate הזו מבקשת את כל יחידות ה-TPU, ולכן כל יחידות ה-TPU בצומת מוקצות לכל ResourceClaim שנוצר.

  2. יוצרים את ResourceClaimTemplate:

    kubectl create -f claim-template.yaml
    
  3. כדי ליצור עומס עבודה שמפנה אל ResourceClaimTemplate, שומרים את המניפסט הבא בתור 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. פורסים את עומס העבודה:

    kubectl create -f dra-tpu-example.yaml
    

אימות הקצאת החומרה

כדי לוודא שהוקצה לכם חומרה לעומסי העבודה, אפשר לבדוק את ResourceClaim או את היומנים של ה-Pod. כדי לאמת את ההקצאה של יחידות GPU או TPU, בוחרים באחת מהאפשרויות הבאות:

GPU

  1. מקבלים את ResourceClaim שמשויך לעומס העבודה שפרסתם:

    kubectl get resourceclaims
    

    הפלט אמור להיראות כך:

    NAME                                               STATE                AGE
    dra-gpu-example-64b75dc6b-x8bd6-single-gpu-jwwdh   allocated,reserved   9s
    
  2. פרטים נוספים על הציוד שהוקצה ל-Pod:

    kubectl describe resourceclaims RESOURCECLAIM
    

    מחליפים את RESOURCECLAIM בשם המלא של ResourceClaim שקיבלתם מהפלט של השלב הקודם.

    הפלט אמור להיראות כך:

       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. מקבלים יומנים של עומס העבודה שפרסתם:

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

    הפלט אמור להיראות כך:

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

    הפלט של השלבים האלה מראה ש-GKE הקצה GPU אחד לקונטיינר.

TPU

  1. מקבלים את ResourceClaim שמשויך לעומס העבודה שפרסתם:

    kubectl get resourceclaims | grep dra-tpu-example
    

    הפלט אמור להיראות כך:

    NAME                                               STATE                AGE
    dra-tpu-example-64b75dc6b-x8bd6-all-tpus-jwwdh     allocated,reserved   9s
    
  2. פרטים נוספים על הציוד שהוקצה ל-Pod:

    kubectl describe resourceclaims RESOURCECLAIM -o yaml
    

    מחליפים את RESOURCECLAIM בשם המלא של ResourceClaim שקיבלתם מהפלט של השלב הקודם.

    הפלט אמור להיראות כך:

    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. מקבלים יומנים של עומס העבודה שפרסתם:

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

    הפלט אמור להיראות כך:

    [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
    

    הפלט של השלבים האלה מציין שכל יחידות ה-TPU במאגר הצמתים הוקצו ל-Pod.

המאמרים הבאים