Hyperdisk ML で AI / ML データの読み込みを高速化する


このガイドでは、Hyperdisk ML を使用して Google Kubernetes Engine(GKE)で AI/ML モデルの重みを簡単に読み込み、高速化する方法について説明します。Compute Engine Persistent Disk CSI ドライバは、GKE クラスタの Hyperdisk ML ストレージにアクセスする基本的な方法です。

概要

Hyperdisk ML は、アプリケーションのスケールアウトに使用できる高パフォーマンスのストレージ ソリューションです。多くの仮想マシンに同時に高い総スループットを提供するため、大量のデータにアクセスする必要がある AI/ML ワークロードを実行する場合に最適です。

読み取り専用マルチモードで有効にすると、Hyperdisk ML を使用して、モデル レジストリから直接読み込む場合と比較して、モデル重みの読み込みを最大 11.9 倍高速化できます。この高速化は、Google Cloud Hyperdisk アーキテクチャによって実現されています。このアーキテクチャでは、1.2 TB/秒で 2,500 個の同時実行ノードにスケーリングできます。これにより、読み込み時間が短縮され、AI/ML 推論ワークロードの 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. Hyperdisk ML ボリュームを使用する Kubernetes Deployment を作成する: アプリケーションが使用できるように、高速化されたデータ読み込みで Hyperdisk ML ボリュームを参照します。

マルチゾーン Hyperdisk ML ボリューム

Hyperdisk ML ディスクは単一ゾーンでのみ使用できます。必要に応じて、Hyperdisk ML のマルチゾーン機能を使用して、同じコンテンツを含む複数のゾーンディスクを単一の論理 PersistentVolumeClaim と PersistentVolume に動的にリンクできます。マルチゾーン機能で参照されるゾーンディスクは、同じリージョンに配置する必要があります。たとえば、リージョン クラスタが us-central1 に作成されている場合、マルチゾーン ディスクは同じリージョン(us-central1-aus-central1-b など)に配置する必要があります。

AI/ML 推論の一般的なユースケースは、Spot VM を使用してアクセラレータの可用性と費用対効果を高めるために、ゾーン間で 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 ドライバを有効にするをご覧ください。
  • リードアヘッド値を調整する場合は、GKE バージョン 1.29.2-gke.1217000 以降を使用します。
  • マルチゾーン動的プロビジョニング機能を使用する場合は、GKE バージョン 1.30.2-gke.1394000 以降を使用します。
  • Hyperdisk ML は、特定のノードタイプとゾーンでのみサポートされます。詳細については、Compute Engine ドキュメントの Google Cloud Hyperdisk についてをご覧ください。

モデルへのアクセス権を取得する

GKE にデプロイするために Gemma モデルへのアクセス権を取得するには、まずライセンス同意契約に署名してから、Hugging Face のアクセス トークンを生成する必要があります。

Gemma を使用するには同意契約に署名する必要があります。手順は次のとおりです。

  1. Kaggle.com のモデルの同意ページにアクセスします。
  2. Hugging Face アカウントを使用して同意を確認します。
  3. モデルの規約に同意します。

アクセス トークンを生成する

Hugging Face からモデルにアクセスするには、Hugging Face トークンが必要です。

トークンをまだ生成していない場合は、次の手順に沿って生成します。

  1. [Your Profile] > [Settings] > [Access Tokens] の順にクリックします。
  2. [New Token] を選択します。
  3. 任意の名前と、少なくとも Read ロールを指定します。
  4. [Generate a token] を選択します。
  5. トークンをクリップボードにコピーします。

GKE クラスタを作成する

GKE Autopilot クラスタまたは GKE Standard クラスタの GPU で LLM を提供できます。フルマネージドの Kubernetes エクスペリエンスを実現するには、Autopilot クラスタを使用することをおすすめします。ワークロードに最適な 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
    

スタンダード

  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 を使用するには、ディスク イメージにデータを事前にキャッシュに保存し、GKE 内のワークロードによる読み取りアクセス用に Hyperdisk ML ボリュームを作成します。このアプローチ(データ ハイドレーションとも呼ばれます)により、ワークロードで必要なときにデータを使用できます。

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
    

マウントされた Google Cloud Hyperdisk ボリュームにデータを入力する Kubernetes Job を作成する

このセクションでは、ディスクをプロビジョニングし、Gemma 7B 指示用調整モデルを Hugging Face からマウントされた Google Cloud Hyperdisk ボリュームにダウンロードする Kubernetes Job を作成する例を示します。

  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. 次のコマンドを実行して Job を作成します。

    kubectl apply -f producer-job.yaml
    

    Job が Persistent Disk ボリュームへのデータのコピーを完了するまでに数分かかることがあります。ジョブのプロビジョニングが完了すると、ステータスは [完了] になります。

  4. Job のステータスの進行状況を確認するには、次のコマンドを実行します。

    kubectl get job producer-job
    
  5. Job が完了したら、次のコマンドを実行して Job をクリーンアップできます。

    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
    

    次の値を置き換えます。

  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 ボリュームを作成する手順について説明します。VolumeSnapshot は、既存の Persistent Disk ディスクイメージに使用します。詳細については、ボリューム スナップショットを使用して 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 が「Ready」とマークされたら、次のコマンドを実行して 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 を参照するコンシューマの前に 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 ボリュームを使用する

PersistentVolume で Pod を使用する場合は、ワークロード コントローラ(DeploymentStatefulSet など)を使用することをおすすめします。

Deployment で ReadOnlyMany モードの既存の PersistentVolume を使用する場合は、複数のリーダーで永続ディスクを使用するをご覧ください。

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:**"]}
    

先読み量を調整する

順序付き I/O を実行するワークロードがある場合は、先読み値を調整すると効果的です。これは通常、AI/ML モデルの重みをメモリに読み込む必要がある推論ワークロードまたはトレーニング ワークロードに適用されます。通常、シーケンシャル I/O を使用するほとんどのワークロードでは、1,024 KB 以上のリードアヘッド値でパフォーマンスが向上します。

このオプションは、新しい PersistentVolume を静的にプロビジョニングする場合、または動的にプロビジョニングされた既存の PersistentVolume を変更する場合に、read_ahead_kb マウント オプションで指定できます。

次の例は、先読み値を 4,096 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 ボリュームのパフォーマンスをテストしてベンチマークする

このセクションでは、Flexible I/O Tester(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. 次のコマンドを実行して Job を作成します。

    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

GKE は、ReadOnlyMany アクセスモードの PersistentVolume で使用されている場合、Hyperdisk ML ボリュームの accessMode を READ_WRITE_SINGLE から READ_ONLY_MANY に自動的に更新します。この更新は、ディスクが新しいノードに接続されたときに行われます。

この問題を解決するには、ReadWriteOnce モードの PersistentVolume を使用してディスクを参照しているすべての Pod を削除します。ディスクが切断されるのを待ってから、ReadOnlyMany モードで PersistentVolume を使用するワークロードを再作成します。

ディスクを READ_WRITE モードでアタッチできない

次のエラーは、GKE が ReadWriteOnce アクセス モードを使用して、READ_ONLY_MANY アクセス モードの Hyperdisk ML ボリュームを 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

GKE は、ReadOnlyMany アクセスモードの PersistentVolume で使用されている場合、Hyperdisk ML ボリュームの accessMode を READ_WRITE_SINGLE から READ_ONLY_MANY に自動的に更新します。ただし、GKE はアクセスモードを READ_ONLY_MANY から READ_WRITE_SINGLE に自動的に更新しません。これは、マルチゾーン ディスク間でコンテンツが分散する可能性があるため、マルチゾーン ディスクに誤って書き込まれないようにするための安全メカニズムです。

この問題を解決するには、更新されたコンテンツが必要な場合は、永続ディスク ディスク イメージにデータを事前キャッシュに保存するワークフローに沿って操作することをおすすめします。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 でストレージ パフォーマンスをスケールするをご覧ください。

次のステップ