Accélération du chargement des données d'IA/ML avec Hyperdisk ML


Ce guide explique comment simplifier et accélérer le chargement des pondérations de modèles d'IA/ML sur Google Kubernetes Engine (GKE) à l'aide d'Hyperdisk ML. Le pilote CSI Persistent Disk Compute Engine est le principal moyen d'accéder au stockage Hyperdisk ML avec les clusters GKE.

Présentation

Hyperdisk ML est une solution de stockage hautes performances qui peut être utilisée pour effectuer un scaling horizontal de vos applications. Il fournit un débit agrégé élevé à de nombreuses machines virtuelles simultanément, ce qui le rend idéal si vous souhaitez exécuter des charges de travail d'IA/ML qui nécessitent un accès à de grandes quantités de données.

Lorsque vous l'activez en mode lecture seule, vous pouvez utiliser Hyperdisk ML pour accélérer le chargement des pondérations de modèle jusqu'à 11,9 fois par rapport au chargement directement à partir d'un registre de modèles. Cette accélération est rendue possible par l'architecture de Google Cloud Hyperdisk, qui permet de passer à 2 500 nœuds simultanés à 1,2 To/s. Cela vous permet d'améliorer les temps de chargement et de réduire le surprovisionnement des pods pour vos charges de travail d'inférence d'IA/ML.

Voici les principales étapes à suivre pour créer et utiliser des disques Hyperdisk ML :

  1. Mise en cache préalable ou hydratation des données dans une image de disque Persistent Disk : chargez des volumes Hyperdisk ML avec des données provenant d'une source de données externe (par exemple, des pondérations Gemma chargées à partir de Cloud Storage) qui peuvent être utilisés pour l'inférence. Le disque Persistent Disk de l'image disque doit être compatible avec Google Cloud Hyperdisk.
  2. Créer un volume Hyperdisk ML à l'aide d'un disque Google Cloud Hyperdisk préexistant : créez un volume Kubernetes qui fait référence au volume Hyperdisk ML chargé de données. Si vous le souhaitez, vous pouvez créer des classes de stockage multizones pour vous assurer que vos données sont disponibles dans toutes les zones dans lesquelles vos pods s'exécuteront.
  3. Créez un déploiement Kubernetes pour consommer le volume Hyperdisk ML : référencez le volume Hyperdisk ML avec un chargement de données accéléré pour que vos applications puissent le consommer.

Volumes Hyperdisk ML multizones

Les disques Hyperdisk ML ne sont disponibles que dans une seule zone. Vous pouvez également utiliser la fonctionnalité multizone Hyperdisk ML pour associer dynamiquement plusieurs disques zonaux contenant le même contenu dans un PersistentVolumeClaim et un PersistentVolume uniques logiques. Les disques zonaux référencés par la fonctionnalité multizone doivent être situés dans la même région. Par exemple, si votre cluster régional est créé dans us-central1, les disques multizones doivent être situés dans la même région (par exemple, us-central1-a, us-central1-b).

Un cas d'utilisation courant de l'inférence d'IA/ML consiste à exécuter des pods dans différentes zones afin d'améliorer la disponibilité des accélérateurs et la rentabilité avec les VM Spot. Comme Hyperdisk ML est zonal, si votre serveur d'inférence exécute de nombreux pods sur plusieurs zones, GKE clone automatiquement les disques sur plusieurs zones pour vous assurer que vos données suivent votre application.

Hydratation de Hyperdisk ML à partir de sources de données externes et création de PV multizone pour accéder aux données dans les différentes zones

Les volumes Hyperdisk ML multizones présentent les limites suivantes :

  • Les opérations de redimensionnement et d'instantanés de volume ne sont pas prises en charge.
  • Les volumes Hyperdisk ML multizones ne sont compatibles qu'avec le mode lecture seule.
  • Lorsque vous utilisez des disques préexistants avec un volume Hyperdisk ML multizone, GKE n'effectue aucune vérification pour vérifier que le contenu du disque est identique entre les zones. Si l'un des disques contient du contenu divergent, assurez-vous que votre application tient compte des incohérences potentielles entre les zones.

Pour en savoir plus, consultez la section Créer un volume ReadOnlyMany Hyperdisk ML multizone à partir d'un VolumeSnapshot.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

  • Activez l'API Google Kubernetes Engine.
  • Activer l'API Google Kubernetes Engine
  • Si vous souhaitez utiliser Google Cloud CLI pour cette tâche, installez puis initialisez gcloud CLI. Si vous avez déjà installé gcloud CLI, assurez-vous de disposer de la dernière version en exécutant la commande gcloud components update.
  • Définissez votre région et votre zone par défaut sur l'une des valeurs acceptées.
  • Assurez-vous que votre projet Google Cloud dispose d'un quota suffisant pour créer les nœuds nécessaires dans ce guide. L'exemple de code pour la création de clusters GKE et de ressources Kubernetes nécessite le quota minimal suivant dans la région de votre choix : 88 CPU C3, 8 GPU NVIDIA L4.

Exigences

Pour utiliser des volumes Hyperdisk ML dans GKE, vos clusters doivent répondre aux exigences suivantes :

  • Utilisez des clusters Linux exécutant la version 1.30.2-gke.1394000 ou une version ultérieure de GKE. Si vous utilisez une canal de publication, assurez-vous que le canal dispose de la version minimale de GKE requise pour ce pilote ou d'une version ultérieure.
  • Assurez-vous que le pilote CSI de disque persistant Compute Engine est activé. Le pilote de disque persistant Compute Engine est activé par défaut sur les nouveaux clusters Autopilot et Standard et ne peut pas être désactivé ou modifié avec l'utilisation d'Autopilot. Si vous devez activer le pilote CSI Persistent Disk Compute Engine depuis votre cluster, consultez la page Activer le pilote CSI Persistent Disk Compute Engine sur un cluster existant.
  • Si vous souhaitez ajuster la valeur readahead, utilisez GKE version 1.29.2-gke.1217000 ou ultérieure.
  • Si vous souhaitez utiliser la fonctionnalité de provisionnement dynamique multizone, utilisez GKE version 1.30.2-gke.1394000 ou ultérieure.
  • Hyperdisk ML n'est compatible qu'avec certains types de nœuds et certaines zones. Pour en savoir plus, consultez la section À propos de Google Cloud Hyperdisk dans la documentation de Compute Engine.

Accéder au modèle

Pour accéder aux modèles Gemma en vue du déploiement sur GKE, vous devez d'abord signer le contrat d'autorisation de licence, puis générer un jeton d'accès Hugging Face.

Vous devez signer le contrat de consentement pour utiliser Gemma. Procédez comme suit :

  1. Accédez à la page de consentement du modèle sur Kaggle.com.
  2. Vérifiez l'autorisation à l'aide de votre compte Hugging Face.
  3. Acceptez les conditions du modèle.

Générer un jeton d'accès

Pour accéder au modèle via Hugging Face, vous avez besoin d'un jeton Hugging Face.

Pour générer un nouveau jeton si vous n'en possédez pas, procédez comme suit :

  1. Cliquez sur Your Profile > Settings > Access Tokens (Votre profil > Paramètres > Jetons d'accès).
  2. Sélectionnez New Token (Nouveau jeton).
  3. Spécifiez le nom de votre choix et un rôle d'au moins Read.
  4. Sélectionnez Générer un jeton.
  5. Copiez le jeton dans votre presse-papiers.

Créer un cluster GKE

Vous pouvez diffuser les LLM sur des GPU dans un cluster GKE Autopilot ou GKE Standard. Nous vous recommandons d'utiliser un cluster GKE Autopilot pour une expérience Kubernetes entièrement gérée. Pour choisir le mode de fonctionnement GKE le mieux adapté à vos charges de travail, consultez la section Choisir un mode de fonctionnement GKE.

Autopilot

  1. Dans Cloud Shell, exécutez la commande suivante :

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

    Remplacez les valeurs suivantes :

    • PROJECT : ID de projet Google Cloud.
    • REGION : région compatible avec le type d'accélérateur que vous souhaitez utiliser, par exemple us-east4 pour les GPU L4.

    GKE crée un cluster Autopilot avec des nœuds de processeur et de GPU, à la demande des charges de travail déployées.

  2. Configurez kubectl de manière à communiquer avec votre cluster :

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

Standard

  1. Dans Cloud Shell, exécutez la commande suivante pour créer un cluster Standard et des pools de nœuds :

    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
    

    Remplacez les valeurs suivantes :

    • CLUSTER_VERSION : version de votre cluster GKE (par exemple, 1.30.2-gke.1394000).
    • REGION : région de calcul du plan de contrôle du cluster. La région doit être compatible avec l'accélérateur que vous souhaitez utiliser, par exemple us-east4 pour les GPU L4. Vérifiez les régions dans lesquelles les GPU L4 sont disponibles.
    • ZONES : zones dans lesquelles les nœuds sont créés. Vous pouvez spécifier autant de zones que nécessaire pour votre cluster. Toutes les zones doivent se trouver dans la même région que le plan de contrôle du cluster, spécifié par l'option --zone. Pour les clusters zonaux, --node-locations doit contenir la zone principale du cluster.
    • PROJECT : ID de projet Google Cloud.

    La création du cluster peut prendre plusieurs minutes.

  2. Configurez kubectl de manière à communiquer avec votre cluster :

    gcloud container clusters get-credentials hdml-gpu-l4
    

Mettre en cache des données dans une image de disque Persistent Disk

Pour utiliser Hyperdisk ML, vous devez mettre en cache les données dans une image disque et créer un volume Hyperdisk ML pour que votre charge de travail dispose d'un accès en lecture dans GKE. Cette approche (également appelée hydratation des données) garantit que vos données sont disponibles lorsque votre charge de travail en a besoin.

Pour copier les données de Cloud Storage afin de faire une mise en cache préalable d'une image de disque Persistent Disk, procédez comme suit :

Créer une StorageClass compatible avec Hyperdisk ML

  1. Enregistrez le fichier manifeste suivant de la StorageClass dans un fichier nommé 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. Créez la StorageClass en exécutant la commande suivante :

    kubectl create -f hyperdisk-ml.yaml
    

Créer un PersistentVolumeClaim ReadWriteOnce (RWO)

  1. Enregistrez le fichier manifeste suivant de la PersistentVolumeClaim dans un fichier nommé producer-pvc.yaml. Vous utiliserez la StorageClass que vous avez créée précédemment. Assurez-vous que votre disque dispose d'une capacité suffisante pour stocker vos données.

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: producer-pvc
    spec:
      storageClassName: hyperdisk-ml
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 300Gi
    
  2. Créez la PersistentVolumeClaim en exécutant la commande suivante :

    kubectl create -f producer-pvc.yaml
    

Créer un job Kubernetes pour renseigner le volume Google Cloud Hyperdisk installé

Cette section présente un exemple de création de job Kubernetes qui provisionne un disque et télécharge le modèle adapté aux instructions Gemma 7B de Hugging Face sur le volume Google Cloud Hyperdisk installé.

  1. Pour accéder au LLM Gemma utilisé par les exemples de ce guide, créez un Secret Kubernetes contenant le jeton Hugging Face :

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

    Remplacez HF_TOKEN par le jeton Hugging Face que vous avez généré précédemment.

  2. Enregistrez l'exemple de fichier manifeste suivant sous le nom 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
    

    Remplacez ZONE par la zone de calcul dans laquelle vous souhaitez créer le disque Hyperdisk. Si vous l'utilisez avec l'exemple d'objet déploiement, assurez-vous qu'il s'agit d'une zone disposant d'une capacité de machine G2.

  3. Créez le job en exécutant la commande suivante :

    kubectl apply -f producer-job.yaml
    

    La copie des données sur le volume Persistent Disk peut prendre quelques minutes. Une fois le provisionnement du job terminé, son état est marqué comme "Terminé".

  4. Pour vérifier la progression de l'état de votre job, exécutez la commande suivante :

    kubectl get job producer-job
    
  5. Une fois le job terminé, vous pouvez la nettoyer en exécutant la commande suivante :

    kubectl delete job producer-job
    

Créer un volume Hyperdisk ML ReadOnlyMany à partir d'un disque Google Cloud Hyperdisk préexistant

Cette section explique comment créer une paire PersistentVolume et PersistentVolumeClaim ReadOnlyMany (ROM) à partir d'un volume Google Cloud Hyperdisk existant. Pour en savoir plus, consultez la section Utiliser des disques persistants préexistants en tant que ressources PersistentVolume.

  1. Dans GKE version 1.30.2-gke.1394000 et ultérieure, GKE convertit automatiquement le mode d'accès d'un volume Google Cloud Hyperdisk READ_WRITE_SINGLE en READ_ONLY_MANY.

    Si vous utilisez un volume Google Cloud Hyperdisk préexistant sur une version antérieure de GKE, vous devez modifier le mode d'accès manuellement en exécutant la commande suivante :

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

    Remplacez les valeurs suivantes :

    • HDML_DISK_NAME : nom de votre volume Hyperdisk ML.
    • ZONE : zone de calcul dans laquelle le volume Google Cloud Hyperdisk préexistant est créé.
  2. Créez une paire PersistentVolume et PersistentVolumeClaim, en référençant le disque que vous avez précédemment renseigné.

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

      Remplacez les valeurs suivantes :

      • PROJECT : projet dans lequel votre cluster GKE est créé.
      • ZONE : zone dans laquelle le volume Google Cloud Hyperdisk préexistant est créé.
      • DISK_NAME : nom du volume Google Cloud Hyperdisk préexistant.
    2. Créez les ressources PersistentVolume et PersistentVolumeClaim en exécutant la commande suivante :

      kubectl apply -f hdml-static-pv.yaml
      

Créer un volume Hyperdisk ML ReadOnlyMany multizone à partir d'un VolumeSnapshot

Cette section explique comment créer un volume Hyperdisk ML multizone en mode d'accès ReadOnlyMany. Vous utilisez un VolumeSnapshot pour une image de disque Persistent Disk préexistante. Pour en savoir plus, consultez la section Sauvegarder le stockage Persistent Disk à l'aide d'instantanés de volume.

Pour créer le volume Hyperdisk ML multizone, procédez comme suit :

Créer un VolumeSnapshot de votre disque

  1. Enregistrez le fichier manifeste suivant dans un fichier nommé 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. Créez la classe VolumeSnapshotClass en exécutant la commande suivante :

    kubectl apply -f disk-image-vsc.yaml
    
  3. Enregistrez le fichier manifeste suivant dans un fichier nommé my-snapshot.yaml : Vous allez faire référence à l'objet PersistentVolumeClaim que vous avez créé précédemment dans la section Créer un PersistentVolumeClaim ReadWriteOnce (RWO).

    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
      name: my-snapshot
    spec:
      volumeSnapshotClassName: disk-image-vsc
      source:
        persistentVolumeClaimName: producer-pvc
    
  4. Créez le VolumeSnapshot en exécutant la commande suivante :

    kubectl apply -f my-snapshot.yaml
    
  5. Lorsque le VolumeSnapshot est marqué comme "Prêt", exécutez la commande suivante pour créer le volume Hyperdisk ML :

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

Créer une StorageClass multizone

Si vous souhaitez que les copies de vos données soient accessibles dans plusieurs zones, spécifiez le paramètre enable-multi-zone-provisioning dans votre StorageClass, qui crée des disques dans les zones que vous avez spécifiées dans le champ allowedTopologies.

Pour créer la ressource StorageClass, procédez comme suit :

  1. Enregistrez le fichier manifeste suivant dans un fichier nommé 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
    

    Remplacez ZONE_1, ZONE_2, ..., ZONE_N par les zones où votre espace de stockage est accessible.

    Cet exemple définit le volumeBindingMode sur Immediate, ce qui permet à GKE de provisionner le PersistentVolumeClaim avant tout consommateur qui le référence.

  2. Créez la classe StorageClass en exécutant la commande suivante :

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

Créer un objet PersistentVolumeClaim qui utilise la StorageClass multizone

L'étape suivante consiste à créer un objet PersistentVolumeClaim qui référence la StorageClass.

GKE utilise le contenu de l'image disque spécifiée pour provisionner automatiquement un volume Hyperdisk ML dans chaque zone spécifiée dans votre instantané.

Pour créer l'objet PersistentVolumeClaim, procédez comme suit :

  1. Enregistrez le fichier manifeste suivant dans un fichier nommé 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. Créez le PersistentVolumeClaim en exécutant la commande suivante :

    kubectl apply -f hdml-consumer-pvc.yaml
    

Créer un objet déploiement pour utiliser le volume Hyperdisk ML

Lorsque vous utilisez des pods avec des objets PersistentVolume, nous vous recommandons d'utiliser un contrôleur de charge de travail (tel que Deployment ou StatefulSet).

Si vous souhaitez utiliser un PersistentVolume préexistant en mode ReadOnlyMany avec un objet déploiement, consultez Utiliser des disques persistants avec plusieurs lecteurs.

Pour créer et tester votre objet déploiement, procédez comme suit :

  1. Enregistrez l'exemple de fichier manifeste suivant sous le nom 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
    

    Remplacez CLAIM_NAME par l'une des valeurs suivantes :

    • hdml-static-pvc : si vous utilisez un volume Hyperdisk ML d'un Google Cloud Hyperdisk existant.
    • hdml-consumer-pvc : si vous utilisez un volume Hyperdisk ML à partir d'une image de disque VolumeSnapshot.
  2. Exécutez la commande suivante pour attendre que le serveur d'inférence soit disponible :

    kubectl wait --for=condition=Available --timeout=700s deployment/vllm-gemma-deployment
    
  3. Pour vérifier que votre serveur vLLM est opérationnel, procédez comme suit :

    1. Exécutez la commande suivante pour configurer le transfert de port sur le modèle :

      kubectl port-forward service/llm-service 8000:8000
      
    2. Exécutez une commande curl pour envoyer une requête au modèle :

      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
      

    Le résultat suivant affiche un exemple de réponse du modèle :

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

Ajuster la valeur readahead

Si vous avez des charges de travail qui effectuent des E/S séquentielles, elles peuvent tirer parti du réglage de la valeur readahead. Cela s'applique généralement aux charges de travail d'inférence ou d'entraînement qui doivent charger des pondérations de modèles d'IA/ML dans la mémoire. La plupart des charges de travail avec des E/S séquentielles constatent généralement une amélioration des performances avec une valeur readahead de 1 024 Ko ou plus.

Vous pouvez spécifier cette option via l'option d'installation read_ahead_kb lorsque vous provisionnez de manière statique un nouveau PersistentVolume ou lorsque vous modifiez un objet PersistentVolume existant provisionné de manière dynamique.

L'exemple suivant montre comment régler la valeur readahead sur 4 096 ko.

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

Remplacez les valeurs suivantes :

  • DISK_NAME : nom du volume Google Cloud Hyperdisk préexistant.
  • ZONE : zone dans laquelle le volume Google Cloud Hyperdisk préexistant est créé.

Tester et comparer les performances de votre volume Hyperdisk ML

Cette section explique comment utiliser Flexible I/O Tester (FIO) pour comparer les performances de vos volumes Hyperdisk ML pour la lecture de données préexistantes. Vous pouvez utiliser ces métriques pour évaluer les performances de votre volume pour des charges de travail et des configurations spécifiques.

  1. Enregistrez l'exemple de fichier manifeste suivant sous le nom 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
    

    Remplacez CLAIM_NAME par le nom de votre PersistentVolumeClaim (par exemple, hdml-static-pvc).

  2. Mettez à jour le job en exécutant la commande suivante :

    kubectl apply -f benchmark-job.yaml.
    
  3. Utilisez les journaux kubectl pour afficher le résultat de l'outil fio :

    kubectl logs benchmark-job-nrk88 -f
    

    La sortie ressemble à ceci :

    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%
    

Surveiller le débit ou les IOPS sur un volume Hyperdisk ML

Pour surveiller les performances provisionnées de votre volume Hyperdisk ML, consultez la section Analyser les IOPS et le débit provisionnés dans la documentation de Compute Engine.

Pour mettre à jour le débit ou les IOPS provisionnés d'un volume Hyperdisk ML existant, ou pour en savoir plus sur les paramètres Google Cloud Hyperdisk supplémentaires que vous pouvez spécifier dans votre StorageClass, consultez Effectuer le scaling des performances de l'espace de stockage avec Google Cloud Hyperdisk.

Dépannage

Cette section fournit des conseils de dépannage pour résoudre les problèmes liés aux volumes Hyperdisk ML sur GKE.

Impossible de mettre à jour le mode d'accès au disque

L'erreur suivante se produit lorsqu'un volume Hyperdisk ML est déjà utilisé et associé par un nœud en mode d'accès 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 met automatiquement à jour l'accessMode du volume Hyperdisk ML de READ_WRITE_SINGLE à READ_ONLY_MANY, lorsqu'il est utilisé par un PersistentVolume du mode d'accès ReadOnlyMany. Cette mise à jour est effectuée lorsque le disque est associé à un nouveau nœud.

Pour résoudre ce problème, supprimez tous les pods qui font référence au disque à l'aide d'un PersistentVolume en mode ReadWriteOnce. Attendez que le disque soit dissocié, puis recréez la charge de travail qui consomme le PersistentVolume en mode ReadOnlyMany.

Le disque ne peut pas être associé en mode READ_WRITE

L'erreur suivante indique que GKE a tenté d'associer un volume Hyperdisk ML en mode d'accès READ_ONLY_MANY à un nœud GKE à l'aide du mode d'accès ReadWriteOnce.

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 met automatiquement à jour l'accessMode du volume Hyperdisk ML de READ_WRITE_SINGLE à READ_ONLY_MANY, lorsqu'il est utilisé par un PersistentVolume du mode d'accès ReadOnlyMany. Toutefois, GKE ne met pas automatiquement à jour le mode d'accès de READ_ONLY_MANY à READ_WRITE_SINGLE. Il s'agit d'un mécanisme de sécurité qui garantit que rien n'est écrit dans les disques multizones par accident, car cela pourrait entraîner un contenu divergent entre les disques multizones.

Pour résoudre ce problème, nous vous recommandons de suivre le workflow Mettre en cache des données dans une image de disque Persistent Disk si vous avez besoin d'un contenu mis à jour. Si vous avez besoin de plus de contrôle sur le mode d'accès et d'autres paramètres du volume Hyperdisk ML, consultez la section Modifier les paramètres d'un volume Google Cloud Hyperdisk.

Quota dépassé : quota de débit insuffisant

L'erreur suivante indique qu'il n'y avait pas suffisamment de quota de débit Hyperdisk ML au moment du provisionnement de disque.

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

Pour résoudre ce problème, consultez la section Quotas de disque pour en savoir plus sur le quota Hyperdisk et découvrir comment augmenter le quota de disque dans votre projet.

Pour obtenir des conseils de dépannage supplémentaires, consultez la section Effectuer le scaling des performances de stockage avec Google Cloud Hyperdisk.

Étape suivante