使用 TPU 和灵活启动虚拟机运行小型批量工作负载

本指南介绍如何使用灵活启动虚拟机优化中小型训练工作负载的 TPU 预配。灵活启动虚拟机是使用灵活启动使用选项创建的。在本指南中,您将使用灵活启动虚拟机来部署包含 TPU 切片节点池的工作负载。

本指南适用于机器学习 (ML) 工程师、平台管理员和运维人员,以及对使用 Kubernetes 容器编排功能运行批量工作负载感兴趣的数据和 AI 专家。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE 用户角色和任务

灵活启动价格

如果您的工作负载需要根据需要动态配置资源(最多 7 天,短期预留)、无需复杂的配额管理且可经济高效地访问,建议使用灵活启动。 灵活启动由动态工作负载调度器提供支持,并按照动态工作负载调度器价格计费:

  • vCPU、GPU 和 TPU 可享受折扣(最高 53%)。
  • 随用随付。

准备工作

在开始之前,请确保您已执行以下任务:

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请通过运行 gcloud components update 命令来获取最新版本。较早版本的 gcloud CLI 可能不支持运行本文档中的命令。
  • 验证您是否拥有运行 1.33.0-gke.1712000 版或更高版本的 Autopilot 集群标准集群
  • 确认您已熟悉灵活启动的限制
  • 使用 Standard 集群时,验证您是否至少维护了一个未启用灵活启动的节点池,以便集群能够正常运行。
  • 验证您在节点位置是否拥有抢占式 TPU 的配额。

创建具有灵活启动的节点池

如果您在 Autopilot 模式下使用集群,请跳过本部分,然后前往运行批量工作负载部分。

如需在现有 Standard 集群上创建启用了灵活启动的节点池,请使用 gcloud CLI。

创建单主机 TPU 切片节点池

您可以创建启用了灵活启动的单主机 TPU 切片节点池:

  1. 创建具有灵活启动的节点池:

    gcloud container node-pools create NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION \
        --node-locations=NODE_ZONES \
        --machine-type=MACHINE_TYPE \
        --reservation-affinity=none \
        --enable-autoscaling \
        --flex-start \
        --num-nodes 0 \
        --min-nodes=0 \
        --max-nodes=1
    

    替换以下内容:

    • NODE_POOL_NAME:您为节点池选择的名称。
    • CLUSTER_NAME:集群的名称。
    • CONTROL_PLANE_LOCATION:集群控制平面的计算区域
    • NODE_ZONES:GKE 在其中创建节点池的一个或多个可用区的英文逗号分隔列表。
    • MACHINE_TYPE:用于节点的机器类型。如需详细了解与 TPU 兼容的机器类型,请使用选择 TPU 版本中的表。

      例如,您的节点池创建命令可以包含以下参数:

      ...
      --machine-type=ct6e-standard-4t \
      --tpu-topology=4x4 \
      --enable-autoscaling \
      --num-nodes=0 \
      --max-nodes=4 \
      

      此命令将 --max-nodes 字段设置为 4,因为 4x4 拓扑包含 16 个芯片,而每个 ct6e-standard-4t 虚拟机有 4 个芯片。

      集群自动扩缩器会扩容到工作负载所需的节点数量。工作负载完成后,集群自动扩缩器会将集群缩减至零个节点。

    • --reservation-affinity=none:灵活启动不使用或不需要预留。

创建多主机 TPU 切片节点池

创建多主机 TPU 切片节点池的步骤因您使用的是 Ironwood (TPU7x) 还是更早的 TPU 版本而异。

Ironwood (TPU7x)

您可以使用 Google Cloud CLI 或 Terraform 在 Ironwood 版本 (TPU7x) 中创建多主机 TPU 切片节点池:

gcloud

如需使用 Ironwood (TPU7x) 创建多主机 TPU 切片节点池,您必须先创建工作负载政策。

  1. 创建工作负载政策:

    gcloud compute resource-policies create workload-policy WORKLOAD_POLICY_NAME \
        --type=HIGH_THROUGHPUT \
        --accelerator-topology=TPU_TOPOLOGY \
        --project=PROJECT_ID \
        --region=REGION
    

    替换以下内容:

    • WORKLOAD_POLICY_NAME:工作负载政策的名称。
    • TPU_TOPOLOGY:TPU Ironwood (TPU7x) 拓扑。 例如 2x2x2。如需查看所有受支持的 Ironwood (TPU7x) 拓扑,请参阅拓扑部分
    • PROJECT_ID:您的 Google Cloud 项目 ID。
    • REGION:工作负载政策的区域。 工作负载政策是一种区域级资源,可在共享相同拓扑的节点池中重复使用。
  2. 使用工作负载政策创建节点池:

    gcloud container node-pools create NODE_POOL_NAME \
        --cluster=CLUSTER_NAME \
        --location=us-central1 \
        --node-locations=us-central1-c \
        --machine-type=tpu7x-standard-4t \
        --reservation-affinity=none \
        --enable-autoscaling \
        --num-nodes=0 --min-nodes=0 --max-nodes=MAX_NODES \
        --flex-start \
        --placement-policy=WORKLOAD_POLICY
    

    替换以下内容:

    • NODE_POOL_NAME:新节点池的名称。
    • WORKLOAD_POLICY:您创建的工作负载政策的名称。
    • MAX_NODES:节点池的大小上限。如果提供了 --enable-autoscaling,则必须使用 --max-nodes 标志,且该标志必须等于 TPU_TOPOLOGY ({A}x{B}x{C}) 中定义的值的乘积除以每个虚拟机中的芯片数量。 例如,如果 TPU_TOPOLOGY2x2x2,则乘积为 8。由于 tpu7x-standard-4t 中的每个虚拟机都有 4 个芯片,因此节点数为 2。

    此命令会创建一个名为 NODE_POOL_NAME 的节点池,该节点池具有以下特征:

    • --machine-type=tpu7x-standard-4t 指定 Ironwood (TPU7x) 机器类型。
    • --flex-start 启用灵活启动。

Terraform

  1. 确保您使用 google 提供程序 4.84.0 版或更高版本。
  2. 创建工作负载政策:

    resource "google_compute_resource_policy" {
      name   = "WORKLOAD_POLICY_NAME"
      region = CLUSTER_LOCATION
      workload_policy {
        type = "HIGH_THROUGHPUT"
        accelerator_topology = "TPU_TOPOLOGY"
      }
    }
    

    替换以下内容:

    • WORKLOAD_POLICY_NAME:工作负载政策的名称。
    • CLUSTER_LOCATION:集群的计算位置。我们建议您使用区域级集群,以提高 Kubernetes 控制平面的可靠性。您还可以使用可用区级集群。如需了解详情,请参阅选择 TPU 版本和拓扑
    • TPU_TOPOLOGY:TPU Ironwood (TPU7x) 拓扑。 例如 2x2x2。如需查看所有受支持的 Ironwood (TPU7x) 拓扑,请参阅规划 TPU

    如需详细了解 google_compute_resource_policy 参考,请参阅 Terraform 提供程序

  3. 在 Terraform 配置中,添加以下块:

    resource "google_container_node_pool" "NODE_POOL_RESOURCE_NAME" {
      provider           = google
      project            = PROJECT_ID
      cluster            = CLUSTER_NAME
      name               = POOL_NAME
      location           = CLUSTER_LOCATION
      node_locations     = [NODE_ZONES]
      initial_node_count = NUM_NODES
    
      autoscaling {
        max_node_count = MAX_NODES
        location_policy      = "ANY"
      }
      node_config {
        machine_type = MACHINE_TYPE
        reservation_affinity {
          consume_reservation_type = "SPECIFIC_RESERVATION"
          key = "compute.googleapis.com/reservation-name"
          values = [RESERVATION_LABEL_VALUES]
        }
        flex_start = true
      }
    
      placement_policy {
        policy_name = WORKLOAD_POLICY_NAME
      }
    }
    

    替换以下内容:

    • NODE_POOL_RESOURCE_NAME:Terraform 模板中的节点池资源的名称。
    • PROJECT_ID:您的项目 ID。
    • CLUSTER_NAME:要在其中添加节点池的现有集群的名称。
    • POOL_NAME:要创建的节点池的名称。
    • NODE_ZONES:GKE 在其中创建节点池的一个或多个可用区的英文逗号分隔列表。
    • NUM_NODES:节点池中的节点数。值必须为零或 TPU 芯片数量的乘积除以 4,因为在多主机 TPU 切片中,每个 TPU 切片节点都有 4 个芯片。例如,如果 TPU_TOPOLOGY4x8,则有 32 个芯片,这意味着 NUM_NODES 必须为 8。如需详细了解 TPU 拓扑,请使用选择 TPU 版本中的表。
    • TPU_TOPOLOGY:这指示所选的 TPU 切片物理拓扑。拓扑格式取决于您使用的 TPU 版本。如需详细了解 TPU 拓扑,请使用选择拓扑中的表。

    (可选)您还可以使用以下变量:

    • RESERVATION_NAME:如果您使用 TPU 预留,请提供创建节点池时要使用的预留资源标签列表。如需详细了解如何填充 reservation_affinity 字段中的 RESERVATION_LABEL_VALUES,请参阅 Terraform 提供程序
    • autoscaling:创建启用了自动扩缩功能的节点池。当 GKE 扩缩多主机 TPU 切片节点池时,它会以原子方式将节点池从零扩容到大小上限。
      • MAX_NODES:节点池的大小上限。该值必须等于 TPU_TOPOLOGY ({A}x{B}x{C}) 中定义的值的乘积除以每个虚拟机中的芯片数量。例如,如果 TPU_TOPOLOGY2x2x2,则乘积为 8。由于 tpu7x-standard-4t 中的每个虚拟机都有 4 个芯片,因此节点数为 2。
    • spot:将对 TPU 切片节点使用 Spot 虚拟机的节点池。创建节点池后,此设置便无法更改。如需了解详情,请参阅 Spot 虚拟机
    • flex_start:将使用灵活启动使用选项的节点池。如果启用了 spot,则无法将此设置设为 true

其他 TPU 版本

您可以使用 Google Cloud CLI、Terraform 或 Google Cloud 控制台在 v3、v4、v5p、v5e 和 Trillium (v6e) 版本中创建多主机 TPU 切片节点池。

gcloud

  gcloud container node-pools create NODE_POOL_NAME \
      --cluster=CLUSTER_NAME \
      --location=CONTROL_PLANE_LOCATION \
      --node-locations=NODE_ZONES \
      --machine-type=MACHINE_TYPE \
      --tpu-topology=TPU_TOPOLOGY \
      --reservation-affinity=none \
      --enable-autoscaling \
      --num-nodes=0 --min-nodes=0 --max-nodes=MAX_NODES \
      --flex-start

替换以下内容:

  • NODE_POOL_NAME:新节点池的名称。
  • CLUSTER_NAME:集群的名称。
  • CONTROL_PLANE_LOCATION:基于您要使用的 TPU 版本的可用区名称。如需确定可用的位置,请参阅 GKE 中的 TPU 可用性
  • NODE_ZONES:GKE 在其中创建节点池的一个或多个可用区的英文逗号分隔列表。
  • MACHINE_TYPE:用于节点的机器类型。如需详细了解与 TPU 兼容的机器类型,请使用选择 TPU 版本中的表。
  • TPU_TOPOLOGY:TPU 拓扑。 例如 2x2x2。如需查看所有受支持的 TPU 拓扑,请参阅拓扑部分
  • MAX_NODES:节点池的大小上限。如果提供了 --enable-autoscaling,则必须使用 --max-nodes 标志,且该标志必须等于 TPU_TOPOLOGY ({A}x{B}x{C}) 中定义的值的乘积除以每个虚拟机中的芯片数量。

    此命令会创建一个名为 NODE_POOL_NAME 且已启用灵活启动的节点池。

Terraform

  1. 确保您使用 google 提供程序 4.84.0 版或更高版本。
  2. 将以下块添加到 Terraform 配置中:

    resource "google_container_node_pool" "NODE_POOL_RESOURCE_NAME" {
      provider           = google
      project            = PROJECT_ID
      cluster            = CLUSTER_NAME
      name               = POOL_NAME
      location           = CLUSTER_LOCATION
      node_locations     = [NODE_ZONES]
      initial_node_count = NUM_NODES
    
      autoscaling {
        max_node_count = MAX_NODES
        location_policy      = "ANY"
      }
      node_config {
        machine_type = MACHINE_TYPE
        reservation_affinity {
          consume_reservation_type = "SPECIFIC_RESERVATION"
          key = "compute.googleapis.com/reservation-name"
          values = [RESERVATION_LABEL_VALUES]
        }
        flex_start = true
      }
    
      placement_policy {
        type = "COMPACT"
        tpu_topology = TPU_TOPOLOGY
      }
    }
    

    替换以下内容:

    • NODE_POOL_RESOURCE_NAME:Terraform 模板中的节点池资源的名称。
    • PROJECT_ID:您的项目 ID。
    • CLUSTER_NAME:要在其中添加节点池的现有集群的名称。
    • POOL_NAME:要创建的节点池的名称。
    • CLUSTER_LOCATION:集群的计算位置。我们建议您使用区域级集群,以提高 Kubernetes 控制平面的可靠性。您还可以使用可用区级集群。如需了解详情,请参阅选择 TPU 版本和拓扑
    • NODE_ZONES:GKE 在其中创建节点池的一个或多个可用区的英文逗号分隔列表。
    • NUM_NODES:节点池中的节点数。值必须为零或 TPU 芯片数量的乘积除以 4,因为在多主机 TPU 切片中,每个 TPU 切片节点都有 4 个芯片。例如,如果 TPU_TOPOLOGY4x8,则有 32 个芯片,这意味着 NUM_NODES 必须为 8。如需详细了解 TPU 拓扑,请使用选择 TPU 版本中的表。
    • TPU_TOPOLOGY:这指示 TPU 切片的物理拓扑。拓扑格式取决于您使用的 TPU 版本。如需详细了解 TPU 拓扑,请使用选择拓扑中的表。

    (可选)您还可以使用以下变量:

    • RESERVATION_NAME:如果您使用 TPU 预留,则这是创建节点池时使用的预留资源的标签列表。如需详细了解如何填充 reservation_affinity 字段中的 RESERVATION_LABEL_VALUES,请参阅 Terraform 提供程序
    • autoscaling:创建启用了自动扩缩功能的节点池。当 GKE 扩缩多主机 TPU 切片节点池时,它会以原子方式将节点池从零扩容到大小上限。
      • MAX_NODES:节点池的大小上限。该值必须等于 TPU_TOPOLOGY ({A}x{B}x{C}) 中定义的值的乘积除以每个虚拟机中的芯片数量。
    • spot:可让节点池对 TPU 切片节点使用 Spot 虚拟机。创建节点池后,此设置将无法更改。如需了解详情,请参阅 Spot 虚拟机
    • flex_start:将节点池设置为使用灵活启动使用选项。如果启用了 spot,则无法将此属性设置为 true

控制台

如需创建具有 TPU 的节点池,请执行以下操作:

  1. 前往 Google Cloud 控制台中的 Google Kubernetes Engine 页面。

    转到 Google Kubernetes Engine

  2. 在集群列表中,点击您要修改的集群的名称。

  3. 点击 添加节点池

  4. 节点池详情部分中,勾选指定节点位置复选框。

  5. 选择基于您要使用的 TPU 版本的可用区名称。如需确定可用的位置,请参阅 GKE 中的 TPU 可用性

  6. 在导航窗格中,点击节点

  7. 机器配置部分中,选择 TPU

  8. 系列下拉菜单中,选择以下选项之一:

    • CT3:TPU v3,单主机设备
    • CT3P:TPU v3,多主机 Pod 切片
    • CT4P:TPU v4
    • CT5LP:TPU v5e
    • CT5P:TPU v5p
    • CT6E:TPU Trillium (v6e)
  9. 机器类型下拉菜单中,选择要用于节点的机器的名称。使用选择 TPU 版本表可了解如何定义用于创建多主机 TPU 切片节点池的机器类型和 TPU 拓扑。

  10. TPU 拓扑下拉菜单中,选择 TPU 切片的物理拓扑。

  11. 需要更改对话框中,点击进行更改

  12. 确保启动磁盘类型标准永久性磁盘SSD 永久性磁盘

  13. (可选)选中在 Spot 虚拟机上启用节点复选框,以对节点池中的节点使用 Spot 虚拟机。

  14. 点击创建

验证节点池中灵活启动的状态

运行以下命令:

gcloud container node-pools describe NODE_POOL_NAME \
    --cluster CLUSTER_NAME \
    --location CONTROL_PLANE_LOCATION \
    --format="get(config.flexStart)"

如果节点池中启用了灵活启动,则 flexStart 字段会设置为 True

运行批量工作负载

在本部分中,您将创建一个作业来调度具有灵活启动虚拟机的 TPU 节点。 Kubernetes 中的 Job 控制器会创建一个或多个 Pod,并确保它们成功执行特定任务。

  1. Google Cloud 控制台中,点击 Cloud Shell 激活图标 激活 Cloud Shell 以启动 Cloud Shell 会话。系统会在 Google Cloud 控制台的底部窗格中打开会话。

  2. 创建一个名为 dws-flex-start.yaml 的文件:

    单个主机

    针对 dws-flex-start.yaml 文件使用以下清单:

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: job-1
    spec:
      template:
        spec:
          nodeSelector:
            cloud.google.com/gke-flex-start: "true"
            cloud.google.com/gke-tpu-accelerator: ACCELERATOR_TYPE
            cloud.google.com/gke-tpu-topology: TPU_TOPOLOGY
          containers:
          - name: container-1
            image: gcr.io/k8s-staging-perf-tests/sleep:latest
            args: ["3600s"] # Sleep for 1 hour
            resources:
              requests:
                  google.com/tpu: NUM_CHIPS
              limits:
                  google.com/tpu: NUM_CHIPS
          restartPolicy: OnFailure
    

    多主机

    针对 dws-flex-start.yaml 文件使用以下清单:

    apiVersion: v1
    kind: Service
    metadata:
      name: headless-svc
    spec:
      clusterIP: None
      selector:
        job-name: job-1
    ---
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: job-1
    spec:
      backoffLimit: 0
      completions: 2
      parallelism: 2
      completionMode: Indexed
      template:
        spec:
          subdomain: headless-svc
          restartPolicy: Never
          nodeSelector:
              cloud.google.com/gke-flex-start: "true"
              cloud.google.com/gke-tpu-accelerator: ACCELERATOR_TYPE
              cloud.google.com/gke-tpu-topology: TPU_TOPOLOGY
          containers:
          - name: tpu-job
            image: us-docker.pkg.dev/cloud-tpu-images/jax-ai-image/tpu:latest
            ports:
            - containerPort: 8471 # Default port using which TPU VMs communicate
            - containerPort: 8431 # Port to export TPU runtime metrics, if supported.
            securityContext:
              privileged: true
            command:
            - bash
            - -c
            - |
              python -c 'import jax; print("TPU cores:", jax.device_count())'
            resources:
              requests:
                google.com/tpu: NUM_CHIPS
              limits:
                google.com/tpu: NUM_CHIPS
    

    替换以下内容:

    • ACCELERATOR_TYPE:创建节点池时使用的 TPU 加速器的类型。例如 tpu-v4-podslicetpu-v5-lite-podslice
    • TPU_TOPOLOGY:TPU 切片的物理拓扑。例如,该值可以是 4x4x42x2,具体取决于 TPU 版本。
    • NUM_CHIPS:每个虚拟机中的 TPU 芯片数量为 1、4 或 8。如需了解详情,请参阅 TPU 版本
  3. 应用 dws-flex-start.yaml 清单:

    kubectl apply -f dws-flex-start.yaml
    
  4. 验证作业是否在同一节点上运行:

    kubectl get pods
    

    输出类似于以下内容:

    NAME    READY   STATUS      RESTARTS   AGE   IP       NODE               NOMINATED NODE   READINESS GATES
    job-1   0/1     Completed   0          19m   10.(...) gke-flex-zonal-a2  <none>           <none>
    

清理

为避免因本页面中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留该项目但删除各个资源。

删除项目

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

逐个删除资源

  1. 删除作业:

    kubectl delete job -l "job-name in (job-1,job-2)"
    
  2. 删除节点池:

    gcloud container node-pools delete NODE_POOL_NAME \
          --location CONTROL_PLANE_LOCATION
    
  3. 删除集群:

    gcloud container clusters delete CLUSTER_NAME
    

后续步骤