使用 Kueue 和 TAS 排定動態配額

本文說明如何使用 Kueue 和拓撲感知調度 (TAS),在 Google Kubernetes Engine (GKE) 佈建 TPU 節點集區及排定動態配量。

您也可以直接與配量自訂資源互動,使用動態配量功能。詳情請參閱「搭配使用動態配量和自訂排程器」。

按照這些操作說明操作之前,請務必瞭解動態配量的概念。

需求條件

如要在 GKE 使用動態配量,必須符合下列條件:

  • 在快速版本中使用下列其中一個版本的標準叢集:
    • 如要使用動態超級切片設定 (拓撲等於或大於 4x4x4),請使用 1.35.2-gke.1842000 以上版本。
    • 如要動態設定子切片 (拓撲小於 4x4x4),請使用 1.36.0-gke.3712000 以上版本。
  • 使用 Ironwood (TPU7x) 版本。
  • 為節點使用 Container-Optimized OS 映像檔。
  • 如要使用增量佈建,請使用所有容量模式預留項目。所有容量模式都是 TPU Cluster Director 啟用的功能。
  • 如要使用動態子切片,請確認節點有待處理的維護事件。監控執行個體,查看是否有待處理的維護事件。如果任何節點有待處理的維護事件,且結束時間介於 2026 年 9 月 18 日至 2026 年 9 月 30 日之間,您必須先手動觸發這些節點的主機維護事件,才能使用子切片。

事前準備

開始之前,請確認您已執行下列工作:

  • 啟用 Google Kubernetes Engine API。
  • 啟用 Google Kubernetes Engine API
  • 如要使用 Google Cloud CLI 執行這項工作,請安裝並初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行 gcloud components update 指令,取得最新版本。較舊的 gcloud CLI 版本可能不支援執行本文中的指令。

在 GKE 中搭配 Kueue 使用動態配量

本節說明在 GKE 使用動態配量的工作流程。

  1. 查看所有容量模式預留項目的拓撲和健康狀態。
  2. 在叢集中啟用切片控制器。
  3. 安裝 Kueue、JobSet 和 LWS。
  4. 建立 TPU 節點集區。
  5. 設定 Kueue 以建立 Slice 自訂資源。
  6. 使用 Kueue 在動態配量上執行工作負載。
  7. 清理。

啟用 Slice 控制器

如要使用動態配量,請在叢集中啟用配量控制器。

  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 v0.18.2 以上版本。如要使用動態超級切片,請使用 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 v0.12.0 以上版本。如要使用動態超級切片,請使用 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 v0.8.0 以上版本。

建立節點集區並啟用漸進式佈建

本節說明如何建立 TPU 節點集區,並採用遞增佈建。GKE 會將所有 TPU 運算能力轉換為節點集區,其中包含由 16 個節點組成的 Ironwood (TPU7x) VM 群組或子區塊。即使找不到所有健康狀態良好的 VM,GKE 也會佈建這些節點集區,方法是將節點放在主機機器的健康狀態良好部分,並在修復不健康的機器時逐步佈建。

您可以指定節點集區屬於下列任一項目:

  • 特定 TPU 區塊,會在「所有容量」模式預留項目中顯示。指定區塊後,GKE 就能在指定區塊內的任何可用子區塊中建立節點集區。
  • TPU 的特定子區塊,或 Ironwood (TPU7x) VM 的特定 16 節點群組,可進行更精細的控管。

建立工作負載政策

如要使用 Ironwood (TPU7x) 建立 TPU 磁碟區節點集區,您必須先建立工作負載政策,並將 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 專案 ID。
  • REGION:工作負載政策的區域。

在這個指令中,請執行下列操作:

  • 請一律將 accelerator-topology 欄位設為 4x4x4,以符合單一子區塊中的晶片總數。
  • 請務必將 accelerator-topology-mode 欄位設為 provision_only,確保觸發增量佈建程序。設定 provision_only 欄位後,節點集區會佈建 TPU 節點,但不會形成 ICI 或 OCS 連結。

指定節點集區所屬的區塊或子區塊

您可以指定「所有容量」模式預留項目中的特定子區塊或區塊。

  • 指定區塊:每個節點集區都會使用指定區塊的容量。GKE 會將節點集區放在該區塊中可用的子區塊內。您必須建立與要使用的區塊中子區塊數量相同的節點集區。
  • 指定子區塊:每個節點集區都會對應至特定且可用的子區塊。使用子區塊指定目標時,如果至少有一個 VM 狀況良好,GKE 就會建立節點集區。遞增佈建功能可確保所有節點都位於指定的子區塊中。

封鎖

  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. 如要擷取區塊名稱和可用子區塊的 ID,請在「查看所有容量模式預留項目的拓撲和健康狀態」文件中完成下列步驟:

    1. 如要找出區塊名稱,請列出所有預留區塊,並複製 name: 欄位中的值。這個值是區塊或這份文件上 BLOCK_NAME 的名稱。

    2. 如要找出子區塊的名稱,請列出區塊的所有子區塊,然後複製 reservationSubBlocks 下每個項目的 name: 欄位值。這個值是子區塊或本文件中 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 專案 ID。
    • CLUSTER_NAME:GKE 叢集名稱。
    • ZONE:節點集區的可用區,例如 us-central2-b。
    • WORKLOAD_POLICY_NAME:您建立的工作負載政策名稱。

在這個階段,節點已建立,但晶片間互連 (ICI) 連結尚未啟用。因此,您無法直接在這些節點集區上執行工作負載。

如要啟用所有必要的 ICI 連結來建立配量,並允許排定工作負載,請使用下列任一方法建立動態配量:

  • 建立Slice 自訂資源。您可以使用 Slice 自訂資源定義指定的拓撲,而非使用 Pod,並由 Slice 控制器啟用。
  • 使用 Kueue 和 TAS 排定 GKE 工作負載。Kueue 會自動建立及刪除 Slice 自訂資源。請避免手動修改 Kueue 建立的 Slice 自訂資源。

使用 Kueue 和 TAS 建立動態配量

在本節中,您將使用 Kueue 和 TAS 排定 GKE 工作負載。

安裝 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 標籤:必須具備這個層級,才能將 Pod 指派給特定 VM,以及查看其標籤和污點。
    • 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 資源。cq ClusterQueue 包含 superslice-ac 准入檢查。google.com/tpu 的 nominalQuota 欄位可透過兩種方式設定:
      • 特定配額:將 nominalQuota 欄位設為符合現有容量,以便公平共用及管理配額。
      • 無限制配額:將 nominalQuota 欄位設為極高的值 (例如 "999999"),模擬無限制配額。為專注於 TAS 和動態配量,這項設定會略過 Kueue 的配額管理功能。

定義分區健康狀態選項

除了標準節點健康狀態和準備度之外,GKE 還會使用 cloud.google.com/gke-tpu-partition-[shape]-state 標籤 (其中 [shape] 與分區 ID 形狀相符,例如 2x2x1、2x2x2、2x2x4、2x4x4 或 4x4x4),公開每個分區形狀的特定狀態。這個標籤可讓 GKE 考量影響切片形成的因素,例如 TPU 連結的狀態。動態子切片設定 (拓撲小於 4x4x4) 須使用 GKE 1.36.0-gke.3712000 以上版本。

您可以按照下列方式定義失聯狀態標籤的值:

  • HEALTHY:分區健康狀態良好,功能正常。
  • DEGRADED:失聯基礎架構處於降級狀態,例如 OCS 連結降級。失聯節點仍可形成切片,但整體效能可能低於正常節點。這個狀態僅適用於頂層 4x4x4 拓撲。較小的拓撲不會有功能低下的狀態。
  • UNHEALTHY:分區狀態不佳,無法形成切片。
  • UNSET:GKE Slice 控制器初始化失敗,因此狀態未定義。
  • INCOMPLETE:分區內並非所有節點都已佈建。

Kueue Slice Controller Webhook 會驗證工作負載是否包含特定分區健康狀態需求。如未指定偏好設定,Webhook 會插入預設節點親和性。

具體行為如下:

  • 如果存在指定 cloud.google.com/gke-tpu-partition-[shape]-state 標籤的 nodeSelector 或 nodeAffinity,則會保持不變。
  • 如果沒有這類標籤設定,Webhook 會插入下列預設節點親和性,確保只使用可用的分區:

    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,在動態配量上部署工作負載。其中包含範例,說明如何建立動態配量工作負載,以及由多個配量組成的工作負載。工作負載會以 JobSet 的形式提交。

範例 1:單一工作負載使用單一動態配量

以下範例說明如何使用具有 4x12x16 拓撲的切片建立工作負載,該切片由 12 個子區塊組成。Pod 數量的計算方式如下:(4 * 12 * 16) / 每個節點 4 個晶片 = 192 個 Pod。

  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。這些較小的拓撲需要 GKE 1.36.0-gke.3712000 以上版本。
      • 動態超級切片:您可以指定等於或大於 4x4x4 的拓撲。如要使用動態超級切片設定,所要求拓撲的每個維度都必須是 4 的倍數,例如 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:在執行 Ironwood (TPU7x) 的 VM 上排定 Pod。
    • kueue.x-k8s.io/queue-name:將 JobSet 指派給 Kueue LocalQueue。
    • Webhook 會插入預設節點相依性,確保使用 HEALTHY 和 DEGRADED 節點。
  2. 套用 big-super-slice.yaml 資訊清單:

    kubectl apply -f big-super-slice.yaml
    

    套用資訊清單後,Kueue 會建立名為 big-super-slice 的 JobSet。接著,Kueue 會嘗試使用 4x12x16 拓撲建立單一動態配量。配量啟用後,Kueue 會准予工作負載,並在節點上排定 192 個 Pod,形成執行工作負載的動態配量。

範例 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
    

在這個資訊清單中,您可以在 replicatedJobs 區段中將 replicas 欄位設為 2。套用資訊清單後,Kueue 會嘗試使用 4x8x8 拓撲形成兩個獨立切片。Kueue 會為 jobset.spec.replicatedJobs[].replicas 中定義的每個副本建立動態配量。如果指定 n 個副本,Kueue 會為工作負載建立 n 個動態配量,並等待所有配量啟用,再准予工作負載。

重複使用切片,最佳化工作負載排程

根據預設,Kueue 會指示切片控制器為每個工作負載執行作業佈建新的 TPU 切片,並在工作負載完成時刪除。這種行為可能導致客戶流失,並增加基礎架構的負擔。

有了配量重複使用功能,新工作負載就能重複使用拓撲和硬體限制相同的現有閒置 TPU 配量。啟用配量重複使用功能後,Kueue 會在工作結束時將配量標示為閒置,而非刪除。要求相同分區的新工作會立即宣告並重複使用切片,因此不會發生硬體佈建延遲。

啟用 Slice 重複使用功能

如要充分發揮 Slice 重複使用的效益,必須同時設定 Slice 控制器和 Kueue,讓兩者搭配運作。

  1. 設定切片控制器:更新 Kueue 切片控制器部署作業引數,加入 --reuse-slices=true 旗標。為確保工作負載在現有切片上以最佳方式排程,請一併新增 --add-preferred-node-affinity=true 旗標。

  2. 設定 Kueue (建議):如要允許 Kueue 使用控制器偏好的節點親和性建議,您必須在 Kueue 設定中啟用 TASRespectNodeAffinityPreferred feature gate。

    舉例來說,編輯 kueue-manager-config ConfigMap 即可新增 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"
    

    套用這個標籤後,工作負載仍可排定在現有的閒置切片上執行。不過,工作負載完成後,slice 會永久刪除,不會回到可重複使用的集區。

  2. 在 Kueue 設定的 labelKeysToCopy 清單中加入這個標籤,設定 Kueue 將這個標籤從架構工作傳遞至 Kueue Workload 物件:

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

監控切片

您可以透過 GKE 系統指標查看切片狀態及監控切片指標。

監控 Slice 狀態

當工作負載建立或主動使用切片時,切片控制器會附加標籤,識別使用該切片的工作負載。由於 Slice 名稱是動態產生 (啟用重複使用功能時,會與工作負載名稱分離),因此請使用這些標籤,找出指派給工作負載的 Slice。

  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 系統指標,瞭解 slice 的狀況:

  • 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 控制器指標

您也可以監控 Kueue Slice Controller 公開的下列 Prometheus 指標,觀察 Slice 生命週期、重複使用和許可檢查:

Slice 生命週期指標

Slice 生命週期指標會追蹤 Slice 的建立和刪除作業:

  • 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 標籤,指出特定錯誤類型。

清除所用資源

為避免產生非預期的費用,請先刪除 slice,再刪除節點集區。

  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。不過,您也可以使用自訂排程器管理動態配量。如果選擇使用其他排程器,請按照切片自訂資源參考資訊操作。

後續步驟