Planifier des tranches dynamiques avec Kueue et TAS

Ce document explique comment provisionner des pools de nœuds TPU et planifier des tranches dynamiques dans Google Kubernetes Engine (GKE) à l'aide de Kueue et de la planification tenant compte de la topologie (TAS).

Vous pouvez également utiliser le découpage dynamique en interagissant directement avec Découper les ressources personnalisées. Pour en savoir plus, consultez Utiliser le fractionnement dynamique avec un planificateur personnalisé.

Avant de suivre ces instructions, assurez-vous de bien comprendre les concepts du slicing dynamique.

Conditions requises

Pour utiliser le slicing dynamique dans GKE, vous devez répondre aux exigences suivantes :

  • Utilisez un cluster standard dans le canal rapide avec l'une des versions suivantes :
    • Pour la configuration du superslicing dynamique (topologies supérieures ou égales à 4x4x4), utilisez la version 1.35.2-gke.1842000 ou ultérieure.
    • Pour la configuration du sous-partitionnement dynamique (topologies plus petites que 4x4x4), utilisez la version 1.36.0-gke.3712000 ou ultérieure.
  • Utilisez la version Ironwood (TPU7x).
  • Utilisez l'image Container-Optimized OS pour vos nœuds.
  • Pour utiliser le provisionnement incrémentiel, utilisez les réservations en mode "Toute la capacité". Le mode "Toute capacité" est une fonctionnalité activée par TPU Cluster Director.
  • Pour le sous-licenciement dynamique, assurez-vous que vos nœuds ont des événements de maintenance en attente. Surveillez vos instances pour détecter les événements de maintenance en attente. Si l'un de vos nœuds présente un événement de maintenance en attente dont l'heure de fin est comprise entre le 18 et le 30 septembre 2026, vous devez déclencher manuellement l'événement de maintenance de l'hôte sur ces nœuds avant de pouvoir utiliser le sous-partitionnement.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

  • Activez l'API Google Kubernetes Engine.
  • Activer l'API Google Kubernetes Engine
  • Pour utiliser Google Cloud CLI pour cette tâche, installez puis initialisez gcloud CLI. Si vous avez déjà installé la gcloud CLI, obtenez la dernière version en exécutant la commande gcloud components update. Il est possible que les versions antérieures de la gcloud CLI ne permettent pas d'exécuter les commandes de ce document.

Utiliser le slicing dynamique dans GKE avec Kueue

Cette section décrit le workflow d'utilisation du slicing dynamique dans GKE.

  1. Affichez la topologie et l'état des réservations en mode "Toute capacité".
  2. Activez le contrôleur de tranche dans votre cluster.
  3. Installez Kueue, JobSet et LWS.
  4. Créez des pools de nœuds TPU.
  5. Configurez Kueue pour créer une ressource personnalisée Slice.
  6. Exécutez des charges de travail sur le découpage dynamique avec Kueue.
  7. Effectuez un nettoyage.

Activer le contrôleur de segments

Pour utiliser le slicing dynamique, activez le contrôleur de tranche dans votre cluster.

  1. Mettez à jour votre cluster :

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

    Remplacez les éléments suivants :

  2. Obtenez des identifiants pour pouvoir communiquer avec votre cluster à l'aide des commandes kubectl :

    gcloud config set container/cluster CLUSTER_NAME
    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=LOCATION
    
  3. Dans le résultat de la commande suivante, vérifiez que la valeur slices.accelerator.gke.io est présente :

    kubectl get crd slices.accelerator.gke.io
    

    Le résultat ressemble à ce qui suit :

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

Installer Kueue, JobSet et LWS

Si vous avez déjà installé Kueue, JobSet et LWS, vous pouvez ignorer cette section.

Installer Kueue

Suivez les instructions de la documentation Kueue ou exécutez la commande suivante :

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

Remplacez KUEUE_VERSION par la version de Kueue requise en fonction de vos exigences de topologie. Pour le sous-licenciement dynamique, utilisez Kueue v0.18.2 ou version ultérieure. Pour le superslicing dynamique, utilisez Kueue v0.16.6 ou version ultérieure.

Installer JobSet

Suivez les instructions de la documentation JobSet ou exécutez la commande suivante :

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

Remplacez JOBSET_VERSION par la version JobSet requise en fonction des exigences de votre topologie. Pour le sous-licenciement dynamique, utilisez JobSet v0.12.0 ou version ultérieure. Pour le super-slicing dynamique, utilisez JobSet v0.11.1 ou version ultérieure.

Installer LWS

Le LeaderWorkerSet (LWS) n'est requis que pour la sous-licence dynamique.

Suivez les instructions de la documentation LWS ou exécutez la commande suivante :

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

Remplacez LWS_VERSION par la version LWS requise. Utilisez LWS v0.8.0 ou version ultérieure.

Créer des pools de nœuds avec provisionnement incrémentiel

Cette section explique comment créer des pools de nœuds TPU avec provisionnement incrémental. GKE convertit toute votre capacité TPU en pools de nœuds comprenant des groupes de 16 nœuds de VM Ironwood (TPU7x), ou sous-blocs. GKE provisionne ces pools de nœuds même lorsqu'il ne parvient pas à trouver toutes les VM opérationnelles. Pour ce faire, il place les nœuds sur les parties opérationnelles de la machine hôte et provisionne progressivement les machines non opérationnelles pendant qu'elles sont réparées.

Vous pouvez cibler votre pool de nœuds pour qu'il appartienne à l'un des éléments suivants :

  • Bloc spécifique de TPU, exposé dans les réservations en mode "Toute la capacité". Le ciblage par bloc permet à GKE de créer le pool de nœuds dans n'importe quel sous-bloc disponible du bloc spécifié.
  • Un sous-bloc spécifique ou un groupe de 16 nœuds de VM Ironwood (TPU7x) de TPU pour un contrôle plus précis.

Créer une règle de charge de travail

Pour créer un pool de nœuds de tranche TPU avec Ironwood (TPU7x), vous devez d'abord créer une règle de charge de travail avec le champ accelerator-topology-mode défini sur provision_only. Ce paramètre déclenche le processus de provisionnement incrémentiel.

Créez une règle de charge de travail :

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

Remplacez les éléments suivants :

  • WORKLOAD_POLICY_NAME : nom de votre règle de charge de travail.
  • PROJECT_ID : ID de votre projet Google Cloud .
  • REGION : région de la règle de charge de travail.

Dans cette commande, procédez comme suit :

  • Définissez toujours le champ accelerator-topology sur 4x4x4 pour qu'il corresponde au nombre total de jetons dans un même sous-bloc.
  • Définissez toujours le champ accelerator-topology-mode sur provision_only pour vous assurer que le processus de provisionnement incrémentiel est déclenché. Lorsque le champ provision_only est défini, le pool de nœuds provisionne des nœuds TPU sans former de liens ICI ni OCS.

Cibler votre pool de nœuds pour qu'il appartienne à un bloc ou à un sous-bloc

Vous pouvez cibler des sous-blocs ou des blocs spécifiques dans votre réservation en mode "Toute capacité".

  • Cibler un bloc : chaque pool de nœuds utilise la capacité d'un bloc spécifié. GKE place le pool de nœuds dans un sous-bloc disponible de ce bloc. Vous devez créer autant de pools de nœuds que de sous-blocs dans le bloc que vous souhaitez utiliser.
  • Cibler un sous-bloc : chaque pool de nœuds est associé à un sous-bloc spécifique et disponible. Lorsque vous utilisez le ciblage par sous-bloc, GKE crée le pool de nœuds si au moins une VM est opérationnelle. Le provisionnement incrémentiel permet de s'assurer que tous les nœuds sont placés dans le sous-bloc spécifié.

Bloquer

  1. Pour récupérer le nom du bloc dans une réservation et le nombre de sous-blocs disponibles dans le bloc, suivez les étapes décrites dans le document Afficher la topologie et l'état des réservations en mode "Toute la capacité" :

    1. Identifiez le nom du bloc en listant tous les blocs de réservation et en copiant la valeur du champ name:. Cette valeur correspond au nom du bloc ou de BLOCK_NAME dans ce document.

    2. Déterminez le nombre de pools de nœuds à créer en décrivant un bloc de réservation et en identifiant la valeur dans le champ reservationSubBlockCount. Cette valeur correspond au nombre de sous-blocs disponibles. Par exemple, la valeur reservationSubBlockCount: 4 indique que le bloc comporte quatre sous-blocs disponibles et que vous devez créer quatre pools de nœuds distincts.

  2. Définissez le chemin de réservation :

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

    Remplacez les éléments suivants :

    • RESERVATION_NAME : nom de votre réservation de TPU.
    • BLOCK_NAME : nom du bloc.
  3. Créez un pool de nœuds pour chaque sous-bloc identifié à l'étape précédente. Par exemple, si le nombre est 4, exécutez cette commande quatre fois. Attribuez un nom unique à chaque pool de nœuds.

    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}
    

    Remplacez les éléments suivants :

    • NODE_POOL_NAME : nom de votre nouveau pool de nœuds.
    • CLUSTER_NAME : nom de votre cluster GKE.
    • WORKLOAD_POLICY_NAME : nom de la règle de charge de travail que vous avez créée.
    • ZONE : zone du pool de nœuds, par exemple us-central1-a.

Sous-bloc

  1. Pour récupérer le nom du bloc et les ID des sous-blocs disponibles, suivez les étapes décrites dans le document Afficher la topologie et l'état des réservations en mode "Toute la capacité" :

    1. Pour identifier le nom du bloc, listez tous les blocs de réservation et copiez la valeur du champ name:. Cette valeur correspond au nom du bloc ou de BLOCK_NAME dans ce document.

    2. Pour identifier le nom des sous-blocs, listez tous les sous-blocs d'un bloc et copiez la valeur du champ name: pour chaque entrée sous reservationSubBlocks. Cette valeur correspond au nom du sous-bloc ou SUBBLOCK_NAME dans ce document.

  2. Définissez le chemin de réservation :

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

    Remplacez les éléments suivants :

    • RESERVATION_NAME : nom de votre réservation de TPU.
    • BLOCK_NAME : nom du bloc.
    • SUBBLOCK_NAME : nom du sous-bloc.
  3. Créez le pool de nœuds :

    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}
    

    Remplacez les éléments suivants :

    • NODE_POOL_NAME : nom unique du nouveau pool de nœuds, par exemple sub-block-pool-1.
    • PROJECT_ID : ID de votre projet Google Cloud .
    • CLUSTER_NAME : nom de votre cluster GKE.
    • ZONE : zone du pool de nœuds, par exemple us-central2-b.
    • WORKLOAD_POLICY_NAME : nom de la règle de charge de travail que vous avez créée.

À ce stade, les nœuds sont créés, mais leurs liens Inter-Chip Interconnect (ICI) ne sont pas encore actifs. Par conséquent, vous ne pouvez pas exécuter directement de charges de travail sur ces pools de nœuds.

Pour activer tous les liens ICI nécessaires à la formation du slice et permettre la planification des charges de travail, créez un slice dynamique à l'aide de l'une des méthodes suivantes :

  • Créez une ressource personnalisée Slice. Au lieu d'utiliser des pods, vous utilisez une ressource personnalisée Slice pour définir la topologie spécifiée, que le contrôleur de tranche active.
  • Planifiez des charges de travail GKE avec Kueue et TAS. Kueue gère automatiquement la création et la suppression des ressources personnalisées Slice. Évitez de modifier manuellement les ressources personnalisées Slice créées par Kueue.

Créer une tranche dynamique avec Kueue et TAS

Dans cette section, vous allez planifier des charges de travail GKE avec Kueue et TAS.

Installer le contrôleur de tranche Kueue

  1. Pour installer le contrôleur de tranche Kueue, enregistrez le fichier manifeste suivant sous le nom 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: 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
      - 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
    
  2. Appliquez le fichier manifeste slice-controller.yaml :

    kubectl apply -f slice-controller.yaml
    
  3. Pour configurer Kueue pour le slicing dynamique, enregistrez le fichier manifeste suivant sous le nom 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. Appliquez le fichier manifeste dynamic-slice-topology.yaml :

    kubectl apply -f dynamic-slice-topology.yaml
    

    Dans ce fichier manifeste, vous configurez Kueue pour le fractionnement dynamique en définissant les ressources suivantes :

    • Topologie de tranche dynamique Ironwood (TPU7x) (superslice-topology) : la topologie définit les niveaux que Kueue prend en compte lorsqu'il planifie les charges de travail de découpage dynamique. Voici les différents niveaux :
      • Libellé cloud.google.com/gce-topology-block : ce niveau est nécessaire pour comprendre quels sous-blocs appartiennent à quels blocs, car seuls les sous-blocs du même bloc peuvent former une tranche.
      • Libellé cloud.google.com/gke-tpu-partition-4x4x4-id : ce niveau représente des sous-blocs Ironwood (TPU7x) individuels (topologie 4x4x4).
      • Libellé kubernetes.io/hostname : ce niveau est requis pour attribuer des pods à des VM spécifiques et pour observer leurs libellés et leurs taints.
    • ResourceFlavor SuperSlice Ironwood (TPU7x) (superslice-rf) : le ResourceFlavor pour les sous-blocs Ironwood (TPU7x) inclut le libellé cloud.google.com/gke-tpu-accelerator: tpu7x pour correspondre aux nœuds avec des machines Ironwood (TPU7x).
    • SuperSlice AdmissionCheck (superslice-ac) : ce contrôle d'admission indique à Kueue de ne pas planifier de charge de travail tant que le contrôleur de tranche GKE n'a pas confirmé que la tranche est devenue active. Le contrôle d'admission est d'abord défini, puis ajouté au ClusterQueue qui gère les charges de travail de segmentation dynamique.
    • ClusterQueue (cq) et LocalQueue (lq) : ces champs gèrent les ressources google.com/tpu. La ressource ClusterQueue cq inclut la vérification de l'admission superslice-ac. Le champ nominalQuota pour google.com/tpu peut être configuré de deux manières :
      • Quota spécifique : définissez le champ nominalQuota pour qu'il corresponde à la capacité existante pour la gestion du partage équitable et des quotas.
      • Quota illimité : définissez le champ nominalQuota sur une valeur très élevée, telle que "999999", pour modéliser un quota illimité. Pour se concentrer sur TAS et le découpage dynamique, cette configuration contourne la fonctionnalité de gestion des quotas de Kueue.

Définir la sélection de l'état de la partition

En plus de l'état et de la disponibilité des nœuds standards, GKE expose l'état spécifique de chaque forme de partition à l'aide du libellé cloud.google.com/gke-tpu-partition-[shape]-state (où [shape] correspond à la forme de l'ID de partition, par exemple 2x2x1, 2x2x2, 2x2x4, 2x4x4 ou 4x4x4). Ce libellé permet à GKE de tenir compte des facteurs qui influencent la formation des tranches, tels que l'état des liens TPU. La configuration du sous-licenciement dynamique (topologies inférieures à 4x4x4) nécessite la version 1.36.0-gke.3712000 de GKE ou une version ultérieure.

Vous pouvez définir la valeur du libellé d'état de la partition comme suit :

  • HEALTHY : la partition est en bon état et entièrement fonctionnelle.
  • DEGRADED : l'infrastructure de la partition est dans un état dégradé, par exemple en raison de la dégradation du lien OCS. La partition peut toujours former une tranche, mais les performances globales peuvent être inférieures à celles des partitions saines. Cet état ne s'applique qu'à la topologie 4x4x4 de premier niveau. Les topologies plus petites n'ont pas d'état dégradé.
  • UNHEALTHY : la partition n'est pas saine et ne peut pas former de tranche.
  • UNSET : l'état n'est pas défini en raison de l'échec de l'initialisation du contrôleur de tranche GKE.
  • INCOMPLETE : tous les nœuds de la partition ne sont pas provisionnés.

Le webhook du contrôleur de tranche Kueue valide si une charge de travail inclut une exigence spécifique concernant l'état de la partition. Si aucune préférence n'est indiquée, le webhook injecte une affinité de nœud par défaut.

Voici le comportement à suivre :

  • Si un nodeSelector ou un nodeAffinity ciblant le libellé cloud.google.com/gke-tpu-partition-[shape]-state est présent, il reste inchangé.
  • Si aucune configuration de libellé de ce type n'existe, le webhook insère l'affinité de nœud par défaut suivante pour s'assurer que seules les partitions disponibles sont utilisées :

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

La section suivante inclut des exemples dans lesquels le libellé cloud.google.com/gke-tpu-partition-4x4x4-state est configuré pour spécifier les différentes configurations d'état des sous-blocs.

Exécuter des charges de travail de test sur le partitionnement dynamique avec Kueue

Cette section explique comment déployer des charges de travail sur le découpage dynamique avec Kueue et TAS. Il inclut des exemples montrant comment créer une charge de travail de tranche dynamique et une charge de travail composée de plusieurs tranches. Les charges de travail sont envoyées en tant que JobSets.

Exemple 1 : Une seule charge de travail utilise un seul slice dynamique

L'exemple suivant décrit comment créer une charge de travail à l'aide d'une tranche avec une topologie 4x12x16, qui est composée de 12 sous-blocs. Le nombre de pods a été calculé comme suit : (4 * 12 * 16) / 4 puces par nœud = 192 pods.

  1. Enregistrez le manifeste suivant sous le nom 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
    

    Dans ce fichier manifeste, les annotations suivantes indiquent à Kueue les caractéristiques et la topologie de la tranche à configurer :

    • cloud.google.com/gke-tpu-slice-topology : spécifie "4x12x16" comme topologie de tranche dynamique. Les exigences concernant la topologie d'accélérateur tpu7x incluent les règles suivantes :
      • Pour le sous-partitionnement dynamique : vous pouvez spécifier des topologies plus petites que 4x4x4, telles que 2x2x1, 2x2x2, 2x2x4 ou 2x4x4. Ces topologies plus petites nécessitent GKE version 1.36.0-gke.3712000 ou ultérieure.
      • Pour le superslicing dynamique : vous pouvez spécifier des topologies égales ou supérieures à 4x4x4. Pour la configuration du superslicing dynamique, chaque dimension de la topologie demandée doit être un multiple de quatre (par exemple, 4A x 4B x 4C).
      • La topologie doit être une chaîne tridimensionnelle au format AxBxC, par exemple 4x8x8.
      • Les dimensions doivent être triées par ordre croissant : A <= B <= C. Par exemple, 4x8x4 n'est pas valide et doit être remplacé par 4x4x8.
      • Le produit des dimensions (ABC) ne doit pas dépasser 9 216.
      • Les topologies de tranche les plus grandes acceptées peuvent inclure jusqu'à 32 sous-blocs. Par exemple, 8x16x16 avec 32 sous-blocs, 8x12x20 avec 30 sous-blocs ou 12x12x12 avec 27 sous-blocs sont dans les limites acceptées.
    • cloud.google.com/gke-tpu-accelerator: tpu7x : planifie les pods sur les VM qui exécutent Ironwood (TPU7x).
    • kueue.x-k8s.io/queue-name : attribue le JobSet à une LocalQueue Kueue.
    • Le webhook injecte l'affinité de nœuds par défaut pour s'assurer que les nœuds HEALTHY et DEGRADED sont utilisés.
  2. Appliquez le fichier manifeste big-super-slice.yaml :

    kubectl apply -f big-super-slice.yaml
    

    Une fois le fichier manifeste appliqué, Kueue crée un JobSet nommé big-super-slice. Kueue tente ensuite de former une seule tranche dynamique avec une topologie 4x12x16. Une fois le slice actif, Kueue accepte la charge de travail et les 192 pods sont planifiés sur les nœuds pour former le slice dynamique qui exécute vos charges de travail.

Exemple 2 : Charge de travail avec plusieurs répliques

L'exemple suivant montre comment créer une charge de travail qui utilise deux tranches dynamiques, chacune composée de quatre sous-blocs ciblant uniquement les nœuds HEALTHY.

  1. Enregistrez le manifeste suivant sous le nom 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. Appliquez le fichier manifeste two-super-slices.yaml :

    kubectl apply -f two-super-slices.yaml
    

Dans ce fichier manifeste, vous définissez le champ replicas sur 2 dans la section replicatedJobs. Une fois le fichier manifeste appliqué, Kueue tente de former deux tranches distinctes avec une topologie 4x8x8. Kueue crée une tranche dynamique pour chaque réplica défini dans jobset.spec.replicatedJobs[].replicas. Si n répliques sont spécifiées, Kueue crée n tranches dynamiques pour la charge de travail et attend que toutes les tranches deviennent actives avant d'admettre la charge de travail.

Surveiller le segment

Vous pouvez consulter l'état du slice et surveiller ses métriques avec les métriques système GKE.

Surveiller l'état de la tranche

Pour vérifier l'état de vos tranches dynamiques, exécutez la commande suivante :

kubectl describe slice SLICE_NAME

Remplacez SLICE_NAME par le nom de votre tranche. Le nom du slice est généralement dérivé du nom JobSet et de l'index de réplica. Dans l'exemple 1, une tranche créée par Kueue aurait un nom semblable à default-jobset-big-super-slice-yyyyy-job-jax-0.

Le résultat ressemble à ce qui suit :

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>

Le nom de la tranche respecte les règles suivantes pour assurer la compatibilité avec les conventions d'attribution de noms des ressources Compute Engine sous-jacentes :

  • Modèle : {namespace}-jobset-{jobset.metadata.name}-kueueHash[5-character]-{jobset.spec.replicatedJobs[].name}-sliceIndex.
  • Longueur : le nom ne comporte pas plus de 49 caractères. L'application de contrôleur ajoute un tiret et un hachage de cluster de huit caractères pour créer des noms de ressources Compute Engine, qui sont limités à 63 caractères.
  • Format : le nom correspond à l'expression régulière ^[a-z]([-a-z0-9]*[a-z0-9])?$. Le nom présente les caractéristiques suivantes :
    • Commence par une lettre minuscule.
    • Ne contenir que des lettres minuscules, des chiffres et des traits d'union (-).
    • Se termine par une lettre minuscule ou un chiffre (il ne peut pas se terminer par un trait d'union).

Surveiller les métriques du segment

Vous pouvez surveiller les métriques système GKE suivantes qui exposent l'état d'une tranche :

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

Pour en savoir plus sur les métriques, consultez Métriques système GKE.

Effectuer un nettoyage

Pour éviter des frais inattendus, supprimez vos tranches avant de supprimer les pools de nœuds.

  1. Supprimez le JobSet. Cette action déclenche la suppression des ressources personnalisées Slice associées par Kueue.

    kubectl delete jobset JOBSET_NAME
    

    Remplacez JOBSET_NAME par le nom de votre JobSet, par exemple big-super-slice.

  2. Supprimez le pool de nœuds TPU :

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

(Facultatif) Utiliser le slicing dynamique avec votre propre programmateur

Ce document se concentre sur l'utilisation de Kueue et TAS. Toutefois, vous pouvez également gérer le fractionnement dynamique avec votre propre planificateur personnalisé. Si vous choisissez d'utiliser un autre planificateur, suivez les informations de référence sur la ressource personnalisée Slice.

Étapes suivantes