利用 Hyperdisk ML 加快 AI/机器学习数据加载速度


本指南介绍了如何使用 Hyperdisk ML 简化和加速在 Google Kubernetes Engine (GKE) 上加载 AI/机器学习模型权重的操作。Compute Engine Persistent Disk CSI 驱动程序是您访问使用 GKE 集群的 Hyperdisk ML 存储的主要方式。

概览

Hyperdisk ML 是一种高性能存储解决方案,可用于扩容应用。它可为许多虚拟机同时提供高聚合吞吐量,使它非常适合您希望运行需要访问大量数据的 AI/机器学习工作负载的情况。

在只读多次模式下启用后,您可以使用 Hyperdisk ML 将模型权重的加载速度加快多达 11.9 倍(相对于直接从模型注册表加载)。这种加速是通过 Google Cloud Hyperdisk 架构实现的,该架构允许以 1.2 TB/s 的速度扩容到 2,500 个并发节点。这样,您就可以为 AI/机器学习推理工作负载缩短加载时间并减少 Pod 过度预配。

创建和使用 Hyperdisk ML 的概要步骤如下所示:

  1. 在 Persistent Disk 磁盘映像中预缓存或水合数据:使用可用于服务的外部数据源(例如从 Cloud Storage 加载的 Gemma 权重)中的数据加载 Hyperdisk ML 卷。用于磁盘映像的 Persistent Disk 必须与 Google Cloud Hyperdisk 兼容。
  2. 使用原有 Google Cloud Hyperdisk 创建 Hyperdisk ML 卷:创建一个引用随数据加载的 Hyperdisk ML 卷的 Kubernetes 卷。或者,您可以创建多可用区存储类别,以确保您的数据在 Pod 将运行的所有可用区中可用。
  3. 创建 Kubernetes Deployment 以使用 Hyperdisk ML 卷:引用 Hyperdisk ML 卷并加速数据加载,以供应用使用。

多可用区 Hyperdisk ML 卷

Hyperdisk ML 磁盘只能在单个可用区中使用。(可选)您可以使用 Hyperdisk ML 多可用区功能,在单个逻辑 PersistentVolumeClaim 和 PersistentVolume 中动态链接包含相同内容的多个可用区级磁盘。多可用区功能引用的可用区级磁盘必须位于同一区域中。例如,如果您的区域级集群在 us-central1 中创建,则多可用区磁盘必须位于同一区域(例如 us-central1-aus-central1-b)。

AI/机器学习推理的一个常见应用场景是使用 Spot 虚拟机跨可用区运行 Pod,以提高加速器可用性并提升成本效益。由于 Hyperdisk ML 是可用区级的,因此如果推理服务器跨可用区运行多个 Pod,GKE 会自动跨可用区克隆磁盘,以确保您的数据遵循您的应用。

水合来自外部数据源的 Hyperdisk ML,并创建多可用区 PV 以跨可用区访问数据。

多可用区 Hyperdisk ML 卷具有以下限制:

  • 不支持卷大小调整和卷快照操作。
  • 只有在只读模式下才支持多可用区 Hyperdisk ML 卷。
  • 将原有磁盘与多可用区 Hyperdisk ML 卷搭配使用时,GKE 不会执行检查来验证各个可用区的磁盘内容是否相同。如果任何磁盘包含不同的内容,请确保您的应用考虑了可用区之间潜在的不一致性。

如需了解详情,请参阅通过 VolumeSnapshot 创建多可用区 ReadOnlyMany Hyperdisk ML 卷

准备工作

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

  • 启用 Google Kubernetes Engine API。
  • 启用 Google Kubernetes Engine API
  • 如果您要使用 Google Cloud CLI 执行此任务,请安装初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行 gcloud components update 以获取最新版本。
  • 将您的默认区域和可用区设置为某个支持的值
  • 确保您的 Google Cloud 项目具有足够的配额,以便创建本指南中所需的节点。用于 GKE 集群和 Kubernetes 资源创建的示例代码在您选择的区域中需要以下最低配额:88 个 C3 CPU、8 个 NVIDIA L4 GPU。

要求

如需在 GKE 中使用 Hyperdisk ML 卷,您的集群必须满足以下要求:

  • 使用运行 GKE 1.30.2-gke.1394000 版或更高版本的 Linux 集群。如果您使用发布渠道,请确保该渠道具有此驱动程序所需的最低 GKE 版本或更高版本。
  • 确保已启用 Compute Engine Persistent Disk CSI 驱动程序。默认情况下,Compute Engine Persistent Disk 驱动程序会在新的 Autopilot 和 Standard 集群中启用,并且在使用 Autopilot 时无法停用或修改。如果您需要在集群中启用 Compute Engine Persistent Disk CSI 驱动程序,请参阅在现有集群上启用 Compute Engine Persistent Disk CSI 驱动程序
  • 如果您要对 readahead 值进行调优,请使用 GKE 1.29.2-gke.1217000 版或更高版本。
  • 如果您要使用多可用区动态预配功能,请使用 GKE 1.30.2-gke.1394000 版或更高版本。
  • Hyperdisk ML 仅在特定节点类型和可用区中受支持。如需了解详情,请参阅 Compute Engine 文档中的 Google Cloud Hyperdisk 简介

获取对模型的访问权限

如需获取对 Gemma 模型的访问权限以便部署到 GKE,您必须先签署许可同意协议,然后生成 Huggging Face 访问令牌。

您必须签署同意协议才能使用 Gemma。请按照以下说明操作:

  1. 访问 Kaggle.com 上的模型同意页面
  2. 使用您的 Hugging Face 账号验证同意情况。
  3. 接受模型条款。

生成一个访问令牌

如需通过 Hugging Face 访问模型,您需要 Hugging Face 令牌

如果您还没有令牌,请按照以下步骤生成新令牌:

  1. 点击您的个人资料 > 设置 > 访问令牌
  2. 选择新建令牌 (New Token)。
  3. 指定您选择的名称和一个至少为 Read 的角色。
  4. 选择生成令牌
  5. 将生成的令牌复制到剪贴板。

创建 GKE 集群

您可以在 GKE Autopilot 或 Standard 集群中的 GPU 上应用 LLM。我们建议您使用 Autopilot 集群获得全托管式 Kubernetes 体验。如需选择最适合您的工作负载的 GKE 操作模式,请参阅选择 GKE 操作模式

Autopilot

  1. 在 Cloud Shell 中,运行以下命令:

    gcloud container clusters create-auto hdml-gpu-l4 \
      --project=PROJECT \
      --region=REGION \
      --release-channel=rapid \
      --cluster-version=1.30.2-gke.1394000
    

    替换以下值:

    • PROJECT:Google Cloud 项目 ID。
    • REGION:支持要使用的加速器类型的区域,例如适用于 L4 GPU 的 us-east4

    GKE 会根据所部署的工作负载的请求,创建具有所需 CPU 和 GPU 节点的 Autopilot 集群。

  2. 配置 kubectl 以与您的集群通信:

    gcloud container clusters get-credentials hdml-gpu-l4 \
      --region=REGION
    

Standard

  1. 在 Cloud Shell 中,运行以下命令以创建 Standard 集群和节点池:

    gcloud container clusters create hdml-gpu-l4 \
        --location=REGION \
        --num-nodes=1 \
        --machine-type=c3-standard-44 \
        --release-channel=rapid \
        --cluster-version=CLUSTER_VERSION \
        --node-locations=ZONES \
        --project=PROJECT
    
    gcloud container node-pools create gpupool \
        --accelerator type=nvidia-l4,count=2,gpu-driver-version=latest \
        --location=REGION \
        --project=PROJECT \
        --node-locations=ZONES \
        --cluster=hdml-gpu-l4 \
        --machine-type=g2-standard-24 \
        --num-nodes=2
    

    替换以下值:

    • CLUSTER_VERSION:GKE 集群的版本(例如 1.30.2-gke.1394000)。
    • REGION:集群控制层面的计算区域。 该区域必须支持您要使用的加速器,例如适用于 L4 GPU 的 us-east4。查看 L4 GPU 在哪些区域中可用。
    • ZONES:在其中创建节点的可用区。您可以根据集群的需要指定任意数量的可用区。所有可用区必须与集群的控制平面位于同一区域,由 --zone 标志指定。对于可用区级集群,--node-locations 必须包含集群的主要可用区。
    • PROJECT:Google Cloud 项目 ID。

    集群创建可能需要几分钟的时间。

  2. 配置 kubectl 以与您的集群通信:

    gcloud container clusters get-credentials hdml-gpu-l4
    

将数据预缓存到 Persistent Disk 磁盘映像

如需使用 Hyperdisk ML,您可以在磁盘映像中预缓存数据,并创建 Hyperdisk ML 卷以供 GKE 中的工作负载进行读取访问。此方法(也称为数据水合)可确保数据在工作负载需要时可供使用。

如需将数据从 Cloud Storage 复制到预缓存 Persistent Disk 磁盘映像,请按以下步骤操作:

创建支持 Hyperdisk ML 的 StorageClass

  1. 将以下 StorageClass 清单保存在名为 hyperdisk-ml.yaml 的文件中。

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
        name: hyperdisk-ml
    parameters:
        type: hyperdisk-ml
    provisioner: pd.csi.storage.gke.io
    allowVolumeExpansion: false
    reclaimPolicy: Delete
    volumeBindingMode: WaitForFirstConsumer
    
  2. 运行以下命令以创建 StorageClass:

    kubectl create -f hyperdisk-ml.yaml
    

创建 ReadWriteOnce (RWO) PersistentVolumeClaim

  1. 将以下 PersistentVolumeClaim 清单保存在名为 producer-pvc.yaml 的文件中。您将使用之前创建的 StorageClass。请确保您的磁盘有足够的容量来存储数据。

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: producer-pvc
    spec:
      storageClassName: hyperdisk-ml
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 300Gi
    
  2. 运行以下命令以创建 PersistentVolumeClaim:

    kubectl create -f producer-pvc.yaml
    

创建 Kubernetes 作业以填充已装载的 Google Cloud Hyperdisk 卷

本部分展示了一个创建 Kubernetes 作业的示例,该作业会预配磁盘并将 Gemma 7B 指令调优模型从 Hugging Face 下载到已装载的 Google Cloud Hyperdisk 卷上。

  1. 如需访问本指南中示例使用的 Gemma LLM,请创建包含 Hugging Face 令牌的 Kubernetes Secret:

    kubectl create secret generic hf-secret \
        --from-literal=hf_api_token=HF_TOKEN\
        --dry-run=client -o yaml | kubectl apply -f -
    

    HF_TOKEN 替换为您之前生成的 Hugging Face 令牌。

  2. 将以下示例清单保存为 producer-job.yaml

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: producer-job
    spec:
      template:  # Template for the Pods the Job will create
        spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: cloud.google.com/compute-class
                    operator: In
                    values:
                    - "Performance"
                - matchExpressions:
                  - key: cloud.google.com/machine-family
                    operator: In
                    values:
                    - "c3"
                - matchExpressions:
                  - key: topology.kubernetes.io/zone
                    operator: In
                    values:
                    - "ZONE"
          containers:
          - name: copy
            resources:
              requests:
                cpu: "32"
              limits:
                cpu: "32"
            image: huggingface/downloader:0.17.3
            command: [ "huggingface-cli" ]
            args:
            - download
            - google/gemma-1.1-7b-it
            - --local-dir=/data/gemma-7b
            - --local-dir-use-symlinks=False
            env:
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
            volumeMounts:
              - mountPath: "/data"
                name: volume
          restartPolicy: Never
          volumes:
            - name: volume
              persistentVolumeClaim:
                claimName: producer-pvc
      parallelism: 1         # Run 1 Pods concurrently
      completions: 1         # Once 1 Pods complete successfully, the Job is done
      backoffLimit: 4        # Max retries on failure
    

    ZONE 替换为要在其中创建 Hyperdisk 的计算可用区。如果您要将其与 Deployment 示例搭配使用,请确保它是具有 G2 机器容量的可用区。

  3. 运行以下命令以创建作业:

    kubectl apply -f producer-job.yaml
    

    作业可能需要几分钟时间才能完成将数据复制到 Persistent Disk 卷的过程。作业完成预配后,其状态会被标记为“完成”。

  4. 如需检查作业状态的进度,请运行以下命令:

    kubectl get job producer-job
    
  5. 作业完成后,您可以运行以下命令来清理作业:

    kubectl delete job producer-job
    

通过原有 Google Cloud Hyperdisk 创建 ReadOnlyMany Hyperdisk ML 卷

本部分介绍了通过原有 Google Cloud Hyperdisk 卷创建 ReadOnlyMany (ROM) PersistentVolume 和 PersistentVolumeClaim 对的步骤。如需了解详情,请参阅将原有永久性磁盘用作 PersistentVolume

  1. 在 GKE 1.30.2-gke.1394000 版及更高版本中,GKE 会自动将 READ_WRITE_SINGLE Google Cloud Hyperdisk 卷的访问模式转换为 READ_ONLY_MANY

    如果您在较低版本的 GKE 上使用原有 Google Cloud Hyperdisk 卷,则必须通过运行以下命令手动修改访问模式:

    gcloud compute disks update HDML_DISK_NAME \
        --zone=ZONE \
        --access-mode=READ_ONLY_MANY
    

    替换以下值:

    • HDML_DISK_NAME:Hyperdisk ML 卷的名称。
    • ZONE:在其中创建原有 Google Cloud Hyperdisk 卷的计算可用区
  2. 创建 PersistentVolume 和 PersistentVolumeClaim 对(引用您之前填充的磁盘)。

    1. 将以下清单保存为 hdml-static-pv.yaml

      apiVersion: v1
      kind: PersistentVolume
      metadata:
        name: hdml-static-pv
      spec:
        storageClassName: "hyperdisk-ml"
        capacity:
          storage: 300Gi
        accessModes:
          - ReadOnlyMany
        claimRef:
          namespace: default
          name: hdml-static-pvc
        csi:
          driver: pd.csi.storage.gke.io
          volumeHandle: projects/PROJECT/zones/ZONE/disks/DISK_NAME
          fsType: ext4
          readOnly: true
        nodeAffinity:
          required:
            nodeSelectorTerms:
            - matchExpressions:
              - key: topology.gke.io/zone
                operator: In
                values:
                - ZONE
      ---
      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        namespace: default
        name: hdml-static-pvc
      spec:
        storageClassName: "hyperdisk-ml"
        volumeName: hdml-static-pv
        accessModes:
        - ReadOnlyMany
        resources:
          requests:
            storage: 300Gi
      

      替换以下值:

      • PROJECT:在其中创建 GKE 集群的项目。
      • ZONE:在其中创建原有 Google Cloud Hyperdisk 卷的可用区。
      • DISK_NAME:原有 Google Cloud Hyperdisk 卷的名称。
    2. 运行以下命令以创建 PersistentVolume 和 PersistentVolumeClaim 资源:

      kubectl apply -f hdml-static-pv.yaml
      

通过 VolumeSnapshot 创建多可用区 ReadOnlyMany Hyperdisk ML 卷

本部分介绍了在 ReadOnlyMany 访问模式下创建多可用区 Hyperdisk ML 卷的步骤。您可以为原有 Persistent Disk 磁盘映像使用 VolumeSnapshot。如需了解详情,请参阅使用卷快照备份 Persistent Disk 存储空间

如需创建多可用区 Hyperdisk ML 卷,请按照以下步骤操作:

创建磁盘的 VolumeSnapshot

  1. 将以下清单保存为名为 disk-image-vsc.yaml 的文件。

    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshotClass
    metadata:
      name: disk-image-vsc
    driver: pd.csi.storage.gke.io
    deletionPolicy: Delete
    parameters:
      snapshot-type: images
    
  2. 运行以下命令以创建 VolumeSnapshotClass:

    kubectl apply -f disk-image-vsc.yaml
    
  3. 将以下清单保存为名为 my-snapshot.yaml 的文件。您将引用之前在创建 ReadWriteOnce (RWO) PersistentVolumeClaim 中创建的 PersistentVolumeClaim。

    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
      name: my-snapshot
    spec:
      volumeSnapshotClassName: disk-image-vsc
      source:
        persistentVolumeClaimName: producer-pvc
    
  4. 运行以下命令以创建 VolumeSnapshot:

    kubectl apply -f my-snapshot.yaml
    
  5. 当 VolumeSnapshot 被标记为“准备就绪”时,请运行以下命令以创建 Hyperdisk ML 卷:

    kubectl wait --for=jsonpath='{.status.readyToUse}'=true \
        --timeout=300s volumesnapshot my-snapshot
    

创建多可用区 StorageClass

如果您希望能够在多个可用区中访问数据的副本,请在 StorageClass 中指定 enable-multi-zone-provisioning 参数,该参数会在您在 allowedTopologies 字段中指定的可用区中创建磁盘。

如需创建 StorageClass,请按以下步骤操作:

  1. 将以下清单保存为名为 hyperdisk-ml-multi-zone.yaml 的文件。

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: hyperdisk-ml-multi-zone
    parameters:
      type: hyperdisk-ml
      provisioned-throughput-on-create: "2400Mi"
      enable-multi-zone-provisioning: "true"
    provisioner: pd.csi.storage.gke.io
    allowVolumeExpansion: false
    reclaimPolicy: Delete
    volumeBindingMode: Immediate
    allowedTopologies:
    - matchLabelExpressions:
      - key: topology.gke.io/zone
        values:
        - ZONE_1
        - ZONE_2
    

    ZONE_1ZONE_2、...、ZONE_N 替换为可访问您的存储空间的可用区。

    此示例将 volumeBindingMode 设置为 Immediate,以允许 GKE 在任何使用方进行引用之前预配 PersistentVolumeClaim。

  2. 运行以下命令以创建 StorageClass:

    kubectl apply -f hyperdisk-ml-multi-zone.yaml
    

创建使用多可用区 StorageClass 的 PersistentVolumeClaim

下一步是创建一个引用 StorageClass 的 PersistentVolumeClaim。

GKE 会使用指定的磁盘映像内容,在快照中指定的每个可用区中自动预配 Hyperdisk ML 卷。

如需创建 PersistentVolumeClaim,请按以下步骤操作:

  1. 将以下清单保存为名为 hdml-consumer-pvc.yaml 的文件。

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: hdml-consumer-pvc
    spec:
      dataSource:
        name: my-snapshot
        kind: VolumeSnapshot
        apiGroup: snapshot.storage.k8s.io
      accessModes:
      - ReadOnlyMany
      storageClassName: hyperdisk-ml-multi-zone
      resources:
        requests:
          storage: 300Gi
    
  2. 运行以下命令以创建 PersistentVolumeClaim:

    kubectl apply -f hdml-consumer-pvc.yaml
    

创建 Deployment 以使用 Hyperdisk ML 卷

将 Pod 与 PersistentVolume 搭配使用时,我们建议您使用工作负载控制器(例如 DeploymentStatefulSet)。

如果要将处于 ReadOnlyMany 模式的原有 PersistentVolume 与 Deployment 搭配使用,请参阅将永久性磁盘与多个读取方配合使用

如需创建和测试 Deployment,请按以下步骤操作:

  1. 将以下示例清单保存为 vllm-gemma-deployment

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-gemma-deployment
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: gemma-server
      template:
        metadata:
          labels:
            app: gemma-server
            ai.gke.io/model: gemma-7b
            ai.gke.io/inference-server: vllm
        spec:
          affinity:
            podAntiAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
              - weight: 100
                podAffinityTerm:
                  labelSelector:
                    matchExpressions:
                    - key: security
                      operator: In
                      values:
                      - S2
                  topologyKey: topology.kubernetes.io/zone
          containers:
          - name: inference-server
            image: us-docker.pkg.dev/vertex-ai/vertex-vision-model-garden-dockers/pytorch-vllm-serve:latest
            resources:
              requests:
                cpu: "2"
                memory: "25Gi"
                ephemeral-storage: "25Gi"
                nvidia.com/gpu: 2
              limits:
                cpu: "2"
                memory: "25Gi"
                ephemeral-storage: "25Gi"
                nvidia.com/gpu: 2
            command: ["python3", "-m", "vllm.entrypoints.api_server"]
            args:
            - --model=$(MODEL_ID)
            - --tensor-parallel-size=2
            env:
            - name: MODEL_ID
              value: /models/gemma-7b
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
            - mountPath: /models
              name: gemma-7b
          volumes:
          - name: dshm
            emptyDir:
                medium: Memory
          - name: gemma-7b
            persistentVolumeClaim:
              claimName: CLAIM_NAME
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-l4
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: llm-service
    spec:
      selector:
        app: gemma-server
      type: ClusterIP
      ports:
        - protocol: TCP
          port: 8000
          targetPort: 8000
    

    CLAIM_NAME 替换为以下某个值:

    • hdml-static-pvc:如果您使用现有 Google Cloud Hyperdisk 中的 Hyperdisk ML 卷。
    • hdml-consumer-pvc:如果您使用 VolumeSnapshot 磁盘映像中的 Hyperdisk ML 卷。
  2. 运行以下命令,等待推理服务器可用:

    kubectl wait --for=condition=Available --timeout=700s deployment/vllm-gemma-deployment
    
  3. 如需测试 vLLM 服务器是否已启动且正在运行,请按以下步骤操作:

    1. 运行以下命令以设置到模型的端口转发:

      kubectl port-forward service/llm-service 8000:8000
      
    2. 运行 curl 命令以向模型发送请求:

      USER_PROMPT="I'm new to coding. If you could only recommend one programming language to start with, what would it be and why?"
      
      curl -X POST http://localhost:8000/generate \
      -H "Content-Type: application/json" \
      -d @- <<EOF
      {
          "prompt": "<start_of_turn>user\n${USER_PROMPT}<end_of_turn>\n",
          "temperature": 0.90,
          "top_p": 1.0,
          "max_tokens": 128
      }
      EOF
      

    以下输出显示了模型响应的示例:

    {"predictions":["Prompt:\n<start_of_turn>user\nI'm new to coding. If you could only recommend one programming language to start with, what would it be and why?<end_of_turn>\nOutput:\nPython is often recommended for beginners due to its clear, readable syntax, simple data types, and extensive libraries.\n\n**Reasons why Python is a great language for beginners:**\n\n* **Easy to read:** Python's syntax is straightforward and uses natural language conventions, making it easier for beginners to understand the code.\n* **Simple data types:** Python has basic data types like integers, strings, and lists that are easy to grasp and manipulate.\n* **Extensive libraries:** Python has a vast collection of well-documented libraries covering various tasks, allowing beginners to build projects without reinventing the wheel.\n* **Large supportive community:**"]}
    

对 readahead 值进行调优

如果您的工作负载执行顺序 I/O,则对 readahead 值进行调优可能会有益于这些工作负载。这通常适用于需要将 AI/机器学习模型权重加载到内存中的推理或训练工作负载。大多数具有顺序 I/O 的工作负载通常会在 readahead 值为 1024 KB 或更高时获得性能提升。

在静态预配新的 PersistentVolume 或修改现有动态预配的 PersistentVolume 时,您可以通过 read_ahead_kb 装载选项指定此选项。

以下示例展示了如何将 readahead 值调优为 4096 KB。

apiVersion: v1
kind: PersistentVolume
  name: DISK_NAME
spec:
  accessModes:
  - ReadOnlyMany
  capacity:
    storage: 300Gi
  csi:
    driver: pd.csi.storage.gke.io
    fsType: ext4
    readOnly: true
    volumeHandle: projects/PROJECT/zones/ZONE/disks/DISK_NAME
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.gke.io/zone
          operator: In
          values:
          - ZONE
  storageClassName: hyperdisk-ml
  mountOptions:
  - read_ahead_kb=4096

替换以下值:

  • DISK_NAME:原有 Google Cloud Hyperdisk 卷的名称。
  • ZONE:在其中创建原有 Google Cloud Hyperdisk 卷的可用区。

对 Hyperdisk ML 卷性能进行测试和基准测试

本部分介绍了如何使用灵活的 I/O 测试工具 (FIO) 对 Hyperdisk ML 卷在读取原有数据方面的性能进行基准测试。您可以使用这些指标针对特定工作负载和配置来评估卷的性能。

  1. 将以下示例清单保存为 benchmark-job.yaml

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: benchmark-job
    spec:
      template:  # Template for the Pods the Job will create
        spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: cloud.google.com/compute-class
                    operator: In
                    values:
                    - "Performance"
                - matchExpressions:
                  - key: cloud.google.com/machine-family
                    operator: In
                    values:
                    - "c3"
    
          containers:
          - name: fio
            resources:
              requests:
                cpu: "32"
            image: litmuschaos/fio
            args:
            - fio
            - --filename
            - /models/gemma-7b/model-00001-of-00004.safetensors:/models/gemma-7b/model-00002-of-00004.safetensors:/models/gemma-7b/model-00003-of-00004.safetensors:/models/gemma-7b/model-00004-of-00004.safetensors:/models/gemma-7b/model-00004-of-00004.safetensors
            - --direct=1
            - --rw=read
            - --readonly
            - --bs=4096k
            - --ioengine=libaio
            - --iodepth=8
            - --runtime=60
            - --numjobs=1
            - --name=read_benchmark
            volumeMounts:
            - mountPath: "/models"
              name: volume
          restartPolicy: Never
          volumes:
          - name: volume
            persistentVolumeClaim:
              claimName: hdml-static-pvc
      parallelism: 1         # Run 1 Pods concurrently
      completions: 1         # Once 1 Pods complete successfully, the Job is done
      backoffLimit: 1        # Max retries on failure
    

    CLAIM_NAME 替换为您的 PersistentVolumeClaim 的名称(例如 hdml-static-pvc)。

  2. 运行以下命令以创建作业:

    kubectl apply -f benchmark-job.yaml.
    
  3. 使用 kubectl 日志查看 fio 工具的输出:

    kubectl logs benchmark-job-nrk88 -f
    

    输出类似于以下内容:

    read_benchmark: (g=0): rw=read, bs=4M-4M/4M-4M/4M-4M, ioengine=libaio, iodepth=8
    fio-2.2.10
    Starting 1 process
    
    read_benchmark: (groupid=0, jobs=1): err= 0: pid=32: Fri Jul 12 21:29:32 2024
    read : io=18300MB, bw=2407.3MB/s, iops=601, runt=  7602msec
        slat (usec): min=86, max=1614, avg=111.17, stdev=64.46
        clat (msec): min=2, max=33, avg=13.17, stdev= 1.08
        lat (msec): min=2, max=33, avg=13.28, stdev= 1.06
        clat percentiles (usec):
        |  1.00th=[11072],  5.00th=[12352], 10.00th=[12608], 20.00th=[12736],
        | 30.00th=[12992], 40.00th=[13120], 50.00th=[13248], 60.00th=[13376],
        | 70.00th=[13504], 80.00th=[13632], 90.00th=[13888], 95.00th=[14016],
        | 99.00th=[14400], 99.50th=[15296], 99.90th=[22144], 99.95th=[25728],
        | 99.99th=[33024]
        bw (MB  /s): min= 2395, max= 2514, per=100.00%, avg=2409.79, stdev=29.34
        lat (msec) : 4=0.39%, 10=0.31%, 20=99.15%, 50=0.15%
    cpu          : usr=0.28%, sys=8.08%, ctx=4555, majf=0, minf=8203
    IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=99.8%, 16=0.0%, 32=0.0%, >=64=0.0%
        submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
        complete  : 0=0.0%, 4=100.0%, 8=0.1%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
        issued    : total=r=4575/w=0/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
        latency   : target=0, window=0, percentile=100.00%, depth=8
    
    Run status group 0 (all jobs):
    READ: io=18300MB, aggrb=2407.3MB/s, minb=2407.3MB/s, maxb=2407.3MB/s, mint=7602msec, maxt=7602msec
    
    Disk stats (read/write):
    nvme0n2: ios=71239/0, merge=0/0, ticks=868737/0, in_queue=868737, util=98.72%
    

监控 Hyperdisk ML 卷上的吞吐量或 IOPS

如需监控 Hyperdisk ML 卷的预配性能,请参阅 Compute Engine 文档中的分析预配的 IOPS 和吞吐量

如需更新现有 Hyperdisk ML 卷的预配吞吐量或 IOPS,或者了解您可以在 StorageClass 中指定的其他 Google Cloud Hyperdisk 参数,请参阅使用 Google Cloud Hyperdisk 扩缩存储性能

问题排查

本部分提供了解决 GKE 上的 Hyperdisk ML 卷问题的问题排查指南。

无法更新磁盘访问模式

如果 Hyperdisk ML 卷已由处于 ReadWriteOnce 访问模式的节点使用和挂接,则会出现以下错误。

AttachVolume.Attach failed for volume ... Failed to update access mode:
failed to set access mode for zonal volume ...
'Access mode cannot be updated when the disk is attached to instance(s).'., invalidResourceUsage

当 ReadOnlyMany 访问模式 PersistentVolume 使用 Hyperdisk ML 卷时,GKE 会自动将卷的 accessMode 从 READ_WRITE_SINGLE 更新为 READ_ONLY_MANY。此更新在磁盘挂接到新节点时完成。

如需解决此问题,请删除使用处于 ReadWriteOnce 模式的 PersistentVolume 引用磁盘的所有 Pod。等待磁盘分离,然后重新创建使用处于 ReadOnlyMany 模式的 PersistentVolume 的工作负载。

无法以 READ_WRITE 模式挂接磁盘

以下错误表示 GKE 尝试将处于 READ_ONLY_MANY 访问模式的 Hyperdisk ML 卷挂接到使用 ReadWriteOnce 访问模式的 GKE 节点。

AttachVolume.Attach failed for volume ...
Failed to Attach: failed cloud service attach disk call ...
The disk cannot be attached with READ_WRITE mode., badRequest

当 ReadOnlyMany 访问模式 PersistentVolume 使用 Hyperdisk ML 卷时,GKE 会自动将卷的 accessMode 从 READ_WRITE_SINGLE 更新为 READ_ONLY_MANY。不过,GKE 不会自动将访问模式从 READ_ONLY_MANY 更新为 READ_WRITE_SINGLE。这是一种安全机制,可确保不会意外写入多可用区磁盘,因为这可能会导致多可用区磁盘之间的内容不同。

如需解决此问题,如果您需要更新内容,我们建议您按照将数据预缓存到 Persistent Disk 磁盘映像工作流进行操作。如果您需要更好地控制 Hyperdisk ML 卷的访问模式和其他设置,请参阅修改 Google Cloud Hyperdisk 卷的设置

已超出配额 - 吞吐量配额不足

以下错误表明预配磁盘时 Hyperdisk ML 吞吐量配额不足。

failed to provision volume with StorageClass ... failed (QUOTA_EXCEEDED): Quota 'HDML_TOTAL_THROUGHPUT' exceeded

如需解决此问题,请参阅磁盘配额,详细了解 Hyperdisk 配额以及如何在项目中增加磁盘配额。

如需更多问题排查指南,请参阅使用 Google Cloud Hyperdisk 扩缩存储性能

后续步骤