תזמון עומסי עבודה ב-GKE באמצעות TAS

עומסי עבודה של AI ו-ML דורשים תקשורת משמעותית בין Pod ל-Pod. בגלל הדרישה הזו, רוחב הפס של הרשת בין Pods משפיע ישירות על זמן הביצוע ועל העלות של עומס העבודה. רוחב הפס הזה תלוי במיקום של המכונות הווירטואליות (VM) באשכול.

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

מה זה Topology Aware Scheduling‏ (TAS)?

‫TAS יכול לשפר משמעותית את היעילות של אימון מודל שפה גדול (LLM). ‫TAS ממקם את ה-workers באופן אסטרטגי בטופולוגיה של הרשת כדי לצמצם את התקורה של התקשורת במהלך צבירת הגרדיאנטים, שדורשת מה-workers לתקשר בסדר דירוג ספציפי. התכונה TAS מצמצמת את מספר הצעדים ברשת בין ה-workers שמתקשרים ברצף, וכך מפחיתה את התחרות על משאבי הרשת ומייעלת את השימוש ברוחב הפס. התוצאה היא התכנסות מהירה יותר וזמני אימון קצרים יותר. ככל שמודלי ה-LLM גדלים, TAS הופך לחיוני יותר כדי למקסם את הביצועים ואת יכולת ההתאמה לעומס (scalability) של האימון המבוזר.

TAS פועל בצורה הטובה ביותר עם קיבולת צפופה, שאפשר להשיג באמצעות קיבולת מבוססת-הזמנה. במכונות וירטואליות במחיר Spot ובאפשרויות צריכה אחרות, סביר להניח שהקיבולת לא תוקצה קרוב זו לזו, ולכן יכול להיות ש-TAS לא יפעל טוב בתרחיש הזה.

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

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

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

    gcloud container clusters get-credentials CLUSTER_NAME
    

    מחליפים את CLUSTER_NAME בשם של האשכול.

הכנת אשכול GKE

כדי להכין את אשכול GKE להרצת עומסי עבודה עם TAS:

  1. התקנת Kueue עם TAS מופעל
  2. הצגת הטופולוגיה של אשכול GKE

  3. הגדרת Kueue

התקנת Kueue עם TAS מופעל

מומלץ להשתמש ב-TAS עם Kueue, מערכת מקורית של Kubernetes שמנהלת את המכסות ואת האופן שבו המשימות צריכות לצרוך אותן. כדי להשתמש ב-TAS צריך להתקין את Kueue בגרסה 0.10.0 ואילך, ולהפעיל את התכונה באופן מפורש.

כדי להתקין את Kueue ולהפעיל את TAS, בוחרים באחת מהאפשרויות הבאות:

מניפסט של Kueue

  1. מתקינים את Kueue:

    kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/v0.10.0/manifests.yaml
    
  2. מפעילים את TAS ב-Kueue:

    kubectl -n kueue-system patch deployment kueue-controller-manager \
        --type json -p='[{"op": "add", "path": "/spec/template/spec/containers/0/args/-", "value": "--feature-gates=TopologyAwareScheduling=true"}]'
    

תרשים Helm

מתקינים את Kueue עם TAS מופעל באמצעות תרשים Helm:

helm install kueue oci://us-central1-docker.pkg.dev/k8s-staging-images/charts/kueue \
    --version="v0.10.0" \
    --create-namespace \
    --namespace=kueue-system \
    --set="controllerManager.featureGates[0].name=TopologyAwareScheduling,controllerManager.featureGates[0].enabled=true"

אחרי שמתקינים את Kueue, צריך להגדיר אותו כך שיבין את התשתית שהוא מנהל, כפי שמוסבר בקטע הבא.

הצגת הטופולוגיה של אשכול GKE

לפני שאתם צופים בטופולוגיה של צומתי A4X,‏ A4,‏ A3 Ultra,‏ A3 Mega ו-A3 High (8 GPUs) שהוקצו כ-VM במודל Spot, אתם צריכים להגדיר מיקום קומפקטי בצומתי GKE כדי לחשוף את הטופולוגיה הפיזית שלהם ל-TAS. אחרת, תקבלו שגיאות.

כדי לראות את הטופולוגיה של הצמתים של אשכול GKE במאגר צמתים ספציפי, מריצים את הפקודה הבאה:

kubectl get nodes -l cloud.google.com/gke-nodepool=NODE_POOL_NAME \
    -ocustom-columns='NAME:.metadata.name,BLOCK:.metadata.labels.cloud\.google\.com/gce-topology-block,SUBBLOCK:.metadata.labels.cloud\.google\.com/gce-topology-subblock,HOST:.metadata.labels.cloud\.google\.com/gce-topology-host' | sort -k2,4

מחליפים את NODE_POOL_NAME בשם של מאגר הצמתים.

כדי להבין את הטופולוגיה הפיזית של צומתי GKE במכונות הווירטואליות בפלט, אפשר לעיין בתוויות הצמתים הבאות:

  • ‫cloud.google.com/gce-topology-block: המזהה הספציפי לארגון של הבלוק השמור שבו נמצאת המכונה הווירטואלית.

  • ‫cloud.google.com/gce-topology-subblock: המזהה הספציפי לארגון של בלוק המשנה שבו נמצאת המכונה הווירטואלית.

  • ‫cloud.google.com/gce-topology-host: המזהה של המארח שבו נמצאת המכונה הווירטואלית.

  • ‫kubernetes.io/hostname: שם המארח של הצומת ב-Kubernetes. שם המארח הזה הוא בדרך כלל גם שם הצומת ב-GKE.

ככל שיש יותר ערכי תוויות משותפים לשתי מכונות וירטואליות, כך המיקום הפיזי שלהן קרוב יותר זו לזו. למידע נוסף על המונחים האלה, ראו טרמינולוגיה.

הגדרת Kueue

אחרי שמתקינים את Kueue, צריך להגדיר את Kueue כדי לציין את התשתית שהוא מנהל. בדרך כלל, Kueue דורש הגדרה של מכסת משאבים ב-ClusterQueue לתשתית סטטית או לתשתית דינמית עם התאמה אוטומטית לעומס באשכול. ה-ClusterQueue מאשר עומס עבודה רק אם המשאבים שעומס העבודה מבקש קטנים או שווים למאגר המשאבים שמוגדר ב-ClusterQueue. אחרי שמגדירים את Kueue כמו שמתואר בקטע הזה, Kueue מאשר עומסי עבודה באמצעות TAS באופן הבא:

  • ‫עומסי עבודה של TAS: המערכת של Kueue בודקת גם את הטופולוגיה של התשתית הפיזית וגם את השימוש הנוכחי בה.

  • עומסי עבודה שלא מבוססים על TAS: Kueue לא בודק את הטופולוגיה של התשתית הפיזית. ‫Kueue מנהל את כל המכסה שמוגדרת בקובץ התצורה, ומשאיר את הקצאת הצמתים ל-kube-scheduler.

כדי להבין איך לספק הגדרה של מכסת משאבים ל-ClusterQueue ב-Kueue, עיינו בדוגמאות הבאות:

  • מכסה גבוהה מאוד: Kueue כמעט אף פעם לא מפסיק את הקבלה של עומס עבודה על סמך המשאבים המבוקשים. בהתאם להגדרות של TAS, יכול להיות ש-Kueue יאשר או לא יאשר עומסי עבודה על סמך הטופולוגיה של התשתית. למידע נוסף, קראו את המאמר מכסת משאבים גבוהה מאוד.

  • מכסה ריאלית: Kueue מאשר את עומס העבודה רק אם המשאבים שעומס העבודה מבקש נמצאים במגבלות המכסה של המשאבים האלה. על סמך ההגדרות של TAS, המערכת של Kueue בודקת את הטופולוגיה של התשתית לפני שהיא מאשרת את עומס העבודה. למידע נוסף, קראו את המאמר מכסת משאבים ריאלית.

כל ההתייחסויות למכסת המשאבים בקטעים הבאים מתייחסות למכסת המשאבים של ClusterQueue.

מכסת משאבים גבוהה מאוד

בדוגמה הבאה נעשה שימוש במכסת משאבים גבוהה מאוד, כך ש-Kueue אף פעם לא מפסיק עומס עבודה על סמך מכסת המשאבים הזמינה. במקום זאת, Kueue משתמש במידע על הטופולוגיה של הצמתים הזמינים כדי לנסות להתאים את הטופולוגיה לדרישות של עומס העבודה.

כדי להשתמש בהגדרה הבאה של מכסת המשאבים, מבצעים את השלבים הבאים:

  1. פותחים כלי לעריכת קבצים לבחירתכם. אחר כך, כוללים את הגדרת המכסה הבאה בקובץ YAML בשם kueue-tas-config-very-high-quota.yaml:

      apiVersion: kueue.x-k8s.io/v1alpha1
      kind: Topology
      metadata:
        name: "gke-default"
      spec:
        levels:
        - nodeLabel: "cloud.google.com/gce-topology-block"
        - nodeLabel: "cloud.google.com/gce-topology-subblock"
        - nodeLabel: "cloud.google.com/gce-topology-host"
        - nodeLabel: "kubernetes.io/hostname"
    ---
      kind: ResourceFlavor
      apiVersion: kueue.x-k8s.io/v1beta1
      metadata:
        name: "tas-flavor"
      spec:
        nodeLabels:
          cloud.google.com/gke-nodepool: "NODE_POOL_NAME"
        topologyName: "gke-default"
        tolerations:
        - key: "nvidia.com/gpu"
          operator: "Exists"
          effect: NoSchedule
    ---
      apiVersion: kueue.x-k8s.io/v1beta1
      kind: ClusterQueue
      metadata:
        name: "tas-cluster-queue"
      spec:
        namespaceSelector: {}
        resourceGroups:
        - coveredResources: ["nvidia.com/gpu"]
          flavors:
          - name: "tas-flavor"
            resources:
            - name: "nvidia.com/gpu"
              nominalQuota: 10000000
    ---
      apiVersion: kueue.x-k8s.io/v1beta1
      kind: LocalQueue
      metadata:
        namespace: "default"
        name: "tas-user-queue"
      spec:
        clusterQueue: "tas-cluster-queue"
    

    מחליפים את NODE_POOL_NAME בשם של מאגר הצמתים.

  2. יוצרים ומחילים את הגדרת מכסת המשאבים למערכת התורים של Kueue:

    kubectl create -f kueue-tas-config-very-high-quota.yaml
    

מכסת משאבים ריאלית

בדוגמה הקודמת הגדרנו רק משאבי GPU. עם זאת, אפשר לנהל באמצעות Kueue את כל המשאבים שתואמים ל-Kubernetes.

בדוגמה הבאה מוגדרת מכסת משאבים מציאותית יותר, כולל מעבד (CPU), זיכרון ומעבד גרפי (GPU). ההגדרה הזו מיועדת ל-100 מכונות a3-ultragpu-8g. במכונה אחת יש 224 יחידות vCPU, זיכרון בנפח 2, 944GB ו-8 יחידות GPU. אותו עיקרון חל על סוגי מכונות GPU כלליות (A2,‏ A3 Edge,‏ G2,‏ G4 ו-N1), בהתאם למפרט המעבד והזיכרון שלהן.

כדי להשתמש בהגדרה הבאה של מכסת המשאבים, מבצעים את השלבים הבאים:

  1. פותחים כלי לעריכת קבצים לבחירתכם. אחר כך, כוללים את הגדרת המכסה הבאה בקובץ YAML בשם kueue-tas-config-real-quota.yaml:

      apiVersion: kueue.x-k8s.io/v1alpha1
      kind: Topology
      metadata:
        name: "gke-default"
      spec:
        levels:
        - nodeLabel: "cloud.google.com/gce-topology-block"
        - nodeLabel: "cloud.google.com/gce-topology-subblock"
        - nodeLabel: "cloud.google.com/gce-topology-host"
        - nodeLabel: "kubernetes.io/hostname"
    ---
      kind: ResourceFlavor
      apiVersion: kueue.x-k8s.io/v1beta1
      metadata:
        name: "tas-flavor"
      spec:
        nodeLabels:
          cloud.google.com/gke-nodepool: "NODE_POOL_NAME"
        topologyName: "gke-default"
        tolerations:
        - key: "nvidia.com/gpu"
          operator: "Exists"
          effect: NoSchedule
    ---
      apiVersion: kueue.x-k8s.io/v1beta1
      kind: ClusterQueue
      metadata:
        name: "tas-cluster-queue"
      spec:
        namespaceSelector: {} # match all
        resourceGroups:
        - coveredResources: ["cpu", "memory", "nvidia.com/gpu"]
          flavors:
          - name: "tas-flavor"
            resources:
            # numbers below represent quota of 100 a3-ultragpu-8g machines
            - name: "cpu"
              nominalQuota: 22400
            - name: "memory"
              nominalQuota: 294400Gi
            - name: "nvidia.com/gpu"
              nominalQuota: 800
    ---
      apiVersion: kueue.x-k8s.io/v1beta1
      kind: LocalQueue
      metadata:
        namespace: "default"
        name: "tas-user-queue"
      spec:
        clusterQueue: "tas-cluster-queue"
    

    מחליפים את NODE_POOL_NAME בשם של מאגר הצמתים.

  2. יוצרים ומחילים הגדרה של מכסת משאבים למערכת התורים של Kueue:

    kubectl create -f kueue-tas-config-real-quota.yaml
    

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

    topology.kueue.x-k8s.io/gke-default created
    resourceflavor.kueue.x-k8s.io/tas-flavor created
    clusterqueue.kueue.x-k8s.io/tas-cluster-queue created
    localqueue.kueue.x-k8s.io/tas-user-queue created
    

תזמון עומסי עבודה עם TAS באמצעות Kueue

בתרחישים הבאים מוסבר איך אפשר להורות ל-Kueue ול-TAS לנהל שילובים נפוצים של עומסי עבודה ותשתיות באמצעות סוגים ורמות של בקשות טופולוגיה:

  • אלה סוגי הבקשות לטופולוגיה (מועדפת או נדרשת):

    • ‫kueue.x-k8s.io/podset-preferred-topology: המערכת מתעדפת תזמון של כל עומס העבודה ברמת טופולוגיה נתונה, אבל עדיין מאשרת עומס עבודה שלא מתאים לרמת הטופולוגיה הזו. אם עומס עבודה מסוים מתאים לרמה אחת של טופולוגיה, יכול להיות ש-Kueue יתזמן את עומס העבודה הזה בכמה מופעים של אותה רמת טופולוגיה.

    • ‫kueue.x-k8s.io/podset-required-topology: המערכת ממשיכה לנסות להכניס את עומס העבודה עד שכל עומס העבודה מתאים לרמת הטופולוגיה שנבחרה.

  • אלה הרמות הזמינות לבקשת טופולוגיה, שמאפשרות לכם להיות ספציפיים יותר או פחות לגבי התשתית הפיזית שבה אתם מעדיפים או דורשים להריץ את המשימה:

    • cloud.google.com/gce-topology-block

    • cloud.google.com/gce-topology-subblock

    • cloud.google.com/gce-topology-host

    • kubernetes.io/hostname

כדי לתזמן עומסי עבודה באמצעות הערכים האלה, משתמשים בקובץ ה-YAML הבא של המשימה:

apiVersion: batch/v1
kind: Job
metadata:
  generateName: JOB_NAME
  labels:
    kueue.x-k8s.io/queue-name: tas-user-queue
spec:
  parallelism: NUMBER_OF_REPLICAS
  completions: NUMBER_OF_REPLICAS
  completionMode: Indexed
  template:
    metadata:
      annotations:
        ANNOTATIONS_STRING
    spec:
      containers:
      - name: dummy-job
        image: gcr.io/k8s-staging-perf-tests/sleep:v0.1.0
        args: ["60s"]
        resources:
          requests:
            nvidia.com/gpu: "1"
          limits:
            nvidia.com/gpu: "1"
      restartPolicy: Never

מחליפים את המשתנים הבאים:

  • ‫JOB_NAME: שם למשימה.

  • ‫NUMBER_OF_REPLICAS: מספר ה-Pods שפועלים במקביל.

  • ‫ANNOTATIONS_STRING: ראו את הטבלה הבאה:

    סוג ורמת הטופולוגיה המבוקשים תיאור ANNOTATIONS_STRING
    עדיף להריץ בתוך שם מארח (מומלץ) ההגדרה הזו תאפשר את עומס העבודה כל עוד יש מספיק משאבים זמינים כדי לעמוד בדרישות המשאבים של עומס העבודה, גם אם הקיבולת מפוצלת. ‫Kueue יתזמן את ה-Pods בצורה הכי קומפקטית שאפשר. kueue.x-k8s.io/podset-preferred-topology: "kubernetes.io/hostname"
    חובה להפעיל בתוך מארח

    ההגדרה הזו תאשר את עומס העבודה רק אם יש מארח זמין עם מספיק משאבים כדי לעמוד בדרישות המשאבים של עומס העבודה.

    האפשרות הזו שימושית כשיש כמה מכונות וירטואליות לכל מארח (לדוגמה, סוגי מכונות קטנים יותר) או כשאפשר להריץ כמה Pods בצומת אחד. במקרים כאלה, אם עומס העבודה יתקבל, הוא יפעל במארח יחיד.

    kueue.x-k8s.io/podset-required-topology: "cloud.google.com/gce-topology-host"
    עדיף להפעיל בתוך מארח ההגדרה הזו תאפשר את עומס העבודה כל עוד יש מספיק משאבים זמינים כדי לעמוד בדרישות המשאבים של עומס העבודה, גם אם הקיבולת מפוצלת. ‫Kueue ינסה לתזמן את ה-Pods שלכם במארח, וישתמש במארחים נוספים לפי הצורך. kueue.x-k8s.io/podset-preferred-topology: "cloud.google.com/gce-topology-host"
    חובה להפעיל בתוך בלוק משנה ההגדרה הזו תאשר את עומס העבודה רק אם יש בלוק משנה זמין עם מספיק משאבים כדי לעמוד בדרישות המשאבים של עומס העבודה. kueue.x-k8s.io/podset-required-topology: "cloud.google.com/gce-topology-subblock"
    עדיף להפעיל בתוך בלוק משנה ההגדרה הזו תאפשר את עומס העבודה כל עוד יש מספיק משאבים זמינים כדי לעמוד בדרישות המשאבים של עומס העבודה, גם אם הקיבולת מפוצלת. ‫Kueue ינסה לתזמן את הפודים בתוך בלוק משנה, וישתמש בבלוקי משנה נוספים לפי הצורך. במקרה כזה, Kueue ידרג גבוה יותר בלוק משנה עם יותר קיבולת זמינה, גם אם הוא מקוטע, בהשוואה לבלוק משנה עם קיבולת שמספיקה בדיוק כדי לעמוד בדרישות. kueue.x-k8s.io/podset-preferred-topology: "cloud.google.com/gce-topology-subblock"
    חובה להפעיל בתוך בלוק ההגדרה הזו תאפשר את עומס העבודה רק אם המשאבים שזמינים בבלוק עומדים בדרישות המשאבים של עומס העבודה. אם הבקשה תאושר, Kueue יצמצם את מספר הבלוקים המשניים והמארחים כדי לתזמן את עומס העבודה. זה עלול לגרום לפרגמנטציה של הקיבולת הזמינה. kueue.x-k8s.io/podset-required-topology: "cloud.google.com/gce-topology-block"
    עדיף להפעיל בתוך בלוק ההגדרה הזו תאפשר את עומס העבודה כל עוד יש מספיק משאבים זמינים כדי לעמוד בדרישות המשאבים של עומס העבודה, גם אם הקיבולת מפוצלת. ‫Kueue ינסה לתזמן את ה-Pods בתוך בלוק אחד, וישתמש בבלוקים נוספים לפי הצורך. kueue.x-k8s.io/podset-preferred-topology: "cloud.google.com/gce-topology-block"

תזמון עומסי עבודה באמצעות PodGroup עם TAS באמצעות Kueue

כשמשתמשים ב-PodGroups, צריך לציין שלושה שדות נוספים לכל Pod ב-PodGroup:

בהתאם למסגרת ה-ML שבה אתם משתמשים, יכול להיות ש-leader של PodGroup ידרוש GPU או לא. בגלל מגבלה של Kueue, צריך לטפל במקרים האלה בצורה שונה. בדוגמאות הבאות מוסבר איך ליצור PodGroup של שלושה פודים עם מנהיג אחד ושני עובדים.

מקרה 1: ה-Leader הוא גם Worker ונדרש GPU

אם ה-leader הוא אחד מה-workers וגם דורש GPU, אז ה-leader יכול להיות כל מספר ב-PodGroup. לשם הפשטות, בדוגמה הבאה האינדקס של ה-leader הוא 0:

apiVersion: v1
kind: Pod
metadata:
  generateName: tas-podgroup-leader-
  labels:
    kueue.x-k8s.io/queue-name: tas-user-queue
    kueue.x-k8s.io/pod-group-name: "tas-podgroup-example-group"
    kueue.x-k8s.io/pod-group-pod-index: "0"
  annotations:
    kueue.x-k8s.io/pod-group-total-count: "3"
    kueue.x-k8s.io/podset-required-topology: "cloud.google.com/gce-topology-block"
spec:
  containers:
  - name: leader
    image: gcr.io/k8s-staging-perf-tests/sleep:v0.1.0
    args: ["600s"]
    resources:
      requests:
        nvidia.com/gpu: "1"
      limits:
        nvidia.com/gpu: "1"
  restartPolicy: Never
---
apiVersion: v1
kind: Pod
metadata:
  generateName: tas-podgroup-worker-1-
  labels:
    kueue.x-k8s.io/queue-name: tas-user-queue
    kueue.x-k8s.io/pod-group-name: "tas-podgroup-example-group"
    kueue.x-k8s.io/pod-group-pod-index: "1"
  annotations:
    kueue.x-k8s.io/pod-group-total-count: "3"
    kueue.x-k8s.io/podset-required-topology: "cloud.google.com/gce-topology-block"
spec:
  restartPolicy: Never
  containers:
  - name: worker
    image: gcr.io/k8s-staging-perf-tests/sleep:v0.1.0
    args: ["600s"]
    resources:
      requests:
        nvidia.com/gpu: "1"
      limits:
        nvidia.com/gpu: "1"
---
apiVersion: v1
kind: Pod
metadata:
  generateName: tas-podgroup-worker-2-
  labels:
    kueue.x-k8s.io/queue-name: tas-user-queue
    kueue.x-k8s.io/pod-group-name: "tas-podgroup-example-group"
    kueue.x-k8s.io/pod-group-pod-index: "2"
  annotations:
    kueue.x-k8s.io/pod-group-total-count: "3"
    kueue.x-k8s.io/podset-required-topology: "cloud.google.com/gce-topology-block"
spec:
  restartPolicy: Never
  containers:
  - name: worker
    image: gcr.io/k8s-staging-perf-tests/sleep:v0.1.0
    args: ["600s"]
    resources:
      requests:
        nvidia.com/gpu: "1"
      limits:
        nvidia.com/gpu: "1"

מקרה 2: ה-Leader הוא לא Worker ולא נדרש GPU

אם ה-leader הוא לא אחד מה-workers בגלל המגבלה של Kueue, האינדקס של ה-leader חייב להיות האחרון ב-PodGroup, בגלל האופן שבו Kueue יוצר PodSets. אם ל-leader אין את האינדקס האחרון ול-worker הראשון אין את האינדקס הראשון, Kueue לא יחיל הקצאות דירוג.

מקרה לדוגמה:

---
apiVersion: v1
kind: Pod
metadata:
  generateName: tas-podgroup-leader-
  labels:
    kueue.x-k8s.io/queue-name: tas-user-queue
    kueue.x-k8s.io/pod-group-name: "tas-podgroup-example-group2"
    kueue.x-k8s.io/pod-group-pod-index: "2"
  annotations:
    kueue.x-k8s.io/pod-group-total-count: "3"
    kueue.x-k8s.io/podset-required-topology: "cloud.google.com/gce-topology-block"
spec:
  containers:
  - name: leader
    image: gcr.io/k8s-staging-perf-tests/sleep:v0.1.0
    args: ["600s"]
    resources:
      requests:
        cpu: "1"
      limits:
        cpu: "1"
  restartPolicy: Never
---
apiVersion: v1
kind: Pod
metadata:
  generateName: tas-podgroup-worker-0-
  labels:
    kueue.x-k8s.io/queue-name: tas-user-queue
    kueue.x-k8s.io/pod-group-name: "tas-podgroup-example-group2"
    kueue.x-k8s.io/pod-group-pod-index: "0"
  annotations:
    kueue.x-k8s.io/pod-group-total-count: "3"
    kueue.x-k8s.io/podset-required-topology: "cloud.google.com/gce-topology-block"
spec:
  restartPolicy: Never
  containers:
  - name: worker
    image: gcr.io/k8s-staging-perf-tests/sleep:v0.1.0
    args: ["600s"]
    resources:
      requests:
        nvidia.com/gpu: "1"
      limits:
        nvidia.com/gpu: "1"
---
apiVersion: v1
kind: Pod
metadata:
  generateName: tas-podgroup-worker-1-
  labels:
    kueue.x-k8s.io/queue-name: tas-user-queue
    kueue.x-k8s.io/pod-group-name: "tas-podgroup-example-group2"
    kueue.x-k8s.io/pod-group-pod-index: "1"
  annotations:
    kueue.x-k8s.io/pod-group-total-count: "3"
    kueue.x-k8s.io/podset-required-topology: "cloud.google.com/gce-topology-block"
spec:
  restartPolicy: Never
  containers:
  - name: worker
    image: gcr.io/k8s-staging-perf-tests/sleep:v0.1.0
    args: ["600s"]
    resources:
      requests:
        nvidia.com/gpu: "1"
      limits:
        nvidia.com/gpu: "1"

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