使用 Kueue 和 TAS 调度动态切片

本文档介绍了如何使用 Kueue 和拓扑感知调度 (TAS) 在 Google Kubernetes Engine (GKE) 中预配 TPU 节点池并调度动态切片。

您还可以通过直接与切片自定义资源交互来使用动态切片。如需了解详情,请参阅将动态切片与自定义调度器搭配使用。

在按照这些说明操作之前,请确保您了解动态切片的概念。

要求

如需在 GKE 中使用动态切片,您必须满足以下要求:

  • 在快速渠道中使用以下任一版本的 Standard 集群:
    • 对于动态超级切片配置(拓扑等于或大于 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 可能不支持运行本文档中的命令。
  • 确保您已有 1.35.2-gke.1842000 版或更高版本的 Standard 集群(在快速渠道中)。如需创建新集群,请参阅创建区域级集群。
  • 确保您在所在区域有足够的 Ironwood (TPU7x) 配额。
  • 如果您计划运行多切片工作负载,请安装 JobSet v0.10.1 或更高版本。
  • 如果您计划运行 Ray 工作负载,请在 GKE 1.37 版或更高版本上启用 Ray Operator 插件。或者,如果您自行管理开源 KubeRay 安装,而不是使用插件,请安装 KubeRay v1.6.2 或更高版本以及 Ray TPU 网络钩子 v1.4.2 或更高版本。
  • 在全容量模式下请求 TPU 容量。

在 GKE 中将动态切片与 Kueue 搭配使用

本部分介绍了在 GKE 中使用动态切片的工作流。

  1. 查看全容量模式预留的拓扑和健康状态。
  2. 在集群中启用切片控制器。
  3. 安装 Kueue、JobSet、LWS 和 KubeRay。
  4. 创建 TPU 节点池。
  5. 配置 Kueue 以创建 Slice 自定义资源。
  6. 使用 Kueue 在动态切片上运行工作负载。
  7. 清理.

启用切片控制器

如需使用动态切片,请在集群中启用切片控制器。

  1. 更新集群:

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

    替换以下内容:

    • CLUSTER_NAME:您的集群的名称。
    • LOCATION:具有可用 TPU 容量的区域。
  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 和 KubeRay

如果您已安装 Kueue、JobSet、LWS 或 KubeRay,则可以跳过此部分。

安装 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 v0.16.6 或更高版本。如果您计划运行 Ray 工作负载,请使用 Kueue v0.20.1 或更高版本,或者 v0.19 版本系列中的 v0.19.8 或更高版本。

安装 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 v0.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 或更高版本。

安装 KubeRay

如果您计划运行 Ray 工作负载,请在集群上启用 Ray Operator。Ray Operator 需要 GKE 1.37 版或更高版本:

gcloud container clusters update CLUSTER_NAME \
    --location=LOCATION \
    --update-addons=RayOperator=ENABLED

替换以下内容:

  • CLUSTER_NAME:您的集群的名称。
  • LOCATION:集群的 Compute Engine 区域或可用区。

Ray Operator 插件会自动包含 Ray TPU 网络钩子。如果您自行管理开源 KubeRay 安装,而不是使用插件,请按照 KubeRay 文档中的说明安装 KubeRay v1.6.2 或更高版本。然后,通过安装 Ray TPU 网络钩子 v1.4.2 或更高版本来配置 TPU 工作进程环境变量和准入。

创建具有增量预配功能的节点池

本部分介绍了如何通过增量预配创建 TPU 节点池。GKE 会将您的所有 TPU 容量转换为节点池,这些节点池由 Ironwood (TPU7x) 虚拟机或子块的 16 节点组组成。即使 GKE 无法找到所有运行状况良好的虚拟机,它也会通过将节点放置在宿主机运行状况良好的部分,并在运行状况不佳的机器修复时以增量方式预配这些机器,来预配这些节点池。

您可以将节点池定位到以下任一位置:

  • 在全容量模式预留中公开的特定 TPU 块。通过块定位,GKE 可以在指定块内的任何可用子块中创建节点池。
  • TPU 的特定子块或特定 16 节点 Ironwood (TPU7x) 虚拟机组,可实现更精细的控制。

创建工作负载政策

如需使用 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 会将节点池放置在该块中的可用子块内。您必须创建与要使用的块中的子块数量相同的节点池。
  • 定位到子块:每个节点池都会映射到特定的可用子块。使用子块定位时,如果至少有一个虚拟机运行状况良好,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)来定义指定的拓扑,切片控制器会激活该拓扑。
  • 使用 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/v1beta2
    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
      # Labels to identify dynamic sub-slice partitions (GKE 1.36.0-gke.3712000+).
      - nodeLabel: cloud.google.com/gke-tpu-partition-2x4x4-id
      - nodeLabel: cloud.google.com/gke-tpu-partition-2x2x4-id
      - nodeLabel: cloud.google.com/gke-tpu-partition-2x2x2-id
      - nodeLabel: cloud.google.com/gke-tpu-partition-2x2x1-id
      # Standard Kubernetes label for individual nodes.
      # Required to assign Pods to specific VMs.
      - nodeLabel: kubernetes.io/hostname
    ---
    apiVersion: kueue.x-k8s.io/v1beta2
    kind: ResourceFlavor
    metadata:
      name: superslice-rf
    spec:
      nodeLabels:
        cloud.google.com/gke-tpu-accelerator: tpu7x
      topologyName: superslice-topology
    ---
    apiVersion: kueue.x-k8s.io/v1beta2
    kind: ResourceFlavor
    metadata:
      name: default-flavor
    spec: {}
    ---
    apiVersion: kueue.x-k8s.io/v1beta2
    kind: AdmissionCheck
    metadata:
      name: superslice-ac
    spec:
      controllerName: accelerator.gke.io/slice
    ---
    apiVersion: kueue.x-k8s.io/v1beta2
    kind: ClusterQueue
    metadata:
      name: cq
    spec:
      namespaceSelector: {}
      admissionChecksStrategy:
        admissionChecks:
        - name: superslice-ac
      preemption:
        withinClusterQueue: LowerPriority
      resourceGroups:
      - coveredResources:
        - google.com/tpu
        flavors:
        - name: superslice-rf
          resources:
          - name: google.com/tpu
            nominalQuota: "999999"  # modeling unlimited quota
      - coveredResources:
        - cpu
        - memory
        flavors:
        - name: default-flavor
          resources:
          - name: cpu
            nominalQuota: "999999"
          - name: memory
            nominalQuota: "999999Gi"
    ---
    apiVersion: kueue.x-k8s.io/v1beta2
    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 拓扑)。
      • cloud.google.com/gke-tpu-partition-2x4x4-id、cloud.google.com/gke-tpu-partition-2x2x4-id、cloud.google.com/gke-tpu-partition-2x2x2-id 和 cloud.google.com/gke-tpu-partition-2x2x1-id 标签:这些级别表示子块内的动态子切片分区,需要 GKE 1.36.0-gke.3712000 版或更高版本。
      • kubernetes.io/hostname 标签:需要此级别才能将 Pod 分配给特定虚拟机并观察其标签和污点。
    • Ironwood (TPU7x) SuperSlice ResourceFlavor (superslice-rf) 和默认 ResourceFlavor (default-flavor):superslice-rf 资源变体包含 cloud.google.com/gke-tpu-accelerator: tpu7x 标签,用于将节点与 Ironwood (TPU7x) 机器进行匹配。空 default-flavor 资源变体与仅 CPU Pod(例如 Ray 头 Pod)匹配。
    • SuperSlice AdmissionCheck (superslice-ac):此准入检查会告知 Kueue,在 GKE 切片控制器确认切片已变为活跃状态之前,不要调度工作负载。首先定义准入检查,然后将其添加到处理动态切片工作负载的 ClusterQueue。
    • ClusterQueue (cq) 和 LocalQueue (lq):这些字段用于管理 google.com/tpu、cpu 和 memory 资源。cq ClusterQueue 在 admissionChecksStrategy 部分下包含 superslice-ac 准入检查。您可以通过以下两种方式配置 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 切片控制器初始化失败,状态未定义。
  • INCOMPLETE:并非分区内的所有节点都已预配。

Kueue Slice Controller 网络钩子会验证工作负载是否包含特定的分区健康状况要求。如果未指明偏好设置,则 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 或 Ray 资源的形式提交。

示例 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 个子块。例如,具有 32 个子块的 8x16x16、具有 30 个子块的 8x12x20 或具有 27 个子块的 12x12x12 都在可接受的限制范围内。
    • cloud.google.com/gke-tpu-accelerator: tpu7x:在运行 Ironwood (TPU7x) 的虚拟机上调度 Pod。
    • kueue.x-k8s.io/queue-name:将 JobSet 分配给 Kueue LocalQueue。
    • 该网络钩子会注入默认节点亲和性,以确保使用 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 个动态切片,并等待所有切片变为活跃状态,然后再准入工作负载。

示例 3:在动态切片上运行 Ray 工作负载

以下示例展示了如何使用 KubeRay 和 Kueue TAS 在动态切片上运行分布式 Ray 工作负载。在部署工作负载之前,请确保您已安装 KubeRay。

此示例部署了一个 RayJob 自定义资源,该资源请求跨两个 tpu7x-standard-4t 工作器主机(8 个芯片,16 个逻辑 JAX 设备)的 2x2x2 动态子切片。RayJob 资源会运行一个 Python 脚本,该脚本会初始化 Ray 并验证两个工作器主机上的 JAX TPU 设备分配情况。

  1. 将以下清单保存为 rayjob-dynamic-slice.yaml:

    apiVersion: ray.io/v1
    kind: RayJob
    metadata:
      generateName: rayjob-tpu7x-dynamic-slice-
      labels:
        # Target the Kueue LocalQueue
        kueue.x-k8s.io/queue-name: lq
    spec:
      # Required by Kueue RayJob validating webhook
      shutdownAfterJobFinishes: true
      entrypoint: |
        python -u -c '
        import os
        import ray
    
        ray.init()
        print("=== Ray Cluster Initialized ===")
        print("Cluster resources:", ray.cluster_resources())
    
        @ray.remote(resources={"TPU": 4})
        def check_worker():
            import jax
            jax.distributed.initialize()
            return {
                "hostname": os.getenv("HOSTNAME"),
                "backend": jax.default_backend(),
                "device_count": jax.device_count(),
                "local_device_count": jax.local_device_count(),
                "devices": [str(d) for d in jax.devices()],
            }
    
        # Dispatch tasks across both worker hosts in the 2x2x2 subslice
        futures = [check_worker.remote() for _ in range(2)]
        results = ray.get(futures)
        print("=== Worker TPU Devices ===")
        for r in results:
            print(r)
        '
      rayClusterSpec:
        rayVersion: '2.60.0'
        headGroupSpec:
          rayStartParams: {}
          template:
            spec:
              containers:
              - name: ray-head
                image: rayproject/ray:2.60.0-py312
                resources:
                  limits:
                    cpu: "2"
                    memory: 4Gi
                  requests:
                    cpu: "1"
                    memory: 2Gi
        workerGroupSpecs:
        - groupName: tpu-workers
          replicas: 1
          minReplicas: 1
          maxReplicas: 1
          numOfHosts: 2
          rayStartParams: {}
          template:
            metadata:
              annotations:
                # Request the specific GKE TPU subslice topology
                cloud.google.com/gke-tpu-slice-topology: 2x2x2
            spec:
              nodeSelector:
                cloud.google.com/gke-tpu-accelerator: tpu7x
              tolerations:
              - key: "google.com/tpu"
                operator: "Equal"
                value: "present"
                effect: "NoSchedule"
              containers:
              - name: ray-worker
                image: rayproject/ray:2.60.0.b7f425-py312-tpu
                resources:
                  limits:
                    google.com/tpu: 4
                  requests:
                    google.com/tpu: 4

    在此清单中,以下内容适用:

    • cloud.google.com/gke-tpu-slice-topology: "2x2x2":请求 2x2x2 动态子切片。Kueue 切片控制器网络钩子会自动为 2x2x2 分区注入所需的 Kueue TAS 注解。
    • kueue.x-k8s.io/queue-name: lq:定位到 Kueue LocalQueue。
    • shutdownAfterJobFinishes: true:在批量作业完成时自动关闭 Ray 集群。Kueue 必需。
    • tolerations:明确容忍 google.com/tpu=present:NoSchedule 污点,以便 Kueue TAS 在准入前验证 PodSet 模板。
  2. 通过 rayjob-dynamic-slice.yaml 清单创建 RayJob:

    kubectl create -f rayjob-dynamic-slice.yaml
    
  3. 验证 Kueue 是否已允许工作负载,以及动态切片是否处于活跃状态:

    kubectl get slices.accelerator.gke.io
    

    输出会确认切片的状态为 ACTIVE:

    NAME                                                TYPE    TOPOLOGY   STATE    AGE
    rayjob-tpu7x-dynamic-slice-tpu-workers-0-046a2cbc   tpu7x   2x2x2      ACTIVE   20s
    
  4. 通过检查作业提交者日志,验证工作器之间的 TPU 发现:

    kubectl logs -l ray.io/originated-from-crd=RayJob -c ray-job-submitter --tail=-1
    

    在输出中,确认以下详细信息:

    • Cluster resources 部分包含 'TPU': 8.0 键值对。
    • === Worker TPU Devices === 部分显示 backend: 'tpu' 块,其中包含两个工作器的 device_count: 16 和 local_device_count: 8 键值对。
    • 输出以 Job 'rayjob-tpu7x-dynamic-slice-...' succeeded 消息结尾。

创建 RayJob 后,Kueue 会将工作负载排入队列,直到动态切片处于活跃状态,然后准入工作负载,并启动 Ray 集群以运行入口点脚本。

对于交互式或长时间运行的 Ray 集群,您可以使用 raycluster-dynamic-slice.yaml 示例部署 RayCluster 自定义资源。设置 spec.suspend: true 键值对,以便 Kueue 在 KubeRay 创建工作器 Pod 之前预配动态切片。

通过切片重复使用优化工作负载调度

默认情况下,Kueue 会指示切片控制器为每次工作负载执行预配一个新的 TPU 切片,并在工作负载完成时将其删除。此行为可能会导致底层基础架构出现流失和开销。

借助切片重用功能,新工作负载可以重用具有相同拓扑和硬件限制的现有空闲 TPU 切片。启用切片重复使用后,Kueue 会在作业结束时将切片标记为空闲,而不是将其删除。请求同一分区的新作业会立即声明并重复使用该切片,从而绕过硬件预配延迟。

启用切片重复使用

如需充分优化切片重用,您必须同时配置 Slice 控制器和 Kueue,使其协同工作。

  1. 配置切片控制器:更新 Kueue 切片控制器部署参数,以包含 --reuse-slices=true 标志。为确保在现有切片上以最佳方式调度工作负载,请同时添加 --add-preferred-node-affinity=true 标志。

  2. 配置 Kueue(推荐):如需允许 Kueue 使用控制器的首选节点亲和性建议,您必须在 Kueue 配置中启用 TASRespectNodeAffinityPreferred 特性门控。

    例如,修改 kueue-manager-config ConfigMap 以添加特性门控:

    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. 将以下标签应用于作业或 JobSet 定义:

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

    应用此标签后,工作负载仍可调度到现有的空闲切片上。不过,在工作负载完成后,切片将被永久删除,而不是返回到可重复使用的池中。

  2. 通过将该标签添加到 Kueue 配置中的 labelKeysToCopy 列表,配置 Kueue 将该标签从框架 Job 传递到 Kueue Workload 对象:

    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 工作负载的名称,通常与作业或 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 控制器指标

您还可以监控 Kueue Slice Controller 公开的以下 Prometheus 指标,以观察切片生命周期、重复使用和准入检查:

切片生命周期指标

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 标签,用于指示具体的错误类型。

清理

为避免产生意外费用,请先删除切片,然后再删除节点池。

  1. 删除工作负载。此操作会触发 Kueue 删除关联的 Slice 自定义资源:

    • 对于 JobSet:

      kubectl delete jobset JOBSET_NAME
      

      将 JOBSET_NAME 替换为 JobSet 的名称,例如 big-super-slice。

    • 对于 RayJob:

      kubectl delete rayjob -l kueue.x-k8s.io/queue-name=lq
      
    • 对于 RayCluster:

      kubectl delete raycluster RAY_CLUSTER_NAME
      

      将 RAY_CLUSTER_NAME 替换为您的 RayCluster 的名称。

  2. 删除 TPU 节点池:

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

(可选)将动态切片与您自己的调度器搭配使用

本文档重点介绍如何使用 Kueue 和 TAS。不过,您也可以使用自己的自定义调度器来管理动态切片。如果您选择使用其他调度器,请遵循切片自定义资源参考信息。

后续步骤