使用 Kueue 和 TAS 排定動態配額

本文說明如何使用 Kueue拓撲感知排程 (TAS),在 Google Kubernetes Engine (GKE) 中佈建 TPU 節點集區,並排定動態切片。

您也可以直接與Slice 自訂資源互動,使用動態切片。詳情請參閱「使用自訂排程器進行動態切片」。

按照這些操作說明操作前,請務必瞭解動態切片的概念

需求條件

如要在 GKE 中使用動態切片,必須符合下列規定:

  • 在 Rapid 管道中使用 1.35.2-gke.1842000 以上版本的 Standard 叢集。
  • 使用 Ironwood (TPU7x) 版本。
  • 為節點使用 Container-Optimized OS 映像檔。
  • 如要使用增量佈建,請使用「所有容量模式」預留項目。所有容量模式都是由 TPU Cluster Director 啟用的功能。

事前準備

開始之前,請務必先完成下列工作:

  • 啟用 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. 建立 TPU 節點集區
  4. 設定 Kueue 建立 Slice 自訂資源
  5. 使用 Kueue 在動態切片上執行工作負載
  6. 清除所用資源

啟用 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
    

建立節點集區並啟用增量佈建

本節說明如何使用增量佈建建立 TPU 節點集區。GKE 會將所有 TPU 容量轉換為 16 個節點的 TPU VM 群組或子區塊節點集區。即使 GKE 無法找到所有 16 個健康狀態良好的 VM,仍會佈建這些節點集區,方法是將節點放在主機的健康狀態良好部分,並在修復健康狀態不良的機器時,逐步佈建這些機器。

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

  • 特定 TPU 區塊,在「所有容量」模式預留中公開。區塊目標設定可讓 GKE 在指定區塊內的任何可用子區塊中建立節點集區。
  • TPU 的特定子區塊,或 TPU 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 控制器會啟動該拓撲。
  • 使用 KueueTAS 安排 GKE 工作負載時程。Kueue 會自動處理 Slice 自訂資源的建立和刪除作業。請避免手動修改 Kueue 建立的 Slice 自訂資源。

使用 Kueue 和 TAS 建立動態切片

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

安裝 JobSet 和 Kueue 資源,進行動態切片

  1. 安裝 JobSet:

    helm install jobset oci://registry.k8s.io/jobset/charts/jobset \
            --version 0.11.1 \
            --namespace jobset-system \
            --create-namespace \
            --set controller.resources.requests.cpu=4 \
            --set controller.resources.requests.memory=16Gi
    
  2. 安裝 Kueue

    helm install kueue oci://registry.k8s.io/kueue/charts/kueue \
            --version 0.16.6 \
            --namespace kueue-system \
            --create-namespace \
            --wait \
            --set controllerManager.replicas=3 \
            --set controllerManager.manager.resources.requests.cpu=16 \
            --set controllerManager.manager.resources.requests.memory=64Gi
    
  3. 如要安裝 Kueue 切片控制器,請將下列資訊清單儲存為 slice-controller.yaml

    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: ClusterRole
    metadata:
      labels:
        control-plane: controller-manager
      name: slice-controller-manager-role
    rules:
    - apiGroups:
      - ""
      resources:
      - events
      verbs:
      - create
      - patch
      - update
      - watch
    - apiGroups:
      - ""
      resources:
      - nodes
      - pods
      verbs:
      - get
      - list
      - watch
    - apiGroups:
      - ""
      resources:
      - secrets
      verbs:
      - get
      - list
      - update
      - 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:
      - admissionregistration.k8s.io
      resources:
      - mutatingwebhookconfigurations
      verbs:
      - get
      - list
      - update
      - watch
    - apiGroups:
      - batch
      resources:
      - jobs
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - jobset.x-k8s.io
      resources:
      - jobsets
      verbs:
      - get
      - list
      - patch
      - update
      - watch
    - apiGroups:
      - leaderworkerset.x-k8s.io
      resources:
      - leaderworkersets
      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
    ---
    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: 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=6m
            command:
            - /manager
            image: tpuongke/kueue-slice-controller:latest
            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: 12000m
                memory: 32Gi
              requests:
                cpu: 8000m
                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
    
  4. 套用 slice-controller.yaml 資訊清單:

    kubectl apply -f slice-controller.yaml
    
  5. 如要設定 Kueue 進行動態切片,請將下列資訊清單儲存為 dynamic-slice-topology.yaml

    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
    
  6. 套用 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/tpunominalQuota 可以透過下列兩種方式設定:
      • 特定配額:設定 nominalQuota 以符合現有容量,確保公平分享和配額管理。
      • 無限制配額:將 nominalQuota 設為極高的值 (例如 "999999"),模擬無限制配額。為著重說明 TAS 和動態切片,這項設定會略過 Kueue 的配額管理功能。

定義子區塊健康狀態選取範圍

除了標準節點健康狀態和就緒狀態之外,GKE 還會使用 cloud.google.com/gke-tpu-partition-4x4x4-state 標籤公開每個子區塊的特定狀態。GKE 可透過這個標籤考量影響切片形成的因素,例如 TPU 連結的狀態。

您可以按照下列方式定義 cloud.google.com/gke-tpu-partition-4x4x4-state 標籤的值:

  • HEALTHY:基礎架構健康狀態良好。
  • DEGRADED:子區塊的基礎架構處於降級狀態,例如 OCS 連結降級。子區塊仍可形成切片,但整體效能可能不如正常的子區塊。
  • UNHEALTHY:子區塊不健全,無法形成切片。

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

行為如下:

  • 如果存在以 cloud.google.com/gke-tpu-partition-4x4x4-state 標籤為目標的 nodeSelectornodeAffinity,則不會變更。
  • 如果沒有這類標籤設定,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

    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
      name: big-super-slice
      labels:
        kueue.x-k8s.io/queue-name: lq
      annotations:
    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
      • 拓撲必須是三維字串,格式為 AxBxC。例如:4x8x8
      • 每個維度 (A、B 和 C) 都必須是 4 的倍數。
      • 尺寸必須以非遞減順序排序: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 會插入預設節點相依性,確保使用 HEALTHYDEGRADED 節點。
  2. 套用 big-super-slice.yaml 資訊清單:

    kubectl apply -f big-super-slice.yaml
    

    套用資訊清單後,Kueue 會建立名為 big-super-sliceJobSet。 Kueue 接著會嘗試使用 4x12x16 拓撲形成單一動態切片。切片啟用後,Kueue 會允許工作負載,並在節點上排定 192 個 Pod,形成動態切片來執行工作負載。

範例 2:具備多個副本的工作負載

以下範例說明如何建立工作負載,使用兩個動態切片,每個切片都由四個子區塊組成,只以 HEALTHY 節點為目標。

  1. 將下列資訊清單儲存為 two-super-slices.yaml

    apiVersion: jobset.x-k8s.io/v1alpha2
    kind: JobSet
    metadata:
    name: two-super-slices
    labels:
        kueue.x-k8s.io/queue-name: lq
    annotations:
    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 個動態切片,並等待所有切片都處於啟用狀態,再允許工作負載。

監控切片

您可以查看切片狀態,並使用 GKE 系統指標監控切片指標。

監控切片狀態

如要檢查動態切片的狀態,請執行下列指令:

kubectl describe slice SLICE_NAME

SLICE_NAME 替換為切片名稱。切片名稱通常衍生自 JobSet 名稱和副本索引。以「範例 1」來說,Kueue 建立的切片名稱會類似於 default-jobset-big-super-slice-yyyyy-job-jax-0

輸出結果會與下列內容相似:

Name:         test-slice
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>

為確保與基礎 Compute Engine 資源命名慣例相容,切片名稱須遵守下列規則:

  • 範本: {namespace}-jobset-{jobset.metadata.name}-kueueHash[5-character]-{jobset.spec.replicatedJobs[].name}-sliceIndex
  • 長度:名稱不得超過 49 個半形字元。控制器會附加連字號和 8 個半形字元的叢集雜湊值,建立 Compute Engine 資源名稱,這些名稱的長度上限為 63 個半形字元。
  • 格式:名稱符合規則運算式 ^[a-z]([-a-z0-9]*[a-z0-9])?$。名稱具有下列特徵:
    • 開頭為小寫英文字母。
    • 只能包含小寫字母、數字和連字號 (-)。
    • 結尾為小寫英文字母或數字 (不得為連字號)。

監控切片的指標

您可以監控下列 GKE 系統指標,瞭解切片的狀況:

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

如要進一步瞭解指標,請參閱「GKE 系統指標」。

清除所用資源

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

  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 自訂資源參考資訊。

後續步驟