תזמון פלחים דינמיים באמצעות Kueue ו-TAS

במאמר הזה מוסבר איך להקצות מאגרי צמתים של TPU ולתזמן פריסות דינמיות ב-Google Kubernetes Engine ‏ (GKE) באמצעות Kueue ו-Topology Aware Scheduling ‏ (TAS).

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

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

דרישות

כדי להשתמש בפריסה דינמית ב-GKE, צריך לעמוד בדרישות הבאות:

  • משתמשים באשכול רגיל בערוץ המהיר באחת מהגרסאות הבאות:
    • כדי להגדיר חלוקה דינמית לפרוסות גדולות (טופולוגיות שוות או גדולות מ-4x4x4), צריך להשתמש בגרסה 1.35.2-gke.1842000 ואילך.
    • כדי להגדיר חלוקה דינמית לפרוסות משנה (טופולוגיות קטנות מ-4x4x4), צריך להשתמש בגרסה 1.36.0-gke.3712000 ואילך.
  • שימוש בגרסת Ironwood‏ (TPU7x).
  • משתמשים בקובץ האימג' של מערכת ההפעלה שמותאמת לקונטיינרים בשביל הצמתים.
  • כדי להשתמש בהקצאה מצטברת, צריך להשתמש בהזמנות במצב All Capacity. מצב All Capacity הוא תכונה שמופעלת על ידי TPU Cluster Director.
  • כדי להשתמש בפריסה דינמית של פרוסות משנה, ודאו שיש לצמתים אירועי תחזוקה בהמתנה. מעקב אחרי אירועי תחזוקה בהמתנה במכונות. אם לאחד מהצמתים יש אירוע תחזוקה בהמתנה עם שעת סיום בין 18 בספטמבר 2026 ל-30 בספטמבר 2026, צריך להפעיל ידנית את אירוע התחזוקה של המארח בצמתים האלה לפני שאפשר יהיה להשתמש ב-sub-slicing.

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

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

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

שימוש בפריסה דינמית ב-GKE עם Kueue

בקטע הזה מתואר תהליך העבודה לשימוש בפריסה דינמית ב-GKE.

  1. איך רואים את הטופולוגיה ואת סטטוס התקינות של כל ההזמנות במצב קיבולת
  2. מפעילים את בקר הפרוסות באשכול.
  3. מתקינים את Kueue,‏ JobSet ו-LWS.
  4. יצירת מאגרי צומתי TPU.
  5. מגדירים את Kueue ליצירת משאב Slice בהתאמה אישית.
  6. הרצת עומסי עבודה בפריסה דינמית באמצעות Kueue.
  7. ניקוי.

הפעלת בקר הפרוסות

כדי להשתמש בפריסה דינמית, צריך להפעיל את בקר הפרוסות באשכול.

  1. מעדכנים את האשכול:

    gcloud container clusters update CLUSTER_NAME \
        --location=LOCATION \
        --enable-slice-controller
    

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

  2. מקבלים פרטי כניסה כדי שתוכלו לתקשר עם האשכול באמצעות פקודות kubectl:

    gcloud config set container/cluster CLUSTER_NAME
    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=LOCATION
    
  3. בפלט של הפקודה הבאה, מוודאים שהערך slices.accelerator.gke.io מופיע:

    kubectl get crd slices.accelerator.gke.io
    

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

    slices.accelerator.gke.io                2026-01-09T23:58:02Z
    

התקנה של Kueue,‏ JobSet ו-LWS

אם כבר התקנתם את Kueue,‏ JobSet ו-LWS, אתם יכולים לדלג על החלק הזה.

התקנת Kueue

פועלים לפי ההוראות במסמכי התיעוד של Kueue או מריצים את הפקודה הבאה:

kubectl apply --server-side -f https://github.com/kubernetes-sigs/kueue/releases/download/KUEUE_VERSION/manifests.yaml

מחליפים את KUEUE_VERSION בגרסת Kueue הנדרשת בהתאם לדרישות הטופולוגיה. כדי להשתמש בחלוקה דינמית לפרוסות משנה, צריך להשתמש ב-Kueue מגרסה 0.18.2 ואילך. כדי להשתמש ב-dynamic super-slicing, צריך להשתמש ב-Kueue מגרסה 0.16.6 ואילך.

התקנת JobSet

פועלים לפי ההוראות במסמכי התיעוד של JobSet או מריצים את הפקודה הבאה:

kubectl apply --server-side -f https://github.com/kubernetes-sigs/jobset/releases/download/JOBSET_VERSION/manifests.yaml

מחליפים את JOBSET_VERSION בגרסה הנדרשת של JobSet, בהתאם לדרישות הטופולוגיה. כדי להשתמש בחלוקה דינמית לפרוסות משנה, צריך להשתמש ב-JobSet מגרסה 0.12.0 ואילך. כדי להשתמש ב-dynamic super-slicing, צריך להשתמש ב-JobSet מגרסה 0.11.1 ואילך.

התקנת LWS

‫LeaderWorkerSet‏ (LWS) נדרש רק לפרוסות משנה דינמיות.

פועלים לפי ההוראות במסמכי התיעוד של LWS או מריצים את הפקודה הבאה:

kubectl apply --server-side -f https://github.com/kubernetes-sigs/lws/releases/download/LWS_VERSION/manifests.yaml

מחליפים את LWS_VERSION בגרסת ה-LWS הנדרשת. צריך להשתמש ב-LWS בגרסה 0.8.0 ואילך.

יצירת מאגרי צמתים עם הקצאה מצטברת

בקטע הזה מוסבר איך ליצור מאגרי צמתים של TPU עם הקצאה מצטברת. ‫GKE ממיר את כל הקיבולת של ה-TPU למאגרי צמתים שמורכבים מקבוצות של 16 צמתים של מכונות וירטואליות מסוג Ironwood‏ (TPU7x), או בלוקים משניים. ‫GKE מקצה את מאגרי הצמתים האלה גם כשהוא לא מוצא את כל המכונות הווירטואליות התקינות, על ידי הצבת צמתים בחלקים תקינים של המכונה המארחת והקצאה הדרגתית של מכונות לא תקינות בזמן שהן מתוקנות.

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

  • בלוק ספציפי של יחידות TPU, שמוצג בהזמנות במצב All Capacity. טירגוט בלוקים מאפשר ל-GKE ליצור את מאגר הצמתים בכל בלוק משנה זמין בתוך הבלוק שצוין.
  • תת-בלוק ספציפי, או קבוצה ספציפית של 16 צמתים של מכונות וירטואליות מסוג Ironwood ‏ (TPU7x), של יחידות TPU לשליטה מפורטת יותר.

יצירת מדיניות עומס עבודה

כדי ליצור מאגר צמתים של פרוסות TPU עם Ironwood (TPU7x), קודם צריך ליצור מדיניות עומסי עבודה כשהשדה accelerator-topology-mode מוגדר לערך provision_only. ההגדרה הזו מפעילה את תהליך הקצאת ההרשאות המצטברת.

יצירת מדיניות עומס עבודה:

gcloud compute resource-policies create workload-policy WORKLOAD_POLICY_NAME \
        --project=PROJECT_ID \
        --region=REGION  \
        --type=HIGH_THROUGHPUT \
        --accelerator-topology=4x4x4 \
        --accelerator-topology-mode=provision_only

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

  • ‫WORKLOAD_POLICY_NAME: שם למדיניות של עומס העבודה.
  • ‫PROJECT_ID: מזהה הפרויקט ב- Google Cloud .
  • ‫REGION: האזור של מדיניות עומס העבודה.

בפקודה הזו, מבצעים את הפעולות הבאות:

  • תמיד צריך להגדיר את השדה accelerator-topology לערך 4x4x4 כדי להתאים למספר הכולל של הצ'יפים בתוך בלוק משנה אחד.
  • כדי לוודא שתהליך הקצאת ההרשאות המצטבר מופעל, תמיד צריך להגדיר את השדה accelerator-topology-mode לערך provision_only. כשהשדה provision_only מוגדר, מאגר הצמתים מקצה צומתי TPU בלי ליצור קישורי ICI או OCS.

מגדירים את מאגר הצמתים כך שיהיה שייך לבלוק או לתת-בלוק

אתם יכולים לטרגט בלוקים או בלוקי משנה ספציפיים בתוך ההזמנה במצב All Capacity.

  • טירגוט בלוק: כל מאגר צמתים משתמש בקיבולת מבלוק מסוים. ‫GKE ממקם את מאגר הצמתים בתוך בלוק משנה זמין בבלוק הזה. צריך ליצור מאגרי צמתים כמספר הבלוקים המשניים בבלוק שבו רוצים להשתמש.
  • טירגוט של בלוק משנה: כל מאגר צמתים ממופה לבלוק משנה ספציפי וזמין. כשמשתמשים בטירגוט של בלוק משנה, GKE יוצר את מאגר הצמתים אם לפחות VM אחד תקין. הקצאה מצטברת עוזרת לוודא שכל הצמתים ממוקמים בבלוק המשנה שצוין.

חסימה

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

    1. מזהים את שם הבלוק על ידי הצגת כל בלוקי ההזמנות והעתקת הערך בשדה name:. הערך הזה הוא השם של הבלוק או של BLOCK_NAME במסמך הזה.

    2. כדי לקבוע כמה מאגרי צמתים צריך ליצור, מתארים בלוק של הזמנות ומזהים את הערך בשדה reservationSubBlockCount. הערך הזה הוא מספר בלוקי המשנה הזמינים. לדוגמה, הערך reservationSubBlockCount: 4 מציין שבבלוק יש ארבעה בלוקי משנה זמינים, וצריך ליצור ארבעה מאגרי צמתים נפרדים.

  2. מגדירים את נתיב ההזמנה:

    export RESERVATION_PATH="projects/PROJECT_ID/reservations/RESERVATION_NAME/reservationBlocks/BLOCK_NAME"
    

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

    • ‫RESERVATION_NAME: השם של הזמנת ה-TPU.
    • ‫BLOCK_NAME: שם הבלוק.
  3. יוצרים מאגר צמתים לכל בלוק משנה שזוהה בשלב הקודם. לדוגמה, אם המספר הוא 4, מריצים את הפקודה הזו ארבע פעמים. צריך להשתמש בשם ייחודי לכל מאגר צמתים.

    gcloud container node-pools create NODE_POOL_NAME \
          --cluster=CLUSTER_NAME \
          --node-locations=ZONE \
          --machine-type=tpu7x-standard-4t \
          --num-nodes=16 \
          --placement-policy=WORKLOAD_POLICY_NAME \
          --reservation-affinity=specific \
          --reservation=${RESERVATION_PATH}
    

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

    • ‫NODE_POOL_NAME: השם של מאגר הצמתים החדש.
    • ‫CLUSTER_NAME: השם של אשכול GKE.
    • ‫WORKLOAD_POLICY_NAME: השם של מדיניות עומסי העבודה שיצרתם.
    • ‫ZONE: האזור של מאגר הצמתים, לדוגמה us-central1-a.

בלוק משנה

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

    1. כדי לזהות את שם הבלוק, מציגים את כל בלוקי ההזמנות ומעתיקים את הערך בשדה name:. הערך הזה הוא השם של הבלוק או של BLOCK_NAME במסמך הזה.

    2. כדי לזהות את השם של הבלוקים המשניים, מציגים את כל הבלוקים המשניים של בלוק ומעתיקים את הערך בשדה name: לכל רשומה ב-reservationSubBlocks. הערך הזה הוא השם של הבלוק המשני או של SUBBLOCK_NAME במסמך הזה.

  2. מגדירים את נתיב ההזמנה:

    export RESERVATION_PATH="projects/PROJECT_ID/reservations/RESERVATION_NAME/reservationBlocks/BLOCK_NAME/reservationSubBlocks/SUBBLOCK_NAME"
    

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

    • ‫RESERVATION_NAME: השם של הזמנת ה-TPU.
    • ‫BLOCK_NAME: שם הבלוק.
    • ‫SUBBLOCK_NAME: השם של הבלוק המשני.
  3. יוצרים את מאגר הצמתים:

    gcloud container node-pools create NODE_POOL_NAME \
            --project=PROJECT_ID \
            --cluster=CLUSTER_NAME \
            --node-locations=ZONE \
            --machine-type=tpu7x-standard-4t \
            --num-nodes=16 \
            --placement-policy=WORKLOAD_POLICY_NAME \
            --reservation-affinity=specific \
            --reservation=${RESERVATION_PATH}
    

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

    • ‫NODE_POOL_NAME: שם ייחודי למאגר הצמתים החדש, לדוגמה sub-block-pool-1.
    • ‫PROJECT_ID: מזהה הפרויקט ב- Google Cloud .
    • ‫CLUSTER_NAME: השם של אשכול GKE.
    • ‫ZONE: האזור של מאגר הצמתים, לדוגמה us-central2-b.
    • ‫WORKLOAD_POLICY_NAME: השם של מדיניות עומסי העבודה שיצרתם.

בשלב הזה, הצמתים נוצרים, אבל הקישורים שלהם ל-Inter-Chip Interconnect‏ (ICI) עדיין לא פעילים. לכן אי אפשר להריץ עומסי עבודה ישירות במאגרי הצמתים האלה.

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

  • יוצרים משאב Slice בהתאמה אישית. במקום Pods, משתמשים במשאב Slice בהתאמה אישית כדי להגדיר את הטופולוגיה שצוינה, שאותה מפעיל בקר ה-Slice.
  • תזמון עומסי עבודה ב-GKE באמצעות Kueue ו-TAS. ‫Kueue מטפל באופן אוטומטי ביצירה ובמחיקה של משאבים בהתאמה אישית של Slice. אל תשנו באופן ידני משאבים בהתאמה אישית של Slice שנוצרו על ידי Kueue.

יצירת פרוסה דינמית באמצעות Kueue ו-TAS

בקטע הזה תתזמנו עומסי עבודה ב-GKE באמצעות Kueue ו-TAS.

התקנת בקר הפרוסות של Kueue

  1. כדי להתקין את בקר הפרוסות של Kueue, שומרים את המניפסט הבא בתור slice-controller.yaml:

    # Copyright 2026 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: v1
    kind: Namespace
    metadata:
      labels:
        app.kubernetes.io/managed-by: kustomize
        app.kubernetes.io/name: slice-controller
        control-plane: controller-manager
      name: slice-controller-system
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      labels:
        app.kubernetes.io/managed-by: kustomize
        app.kubernetes.io/name: slice-controller
        control-plane: controller-manager
      name: slice-controller-controller-manager
      namespace: slice-controller-system
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      labels:
        app.kubernetes.io/managed-by: kustomize
        app.kubernetes.io/name: slice-controller
        control-plane: controller-manager
      name: slice-controller-leader-election-role
      namespace: slice-controller-system
    rules:
    - apiGroups:
      - ""
      resources:
      - configmaps
      verbs:
      - get
      - list
      - watch
      - create
      - update
      - patch
      - delete
    - apiGroups:
      - coordination.k8s.io
      resources:
      - leases
      verbs:
      - get
      - list
      - watch
      - create
      - update
      - patch
      - delete
    - apiGroups:
      - ""
      resources:
      - events
      verbs:
      - create
      - patch
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      labels:
        app.kubernetes.io/managed-by: kustomize
        app.kubernetes.io/name: slice-controller
        control-plane: controller-manager
      name: slice-controller-webhook-secrets-role
      namespace: slice-controller-system
    rules:
    - apiGroups:
      - ""
      resources:
      - secrets
      verbs:
      - get
      - list
      - watch
      - update
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      labels:
        control-plane: controller-manager
      name: slice-controller-manager-role
    rules:
    - apiGroups:
      - ""
      resources:
      - nodes
      - pods
      verbs:
      - get
      - list
      - watch
    - apiGroups:
      - accelerator.gke.io
      resources:
      - slices
      verbs:
      - create
      - delete
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - accelerator.gke.io
      resources:
      - slices/finalizers
      verbs:
      - update
    - apiGroups:
      - accelerator.gke.io
      resources:
      - slices/status
      verbs:
      - get
      - patch
      - update
    - apiGroups:
      - admissionregistration.k8s.io
      resources:
      - mutatingwebhookconfigurations
      verbs:
      - get
      - list
      - update
      - watch
    - apiGroups:
      - batch
      resources:
      - jobs
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - events.k8s.io
      resources:
      - events
      verbs:
      - create
      - patch
      - update
      - watch
    - apiGroups:
      - jobset.x-k8s.io
      resources:
      - jobsets
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - kueue.x-k8s.io
      resources:
      - admissionchecks
      verbs:
      - get
      - list
      - watch
    - apiGroups:
      - kueue.x-k8s.io
      resources:
      - admissionchecks/status
      - workloads/status
      verbs:
      - get
      - patch
      - update
    - apiGroups:
      - kueue.x-k8s.io
      resources:
      - workloads
      verbs:
      - create
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - leaderworkerset.x-k8s.io
      resources:
      - leaderworkersets
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - ray.io
      resources:
      - rayclusters
      - rayjobs
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      labels:
        control-plane: controller-manager
      name: slice-controller-metrics-auth-role
    rules:
    - apiGroups:
      - authentication.k8s.io
      resources:
      - tokenreviews
      verbs:
      - create
    - apiGroups:
      - authorization.k8s.io
      resources:
      - subjectaccessreviews
      verbs:
      - create
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      labels:
        control-plane: controller-manager
      name: slice-controller-metrics-reader
    rules:
    - nonResourceURLs:
      - /metrics
      verbs:
      - get
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      labels:
        app.kubernetes.io/managed-by: kustomize
        app.kubernetes.io/name: slice-controller
        control-plane: controller-manager
      name: slice-controller-leader-election-rolebinding
      namespace: slice-controller-system
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: slice-controller-leader-election-role
    subjects:
    - kind: ServiceAccount
      name: slice-controller-controller-manager
      namespace: slice-controller-system
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      labels:
        app.kubernetes.io/managed-by: kustomize
        app.kubernetes.io/name: slice-controller
        control-plane: controller-manager
      name: slice-controller-webhook-secrets-rolebinding
      namespace: slice-controller-system
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: slice-controller-webhook-secrets-role
    subjects:
    - kind: ServiceAccount
      name: slice-controller-controller-manager
      namespace: slice-controller-system
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      labels:
        app.kubernetes.io/managed-by: kustomize
        app.kubernetes.io/name: slice-controller
        control-plane: controller-manager
      name: slice-controller-manager-rolebinding
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: slice-controller-manager-role
    subjects:
    - kind: ServiceAccount
      name: slice-controller-controller-manager
      namespace: slice-controller-system
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      labels:
        control-plane: controller-manager
      name: slice-controller-metrics-auth-rolebinding
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: slice-controller-metrics-auth-role
    subjects:
    - kind: ServiceAccount
      name: slice-controller-controller-manager
      namespace: slice-controller-system
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      labels:
        control-plane: controller-manager
      name: slice-controller-webhook-server-cert
      namespace: slice-controller-system
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app.kubernetes.io/managed-by: kustomize
        app.kubernetes.io/name: slice-controller
        control-plane: controller-manager
      name: slice-controller-controller-manager-metrics-service
      namespace: slice-controller-system
    spec:
      ports:
      - name: https
        port: 8443
        protocol: TCP
        targetPort: 8443
      selector:
        app.kubernetes.io/name: slice-controller
        control-plane: controller-manager
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        control-plane: controller-manager
      name: slice-controller-webhook-service
      namespace: slice-controller-system
    spec:
      ports:
      - port: 443
        protocol: TCP
        targetPort: 9443
      selector:
        control-plane: controller-manager
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app.kubernetes.io/managed-by: kustomize
        app.kubernetes.io/name: slice-controller
        control-plane: controller-manager
      name: slice-controller-controller-manager
      namespace: slice-controller-system
    spec:
      replicas: 1
      selector:
        matchLabels:
          app.kubernetes.io/name: slice-controller
          control-plane: controller-manager
      template:
        metadata:
          annotations:
            kubectl.kubernetes.io/default-container: manager
          labels:
            app.kubernetes.io/name: slice-controller
            control-plane: controller-manager
        spec:
          containers:
          - args:
            - --metrics-bind-address=:8443
            - --leader-elect
            - --health-probe-bind-address=:8081
            - --zap-log-level=3
            - --feature-gates=UseRetryMechanismForSliceCreation=true
            - --activation-timeout=60m
            - --kube-api-qps=100
            - --kube-api-burst=200
            - --default-slice-health-node-affinity=HEALTHY_AND_DEGRADED
            - --reuse-slices=true
            - --add-preferred-node-affinity=true
            command:
            - /manager
            image: tpuongke/kueue-slice-controller:v0.10
            livenessProbe:
              httpGet:
                path: /healthz
                port: 8081
              initialDelaySeconds: 15
              periodSeconds: 20
            name: manager
            ports:
            - containerPort: 9443
              name: webhook-server
              protocol: TCP
            readinessProbe:
              httpGet:
                path: /readyz
                port: 8081
              initialDelaySeconds: 5
              periodSeconds: 10
            resources:
              limits:
                cpu: 12
                memory: 32Gi
              requests:
                cpu: 8
                memory: 16Gi
            securityContext:
              allowPrivilegeEscalation: false
              capabilities:
                drop:
                - ALL
            volumeMounts:
            - mountPath: /tmp/k8s-webhook-server/serving-certs
              name: cert
              readOnly: true
          securityContext:
            runAsNonRoot: true
            seccompProfile:
              type: RuntimeDefault
          serviceAccountName: slice-controller-controller-manager
          terminationGracePeriodSeconds: 10
          volumes:
          - name: cert
            secret:
              defaultMode: 420
              secretName: slice-controller-webhook-server-cert
    ---
    apiVersion: admissionregistration.k8s.io/v1
    kind: MutatingWebhookConfiguration
    metadata:
      labels:
        control-plane: controller-manager
      name: slice-controller-mutating-webhook-configuration
    webhooks:
    - admissionReviewVersions:
      - v1
      clientConfig:
        service:
          name: slice-controller-webhook-service
          namespace: slice-controller-system
          path: /mutate-batch-v1-job
      failurePolicy: Fail
      name: mjob.kb.io
      rules:
      - apiGroups:
        - batch
        apiVersions:
        - v1
        operations:
        - CREATE
        resources:
        - jobs
      sideEffects: None
    - admissionReviewVersions:
      - v1
      clientConfig:
        service:
          name: slice-controller-webhook-service
          namespace: slice-controller-system
          path: /mutate-jobset-x-k8s-io-v1alpha2-jobset
      failurePolicy: Fail
      name: mjobset.kb.io
      rules:
      - apiGroups:
        - jobset.x-k8s.io
        apiVersions:
        - v1alpha2
        operations:
        - CREATE
        resources:
        - jobsets
      sideEffects: None
    - admissionReviewVersions:
      - v1
      clientConfig:
        service:
          name: slice-controller-webhook-service
          namespace: slice-controller-system
          path: /mutate-leaderworkerset-x-k8s-io-v1-leaderworkerset
      failurePolicy: Fail
      name: mleaderworkerset.kb.io
      rules:
      - apiGroups:
        - leaderworkerset.x-k8s.io
        apiVersions:
        - v1
        operations:
        - CREATE
        resources:
        - leaderworkersets
      sideEffects: None
    - admissionReviewVersions:
      - v1
      clientConfig:
        service:
          name: slice-controller-webhook-service
          namespace: slice-controller-system
          path: /mutate-ray-io-v1-raycluster
      failurePolicy: Fail
      name: mraycluster.kb.io
      rules:
      - apiGroups:
        - ray.io
        apiVersions:
        - v1
        operations:
        - CREATE
        resources:
        - rayclusters
      sideEffects: None
    - admissionReviewVersions:
      - v1
      clientConfig:
        service:
          name: slice-controller-webhook-service
          namespace: slice-controller-system
          path: /mutate-ray-io-v1-rayjob
      failurePolicy: Fail
      name: mrayjob.kb.io
      rules:
      - apiGroups:
        - ray.io
        apiVersions:
        - v1
        operations:
        - CREATE
        resources:
        - rayjobs
      sideEffects: None
    
  2. מחילים את המניפסט slice-controller.yaml:

    kubectl apply -f slice-controller.yaml
    
  3. כדי להגדיר את Kueue לפריסה דינמית, שומרים את המניפסט הבא בתור dynamic-slice-topology.yaml:

    # Copyright 2026 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: Topology
    metadata:
      name: superslice-topology
    spec:
      levels:
      # Label to identify the physical block a sub-block belongs to.
      # Only sub-blocks from the same block can form a slice.
      - nodeLabel: cloud.google.com/gce-topology-block
      # Label to identify individual TPU sub-blocks (4x4x4 topology).
      - nodeLabel: cloud.google.com/gke-tpu-partition-4x4x4-id
      # Standard Kubernetes label for individual nodes.
      # Required to assign Pods to specific VMs.
      - nodeLabel: kubernetes.io/hostname
    ---
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ResourceFlavor
    metadata:
      name: superslice-rf
    spec:
      nodeLabels:
        cloud.google.com/gke-tpu-accelerator: tpu7x
      topologyName: superslice-topology
    ---
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: AdmissionCheck
    metadata:
      name: superslice-ac
    spec:
      controllerName: accelerator.gke.io/slice
    ---
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ClusterQueue
    metadata:
      name: cq
    spec:
      namespaceSelector: {}
      admissionChecks:
      - superslice-ac
      resourceGroups:
      - coveredResources:
        - google.com/tpu
        flavors:
        - name: superslice-rf
          resources:
          - name: google.com/tpu
            nominalQuota: "999999"  # modeling unlimited quota
    ---
    apiVersion: kueue.x-k8s.io/v1beta1
    kind: LocalQueue
    metadata:
      name: lq
      namespace: default
    spec:
      clusterQueue: cq
    
  4. מחילים את המניפסט dynamic-slice-topology.yaml:

    kubectl apply -f dynamic-slice-topology.yaml
    

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

    • ‫טופולוגיית פריסה דינמית של Ironwood (TPU7x) (superslice-topology): הטופולוגיה מגדירה את הרמות ש-Kueue מתייחס אליהן כשהוא מתזמן עומסי עבודה של פריסה דינמית. הרמות האלה הן:
      • תווית cloud.google.com/gce-topology-block: הרמה הזו נדרשת כדי להבין אילו בלוקי משנה שייכים לאילו בלוקים, כי רק בלוקי משנה מאותו בלוק יכולים ליצור פרוסה.
      • תווית cloud.google.com/gke-tpu-partition-4x4x4-id: הרמה הזו מייצגת בלוקי משנה נפרדים של Ironwood (TPU7x) (טופולוגיה 4x4x4).
      • ‫kubernetes.io/hostname label: הרמה הזו נדרשת כדי להקצות Pods למכונות וירטואליות ספציפיות ולצפות בתוויות וב-taints שלהן.
    • ‫Ironwood (TPU7x) SuperSlice ResourceFlavor (superslice-rf): סוג המשאב של תת-הבלוקים של Ironwood (TPU7x) כולל את התווית cloud.google.com/gke-tpu-accelerator: tpu7x כדי להתאים צמתים למכונות Ironwood (TPU7x).
    • ‫SuperSlice AdmissionCheck (superslice-ac): בדיקת הקבלה הזו אומרת ל-Kueue לא לתזמן עומס עבודה עד שבקר הפרוסות של GKE מאשר שהפרוסה הפכה לפעילה. בדיקת הקבלה מוגדרת קודם, ואז מתווספת ל-ClusterQueue שמטפל בעומסי העבודה של הפריסה הדינמית.
    • ‫ClusterQueue (cq) ו-LocalQueue (lq): השדות האלה מנהלים את המשאבים של google.com/tpu. ה-ClusterQueue‏ cq כולל את בדיקת הקבלה superslice-ac. אפשר להגדיר את השדה nominalQuota של google.com/tpu בשתי דרכים:
      • מכסה ספציפית: מגדירים את השדה nominalQuota כך שיתאים לקיבולת הקיימת, כדי לנהל את המכסות ולחלק את המשאבים בצורה הוגנת.
      • מכסה בלתי מוגבלת: מגדירים את השדה nominalQuota לערך גבוה מאוד, כמו "999999", כדי ליצור מודל של מכסה בלתי מוגבלת. כדי להתמקד ב-TAS ובפריסה דינמית, ההגדרה הזו עוקפת את פונקציונליות ניהול המכסות של Kueue.

הגדרת בחירת תקינות המחיצה

מעבר לתקינות ולמוכנות הרגילות של הצומת, GKE חושף את המצב הספציפי של כל צורת מחיצה באמצעות התווית cloud.google.com/gke-tpu-partition-[shape]-state (כאשר [shape] תואם לצורת מזהה המחיצה, כמו 2x2x1,‏ 2x2x2,‏ 2x2x4,‏ 2x4x4 או 4x4x4). התווית הזו מאפשרת ל-GKE להביא בחשבון גורמים שמשפיעים על יצירת הפרוסות, כמו המצב של קישורי ה-TPU. כדי להגדיר פרוסות משנה דינמיות (טופולוגיות קטנות מ-4x4x4), צריך להשתמש ב-GKE בגרסה 1.36.0-gke.3712000 ואילך.

אפשר להגדיר את הערך של התווית של מצב המחיצה באופן הבא:

  • ‫HEALTHY: המחיצה תקינה ופועלת באופן מלא.
  • ‫DEGRADED: התשתית של המחיצה במצב ירוד, למשל בגלל ירידה באיכות הקישור ל-OCS. המחיצה עדיין יכולה ליצור פרוסה, אבל הביצועים הכוללים עשויים להיות נמוכים יותר בהשוואה למחיצות תקינות. המצב הזה חל רק על הטופולוגיה של 4x4x4 ברמה העליונה. לטופולוגיות קטנות יותר אין מצב של פגיעה בביצועים.
  • ‫UNHEALTHY: המחיצה לא תקינה ואי אפשר ליצור ממנה פרוסה.
  • ‫UNSET: המצב לא מוגדר כי בקר הפרוסות של GKE לא אותחל בהצלחה.
  • ‫INCOMPLETE: לא כל הצמתים במחיצה מוקצים.

ה-webhook של Kueue Slice Controller מאמת אם עומס העבודה כולל דרישה ספציפית לתקינות המחיצה. אם לא מצוינת העדפה, ה-webhook מוסיף שיוך צומת כברירת מחדל.

ההתנהגות היא כזו:

  • אם קיימת מדיניות nodeSelector או nodeAffinity שמטרגטת את התווית cloud.google.com/gke-tpu-partition-[shape]-state, היא לא משתנה.
  • אם לא קיימת הגדרת תווית כזו, ה-webhook מוסיף את ה-affinity של הצומת כברירת מחדל כדי להבטיח שייעשה שימוש רק במחיצות זמינות:

    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: cloud.google.com/gke-tpu-partition-4x4x4-state
            operator: In
            values:
            - "HEALTHY"
            - "DEGRADED"
    

בקטע הבא מופיעות דוגמאות שבהן התווית cloud.google.com/gke-tpu-partition-4x4x4-state מוגדרת כדי לציין את ההגדרות השונות של תקינות הבלוקים המשניים.

הרצת עומסי עבודה לבדיקה בפריסה דינמית באמצעות Kueue

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

דוגמה 1: עומס עבודה אחד משתמש בפריסה דינמית אחת

בדוגמה הבאה מוסבר איך ליצור עומס עבודה באמצעות פרוסה עם טופולוגיה של 4x12x16, שמורכבת מ-12 בלוקי משנה. מספר ה-Pods חושב כך: (4 * 12 * 16) / 4 צ'יפים לכל צומת = 192 Pods.

  1. שומרים את המניפסט הבא בתור big-super-slice.yaml:

    # Copyright 2026 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
      name: big-super-slice
      labels:
        kueue.x-k8s.io/queue-name: lq
    spec:
      replicatedJobs:
        - name: job-jax
          replicas: 1
          template:
            spec:
              parallelism: 192  # pods per slice calculation: 4*12*16 / 4 = 192
              completions: 192
              backoffLimit: 10
              template:
                metadata:
                  annotations:
                    cloud.google.com/gke-tpu-slice-topology: 4x12x16
                spec:
                  tolerations:
                    - key: "google.com/tpu"
                      operator: "Equal"
                      value: "present"
                      effect: "NoSchedule"
                  nodeSelector:
                    cloud.google.com/gke-tpu-accelerator: tpu7x
                  containers:
                    - name: jax
                      image: python:latest
                      command:
                        - bash
                        - -c
                        - |
                          printenv
                          pip install "jax[tpu]" -f https://storage.googleapis.com/jax-releases/libtpu_releases.html
                          python -c 'import jax; print("Global device count:", jax.device_count(), "Local device count:", jax.local_device_count())'
                      resources:
                        limits:
                          google.com/tpu: 4
                  restartPolicy: Never
    

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

    • ‫cloud.google.com/gke-tpu-slice-topology: מציין את "4x12x16" כטופולוגיה של הפריסה הדינמית. הדרישות לטופולוגיית המאיץ tpu7x כוללות את הכללים הבאים:
      • לפריסה דינמית של פרוסות משנה: אתם יכולים לציין טופולוגיות קטנות יותר מ-4x4x4, כמו 2x2x1,‏ 2x2x2,‏ 2x2x4 או 2x4x4. כדי להשתמש בטופולוגיות הקטנות יותר, צריך להשתמש בגרסה 1.36.0-gke.3712000 ואילך של GKE.
      • ל-dynamic super-slicing: אפשר לציין טופולוגיות ששוות ל-4x4x4 או גדולות ממנו. כדי להגדיר פריסה דינמית של פרוסות-על, כל מימד של הטופולוגיה המבוקשת צריך להיות כפולה של ארבע, לדוגמה 4A x 4B x 4C.
      • הטופולוגיה צריכה להיות מחרוזת תלת-ממדית בפורמט AxBxC, לדוגמה 4x8x8.
      • צריך למיין את המידות בסדר לא יורד: A <= B <= C. לדוגמה, הערך 4x8x4 לא תקין, הוא צריך להיות 4x4x8.
      • מכפלת המימדים (ABC) לא יכולה להיות גדולה מ-9,216.
      • הטופולוגיות הגדולות ביותר של פרוסות יכולות לכלול עד 32 בלוקי משנה. לדוגמה, 8x16x16 עם 32 בלוקי משנה, 8x12x20 עם 30 בלוקי משנה או 12x12x12 עם 27 בלוקי משנה נמצאים בטווח המגבלות המקובלות.
    • cloud.google.com/gke-tpu-accelerator: tpu7x: מתזמן Pods במכונות וירטואליות שמריצות את Ironwood‏ (TPU7x).
    • ‫kueue.x-k8s.io/queue-name: מקצה את ה-JobSet ל-LocalQueue של Kueue.
    • ה-webhook מוסיף את ברירת המחדל של ה-node affinity כדי להבטיח שימוש בצמתים HEALTHY ו-DEGRADED.
  2. מחילים את המניפסט big-super-slice.yaml:

    kubectl apply -f big-super-slice.yaml
    

    אחרי שמחילים את המניפסט, Kueue יוצר JobSet בשם big-super-slice. לאחר מכן, Kueue מנסה ליצור פריסה דינמית אחת עם טופולוגיית 4x12x16. אחרי שהפרוסה פעילה, Kueue מאשר את עומס העבודה, ו-192 הפודים מתוזמנים בצמתים כדי ליצור את הפרוסה הדינמית שמריצה את עומסי העבודה.

דוגמה 2: עומס עבודה עם יותר מרפליקה אחת

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

  1. שומרים את המניפסט הבא בתור two-super-slices.yaml:

    # Copyright 2026 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
      name: two-super-slices
      labels:
        kueue.x-k8s.io/queue-name: lq
    spec:
      replicatedJobs:
        - name: job-jax
          replicas: 2
          template:
            spec:
              parallelism: 64  # Pods per slice calculation: (4*8*8) / 4 = 64
              completions: 64
              backoffLimit: 10
              template:
                metadata:
                  annotations:
                    cloud.google.com/gke-tpu-slice-topology: 4x8x8
                spec:
                  tolerations:
                    - key: "google.com/tpu"
                      operator: "Equal"
                      value: "present"
                      effect: "NoSchedule"
                  nodeSelector:
                    cloud.google.com/gke-tpu-accelerator: tpu7x
                    cloud.google.com/gke-tpu-partition-4x4x4-state: "HEALTHY"
                  containers:
                    - name: jax
                      image: python:latest
                      command:
                        - bash
                        - -c
                        - |
                          printenv
                          pip install "jax[tpu]" -f https://storage.googleapis.com/jax-releases/libtpu_releases.html
                          python -c 'import jax; print("Global device count:", jax.device_count(), "Local device count:", jax.local_device_count())'
                      resources:
                        limits:
                          google.com/tpu: 4
                  restartPolicy: Never
    
  2. מחילים את המניפסט two-super-slices.yaml:

    kubectl apply -f two-super-slices.yaml
    

במניפסט הזה, מגדירים את השדה replicas לערך 2 בקטע replicatedJobs. אחרי שמחילים את המניפסט, Kueue מנסה ליצור שתי פרוסות נפרדות עם טופולוגיית 4x8x8. ‫Kueue יוצרת פריסה דינמית לכל רפליקה שמוגדרת ב-jobset.spec.replicatedJobs[].replicas. אם מציינים n רפליקות, Kueue יוצר n פריסות דינמיות לעומס העבודה וממתין שכל הפריסות יהיו פעילות לפני שהוא מאשר את עומס העבודה.

אופטימיזציה של תזמון עומסי העבודה באמצעות שימוש חוזר בפרוסות

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

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

הפעלת שימוש חוזר ב-Slice

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

  1. מגדירים את בקר הפרוסות: מעדכנים את הארגומנטים של פריסת בקר הפרוסות של Kueue כך שיכללו את הדגל --reuse-slices=true. כדי לוודא שעומסי העבודה מתוזמנים בצורה אופטימלית בפרוסות הקיימות, צריך להוסיף גם את הדגל --add-preferred-node-affinity=true.

  2. הגדרת Kueue (מומלץ): כדי לאפשר ל-Kueue להשתמש בהצעות של הבקר לגבי העדפת ה-affinity של הצומת, צריך להפעיל את ה-Feature Gate‏ TASRespectNodeAffinityPreferred בהגדרות של Kueue.

    לדוגמה, עורכים את ה-ConfigMap של kueue-manager-config כדי להוסיף את ה-Feature Gate:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: kueue-manager-config
      namespace: kueue-system
    data:
      controller_manager_config.yaml: |
        apiVersion: config.kueue.x-k8s.io/v1beta1
        kind: Configuration
        featureGates:
          TASRespectNodeAffinityPreferred: true
        # ...
    

    אחרי שמשנים את ConfigMap, מפעילים מחדש את הפריסה של kueue-controller-manager כדי לאכוף את השינוי:

    kubectl rollout restart deploy kueue-controller-manager -n kueue-system
    

אכיפת מחיקת פרוסות לכל עומס עבודה

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

  1. מוסיפים את התווית הבאה להגדרה של Job או JobSet:

    kueue.gke.io/tpu-enforce-slice-deletion: "true"
    

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

  2. כדי להגדיר ל-Kueue להעביר את התווית הזו מה-Job של המסגרת לאובייקט Workload של Kueue, מוסיפים את התווית לרשימה labelKeysToCopy בהגדרות של Kueue:

    labelKeysToCopy:
    - "kueue.gke.io/tpu-enforce-slice-deletion"
    

מעקב אחרי הפרוסה

אתם יכולים לראות את הסטטוס של הפרוסה ולעקוב אחרי המדדים שלה באמצעות מדדי המערכת של GKE.

מעקב אחרי הסטטוס של הפרוסה

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

  1. כדי למצוא את הפרוסות שהוקצו לעומס עבודה, מריצים את הפקודה הבאה:

    kubectl get slice -l kueue.gke.io/tpu-slice-used-by-namespace=NAMESPACE,kueue.gke.io/tpu-slice-used-by-workload=WORKLOAD_NAME
    

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

    • ‫NAMESPACE: מרחב השמות של עומס העבודה.
    • ‫WORKLOAD_NAME: השם של עומס העבודה ב-Kueue, שבדרך כלל זהה לשם של ה-Job או ה-JobSet.
  2. מעתיקים את שם הפרוסה מהפלט של הפקודה הקודמת.

  3. כדי לבדוק את הסטטוס המפורט של הפרוסה הדינמית, משתמשים בשם הפרוסה:

    kubectl describe slice SLICE_NAME
    

    מחליפים את SLICE_NAME בשם של הפרוסה.

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

Name:         s-4x4x4-74d3fb0b
Namespace:
Labels:       <none>
Annotations:  <none>
API Version:  accelerator.gke.io/v1beta1
Kind:         Slice
Metadata:
  Creation Timestamp:  2026-02-12T23:44:28Z
  Finalizers:
    accelerator.gke.io/slice-finalizer
  Generation:        1
  Resource Version:  1770939905695871008
  UID:               6dbbfe14-4486-4462-864d-e078d0ca8b5b
Spec:
  Partition Ids:
    5eae6a4f59d59cf30a9bf49de618eb2b
  Topology:  4x4x4
  Type:      tpu7x
Status:
  Conditions:
    Last Transition Time:  2026-02-12T23:45:05Z
    Message:
    Reason:                ACTIVE
    Status:                True
    Type:                  Ready
    Last Transition Time:  2026-02-12T23:45:05Z
    Message:               NodeLabelingCompleted
    Reason:                NodeLabelIsAdded
    Status:                True
    Type:                  NodeLabeled
Events:                    <none>

מעקב אחרי המדדים של הפלח

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

  • kubernetes.io/accelerator/slice/state
  • kubernetes.io/accelerator/partition/state
  • kubernetes.io/accelerator/slice/deformation_durations
  • kubernetes.io/accelerator/slice/formation_durations

מידע נוסף על המדדים זמין במאמר מדדי המערכת של GKE.

מדדי בקר של Kueue Slice

אתם יכולים גם לעקוב אחרי המדדים הבאים של Prometheus שנחשפים על ידי Kueue Slice Controller כדי לבחון את מחזור החיים של הפרוסות, את השימוש החוזר ואת בדיקות הקבלה:

מדדי מחזור חיים של פרוסות

מדדי מחזור החיים של הפרוסות עוקבים אחרי היצירה והמחיקה של הפרוסות:

  • ‫tpu_ac_slice_create_time: היסטוגרמה שמודדת כמה זמן נמשכה יצירת הפרוסה.
  • tpu_ac_slices_created: מונה שעוקב אחרי הפרוסות שנוצרו (כולל תווית is_reusable).
  • ‫tpu_ac_slices_status: מד שעוקב אחרי מספר הפרוסות הנוכחי לפי סטטוס, כולל התוויות is_reusable ו-in_use.
  • ‫tpu_ac_slice_delete_time: היסטוגרמה שמודדת כמה זמן נמשכה מחיקת הפרוסה.
  • ‫tpu_ac_slices_deleted: מונה שעוקב אחרי פרוסות שנמחקו.
  • ‫tpu_ac_slices_gc: מעקב אחר מונה ניקה פרוסות באופן אוטומטי.

מדדי שימוש חוזר ב-Slice

מדדי השימוש החוזר בפרוסות עוקבים אחרי השימוש החוזר המוצלח וההתנגשויות של פרוסות TPU:

  • ‫tpu_ac_slices_reused: מונה שעוקב אחרי פרוסות שנעשה בהן שימוש חוזר בהצלחה.
  • tpu_ac_slices_conflict: פרוסות מעקב של מונה שנמחקו בגלל חוסר התאמה בטופולוגיה או בצורה.

מדדי עומס עבודה וקבלה

מדדי עומס העבודה והקבלה עוקבים אחרי משך הזמן והתוצאות של בדיקות הקבלה:

  • ‫tpu_ac_admission_time: היסטוגרמה שמודדת את משך הזמן של תהליך בדיקת הקבלה. הערה: המדד הזה מודד את משך בדיקת הקבלה של בקר הפרוסה, ולא כולל את זמן הקבלה הכולל של עומס העבודה של Kueue.
  • ‫tpu_ac_workload_processed: מונה של החלטות לגבי בדיקות קבלה, שמכיל תווית target_state.

מדדים כלליים

מדדים כלליים עוקבים אחרי בעיות תפעוליות ושגיאות:

  • ‫tpu_ac_problem: מונה שעוקב אחרי בעיות או שגיאות תפעוליות. המדד הזה כולל תווית problem שמציינת את סוג השגיאה הספציפי.

הסרת המשאבים

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

  1. מוחקים את ה-JobSet. הפעולה הזו גורמת ל-Kueue למחוק את המשאבים המשויכים בהתאמה אישית של Slice.

    kubectl delete jobset JOBSET_NAME
    

    מחליפים את JOBSET_NAME בשם של ה-JobSet, לדוגמה big-super-slice.

  2. מוחקים את מאגר הצמתים של ה-TPU:

    gcloud container node-pools delete NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=LOCATION
    

(אופציונלי) שימוש בפריסה דינמית עם מתזמן משלכם

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

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