Acelerar la carga de datos de IA y aprendizaje automático con Hyperdisk ML

En esta guía se explica cómo simplificar y acelerar la carga de pesos de modelos de IA y aprendizaje automático en Google Kubernetes Engine (GKE) con Hyperdisk ML. El controlador de CSI para Persistent Disk en Compute Engine es la forma principal de acceder al almacenamiento de Hyperdisk ML con clústeres de GKE.

Información general

Hyperdisk ML es una solución de almacenamiento de alto rendimiento que se puede usar para escalar tus aplicaciones. Proporciona un alto rendimiento agregado a muchas máquinas virtuales simultáneamente, por lo que es ideal si quieres ejecutar cargas de trabajo de IA o aprendizaje automático que necesiten acceder a grandes cantidades de datos.

Si se habilita en el modo de solo lectura múltiple, puedes usar Hyperdisk ML para acelerar la carga de los pesos del modelo hasta 11,9 veces en comparación con la carga directa desde un registro de modelos. Esta aceleración es posible gracias a la arquitectura de Hyperdisk de Google Cloud, que permite escalar a 2500 nodos simultáneos a 1,2 TiB/s. Esto te permite mejorar los tiempos de carga y reducir el aprovisionamiento excesivo de pods en tus cargas de trabajo de inferencia de IA o aprendizaje automático.

Estos son los pasos generales para crear y usar Hyperdisk ML:

  1. Pre-caché o hidratación de datos en una imagen de disco de disco persistente: carga volúmenes de Hyperdisk ML con datos de una fuente de datos externa (por ejemplo, pesos de Gemma cargados desde Cloud Storage) que se pueden usar para servir. El Persistent Disk de la imagen de disco debe ser compatible con Google Cloud Hyperdisk.
  2. Crea un volumen de HyperDisk ML con un HyperDisk de Google Cloud preexistente: crea un volumen de Kubernetes que haga referencia al volumen de HyperDisk ML cargado con datos. También puedes crear clases de almacenamiento multizona para asegurarte de que tus datos estén disponibles en todas las zonas en las que se ejecuten tus pods.
  3. Crea un Deployment de Kubernetes para consumir el volumen de Hyperdisk ML: haz referencia al volumen de Hyperdisk ML con carga de datos acelerada para que tus aplicaciones lo consuman.

Volúmenes de Hyperdisk ML multizona

Los discos Hyperdisk ML solo están disponibles en una zona. También puedes usar la función multizona de Hyperdisk ML para vincular dinámicamente varios discos zonales que contengan el mismo contenido en un único PersistentVolumeClaim y PersistentVolume lógicos. Los discos zonales a los que hace referencia la función multizona deben estar ubicados en la misma región. Por ejemplo, si tu clúster regional se crea en us-central1, los discos multizona deben estar ubicados en la misma región (por ejemplo, us-central1-a y us-central1-b).

Un caso de uso habitual de la inferencia de IA o aprendizaje automático es ejecutar pods en diferentes zonas para mejorar la disponibilidad de los aceleradores y la rentabilidad con máquinas virtuales de acceso puntual. Como Hyperdisk ML es zonal, si tu servidor de inferencia ejecuta muchos pods en varias zonas, GKE clonará automáticamente los discos en las zonas para asegurarse de que tus datos sigan a tu aplicación.

Hidratación de Hyperdisk ML a partir de fuentes de datos externas y creación de un volumen persistente multizona para acceder a los datos en todas las zonas.

Los volúmenes Hyperdisk ML multizona tienen las siguientes limitaciones:

  • No se admiten las operaciones de cambio de tamaño ni las de creación de copias de volumen.
  • Los volúmenes Hyperdisk ML multizona solo se admiten en modo de solo lectura.
  • Cuando se usan discos preexistentes con un volumen de Hyperdisk ML multizona, GKE no realiza comprobaciones para validar que el contenido del disco en las zonas sea el mismo. Si alguno de los discos contiene contenido diferente, asegúrate de que tu aplicación tenga en cuenta las posibles incoherencias entre las zonas.

Para obtener más información, consulta Crear un volumen de Hyperdisk ML ReadOnlyMany multizona a partir de un VolumeSnapshot.

Antes de empezar

Antes de empezar, asegúrate de que has realizado las siguientes tareas:

  • Habilita la API de Google Kubernetes Engine.
  • Habilitar la API de Google Kubernetes Engine
  • Si quieres usar Google Cloud CLI para esta tarea, instálala y, a continuación, inicialízala. Si ya has instalado la gcloud CLI, obtén la versión más reciente ejecutando gcloud components update.
  • Defina su región y zona predeterminadas con uno de los valores admitidos.
  • Comprueba que tu Trusted Cloud proyecto tiene suficiente cuota para crear los nodos necesarios en esta guía. El código de ejemplo para la creación de clústeres de GKE y recursos de Kubernetes requiere la siguiente cuota mínima en la región que elijas: 88 CPUs C3 y 8 GPUs NVIDIA L4.

Requisitos

Para usar volúmenes de Hyperdisk ML en GKE, tus clústeres deben cumplir los siguientes requisitos:

  • Usa clústeres Linux con la versión 1.30.2-gke.1394000 de GKE o una posterior. Si usas un canal de lanzamiento, asegúrate de que tenga la versión mínima de GKE o una posterior que se requiera para este controlador.
  • Asegúrate de que el controlador de CSI para Persistent Disk en Compute Engine esté habilitado. El controlador de Persistent Disk de Compute Engine está habilitado de forma predeterminada en los clústeres Autopilot y Standard nuevos, y no se puede inhabilitar ni editar cuando se usa Autopilot. Si necesitas habilitar el controlador de CSI para Persistent Disk en Compute Engine desde tu clúster, consulta el artículo Habilitar el controlador de CSI para Persistent Disk en Compute Engine en un clúster ya creado.
  • Si quieres ajustar el valor de lectura anticipada, usa la versión 1.29.2-gke.1217000 de GKE o una posterior.
  • Si quieres usar la función de aprovisionamiento dinámico multizona, utiliza la versión 1.30.2-gke.1394000 de GKE o una posterior.
  • Hyperdisk ML solo se admite en determinados tipos de nodos y zonas. Para obtener más información, consulta el artículo Acerca de Hyperdisk ML en la documentación de Compute Engine.

Acceder al modelo

Para acceder a los modelos de Gemma e implementarlos en GKE, primero debes firmar el acuerdo de consentimiento de licencia y, a continuación, generar un token de acceso de Hugging Face.

Debes firmar el acuerdo de consentimiento para usar Gemma. Te las indicamos a continuación:

  1. Accede a la página de consentimiento del modelo en Kaggle.com.
  2. Verifica el consentimiento con tu cuenta de Hugging Face.
  3. Acepta los términos del modelo.

Generar un token de acceso

Para acceder al modelo a través de Hugging Face, necesitarás un token de Hugging Face.

Sigue estos pasos para generar un token si aún no tienes uno:

  1. Haz clic en Tu perfil > Configuración > Tokens de acceso.
  2. Selecciona New Token (Nuevo token).
  3. Especifica el nombre que quieras y un rol de al menos Read.
  4. Selecciona Generar un token.
  5. Copia el token generado en el portapapeles.

Crear un clúster de GKE

Puedes servir LLMs en GPUs en un clúster Autopilot o Standard de GKE. Te recomendamos que uses un clúster de Autopilot para disfrutar de una experiencia de Kubernetes totalmente gestionada. Para elegir el modo de funcionamiento de GKE que mejor se adapte a tus cargas de trabajo, consulta Elegir un modo de funcionamiento de GKE.

Autopilot

  1. En Cloud Shell, ejecuta el siguiente comando:

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

    Sustituye los siguientes valores:

    • PROJECT: el ID del proyecto. Trusted Cloud by S3NS
    • CONTROL_PLANE_LOCATION: la región de Compute Engine del plano de control de tu clúster. Proporciona una región que admita el tipo de acelerador que quieras usar. Por ejemplo, us-east4 para la GPU L4.

    GKE crea un clúster de Autopilot con nodos de CPU y GPU según lo soliciten las cargas de trabajo desplegadas.

  2. Configura kubectl para que se comunique con tu clúster:

    gcloud container clusters get-credentials hdml-gpu-l4 \
      --location=CONTROL_PLANE_LOCATION
    

Estándar

  1. En Cloud Shell, ejecuta el siguiente comando para crear un clúster Standard y grupos de nodos:

    gcloud container clusters create hdml-gpu-l4 \
        --location=CONTROL_PLANE_LOCATION \
        --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=CONTROL_PLANE_LOCATION \
        --project=PROJECT \
        --node-locations=ZONES \
        --cluster=hdml-gpu-l4 \
        --machine-type=g2-standard-24 \
        --num-nodes=2
    

    Sustituye los siguientes valores:

    • CLUSTER_VERSION: la versión de tu clúster de GKE (por ejemplo, 1.30.2-gke.1394000).
    • CONTROL_PLANE_LOCATION: la ubicación de Compute Engine del plano de control de tu clúster. En el caso de los clústeres regionales, proporciona una región con una zona que admita el acelerador que quieras usar. En el caso de los clústeres zonales, proporciona una zona que admita el acelerador que quieras usar. Para comprobar dónde están disponibles los aceleradores específicos, consulta la disponibilidad de las GPUs por regiones y zonas.
    • ZONES: las zonas en las que se crean los nodos. Puedes especificar tantas zonas como necesites para tu clúster. Todas las zonas deben estar en la misma región que el plano de control del clúster, especificada por la marca --location. En el caso de los clústeres zonales, --node-locations debe contener la zona principal del clúster.
    • PROJECT: el ID del proyecto. Trusted Cloud by S3NS

    La creación del clúster puede tardar varios minutos.

  2. Configura kubectl para que se comunique con tu clúster:

    gcloud container clusters get-credentials hdml-gpu-l4
    

Pre-almacenar en caché datos en una imagen de disco de Persistent Disk

Para usar Hyperdisk ML, debes prealmacenar en caché los datos en una imagen de disco y crear un volumen de Hyperdisk ML para que tu carga de trabajo en GKE pueda acceder a él para leer. Este enfoque (también llamado hidratación de datos) asegura que tus datos estén disponibles cuando tu carga de trabajo los necesite.

En los siguientes pasos se describe cómo copiar manualmente datos de una fuente, como un repositorio de Hugging Face, directamente en un volumen de Hyperdisk ML mediante un trabajo de Kubernetes.

Si tus datos ya están en un segmento de Cloud Storage, puedes usar Hyperdisk ML para automatizar la transferencia de datos de Cloud Storage a Hyperdisk ML. De esta forma, no tendrás que seguir los pasos para crear manualmente un trabajo que se describen en las siguientes secciones.

Crear un StorageClass que admita Hyperdisk ML

  1. Guarda el siguiente manifiesto de StorageClass en un archivo llamado hyperdisk-ml.yaml.

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
        name: hyperdisk-ml
    parameters:
        type: hyperdisk-ml
        provisioned-throughput-on-create: "2400Mi"
    provisioner: pd.csi.storage.gke.io
    allowVolumeExpansion: false
    reclaimPolicy: Delete
    volumeBindingMode: WaitForFirstConsumer
    mountOptions:
      - read_ahead_kb=4096
    
  2. Crea el objeto StorageClass ejecutando este comando:

    kubectl create -f hyperdisk-ml.yaml
    

Crear un PersistentVolumeClaim ReadWriteOnce (RWO)

  1. Guarda el siguiente manifiesto de PersistentVolumeClaim en un archivo llamado producer-pvc.yaml. Usarás el StorageClass que has creado antes. Este PVC usa el modo de acceso ReadWriteOnce porque lo utiliza un trabajo de Kubernetes para descargar datos del modelo en el disco persistente, lo que requiere acceso de escritura. Google Cloud Hyperdisk no admite el modo de acceso ReadWriteMany. Asegúrate de que tu disco tenga capacidad suficiente para almacenar tus datos.

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: producer-pvc
    spec:
      storageClassName: hyperdisk-ml
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 300Gi
    
  2. Para crear el PersistentVolumeClaim, ejecuta este comando:

    kubectl create -f producer-pvc.yaml
    

Crear un trabajo de Kubernetes para rellenar el volumen de HyperDisk de Google Cloud montado

En esta sección se muestra un ejemplo de cómo crear un trabajo de Kubernetes que aprovisione un disco y descargue el modelo ajustado de instrucciones de Gemma 7B de Hugging Face en el volumen de Google Cloud Hyperdisk montado.

  1. Para acceder al LLM de Gemma que usan los ejemplos de esta guía, crea un secreto de Kubernetes que contenga el token de Hugging Face:

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

    Sustituye HF_TOKEN por el token de Hugging Face que has generado anteriormente.

  2. Guarda el siguiente manifiesto de ejemplo como producer-job.yaml:

    apiVersion: batch/v1
    kind: Job
    metadata:
      name: producer-job
    spec:
      template:
        spec:
          affinity:
            # Node affinity ensures that Pods are scheduled on the nodes that support Hyperdisk ML.
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  # Specifies the Performance compute class. For more information,
                  # see https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-compute-classes#when-to-use.
                  - key: cloud.google.com/compute-class
                    operator: In
                    values:
                    - "Performance"
                - matchExpressions:
                  - key: cloud.google.com/machine-family
                    operator: In
                    values:
                    - "c3"
                - matchExpressions:
                  # Restricts Pod scheduling to a specific zone because Hyperdisk ML disks
                  # are a zonal resource.
                  - key: topology.kubernetes.io/zone
                    operator: In
                    values:
                    - "ZONE"
          containers:
          - name: copy
            resources:
              requests:
                cpu: "32"
              limits:
                cpu: "32"
             # The image used to download models from Hugging Face.
            image: huggingface/downloader:0.17.3
            command: [ "huggingface-cli" ]
            args:
            - download
            # The Hugging Face model to download.
            - google/gemma-1.1-7b-it
            # Destination directory within the container.
            - --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:
              # Mount path for the PersistentVolume.
              - mountPath: "/data"
                name: volume
          # Prevents Pod restarts on scheduling failures. The Job will create new Pods
          # for retries, up to the specified "backoffLimit".
          restartPolicy: Never
          volumes:
            - name: volume
              persistentVolumeClaim:
                # References the Hyperdisk ML PVC created earlier.
                claimName: producer-pvc
      # Runs only one Pod at any given time.
      parallelism: 1
      # After the Pod runs successfully, the Job is complete.
      completions: 1
      # Max retries on Pod failure.
      backoffLimit: 4
    

    Sustituye ZONE por la zona de cálculo en la que quieras crear el hiperdisco. Si lo usas con el ejemplo de implementación, asegúrate de que sea una zona que tenga capacidad de máquinas G2.

  3. Para crear el trabajo, ejecuta este comando:

    kubectl apply -f producer-job.yaml
    

    El trabajo puede tardar unos minutos en terminar de copiar los datos en el volumen del disco persistente. Cuando la tarea completa el aprovisionamiento, su estado se marca como "Completada".

  4. Para comprobar el progreso del estado de tu trabajo, ejecuta el siguiente comando:

    kubectl get job producer-job
    
  5. Una vez que se haya completado el trabajo, puedes limpiarlo ejecutando este comando:

    kubectl delete job producer-job
    

Crear un volumen de Hyperdisk ML ReadOnlyMany a partir de un Hyperdisk de Google Cloud preexistente

En esta sección se describen los pasos para crear un par de PersistentVolume y PersistentVolumeClaim ReadOnlyMany (ROM) a partir de un volumen de Hyperdisk de Google Cloud preexistente. Para obtener más información, consulta Usar discos persistentes preexistentes como volúmenes persistentes.

  1. En la versión 1.30.2-gke.1394000 de GKE y posteriores, GKE convierte automáticamente el modo de acceso de un volumen de READ_WRITE_SINGLEGoogle Cloud Hyperdisk a READ_ONLY_MANY.

    Si estás usando un volumen de Hyperdisk de Google Cloud en una versión anterior de GKE, debes modificar el modo de acceso manualmente ejecutando el siguiente comando:

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

    Sustituye los siguientes valores:

    • HDML_DISK_NAME: el nombre de tu volumen de Hyperdisk ML.
    • ZONE: la zona de cálculo en la que se crea el volumen de Hyperdisk de Google Cloud.
  2. Crea un par PersistentVolume y PersistentVolumeClaim que haga referencia al disco que has rellenado anteriormente.

    1. Guarda el siguiente archivo de manifiesto como hdml-static-pv.yaml:

      apiVersion: v1
      kind: PersistentVolume
      metadata:
        name: hdml-static-pv
      spec:
        storageClassName: "hyperdisk-ml"
        capacity:
          storage: 300Gi
        # The "ReadOnlyMany" access mode allows the volume to be mounted by multiple
        # nodes for read-only access.
        accessModes:
          - ReadOnlyMany
        # ClaimRef links this PersistentVolume to a PersistentVolumeClaim.
        claimRef:
          namespace: default
          name: hdml-static-pvc
        csi:
          driver: pd.csi.storage.gke.io
          # The unique identifier of the Compute Engine disk resource backing
          # this volume.
          volumeHandle: projects/PROJECT/zones/ZONE/disks/DISK_NAME
          fsType: ext4
          readOnly: true
        # Node affinity ensures that Pod is scheduled in a zone where the volume
        # is replicated.
        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
      

      Sustituye los siguientes valores:

      • PROJECT: el proyecto en el que se crea el clúster de GKE.
      • ZONE: la zona en la que se crea el volumen de Google Cloud Hyperdisk preexistente.
      • DISK_NAME: el nombre del volumen de Google Cloud Hyperdisk que ya existe.
    2. Crea los recursos PersistentVolume y PersistentVolumeClaim ejecutando este comando:

      kubectl apply -f hdml-static-pv.yaml
      

Crear un volumen de Hyperdisk ML ReadOnlyMany multizona a partir de un VolumeSnapshot

En esta sección se describen los pasos para crear un volumen de Hyperdisk ML multizona en el modo de acceso ReadOnlyMany. Usas un VolumeSnapshot para una imagen de disco de Persistent Disk preexistente. Para obtener más información, consulta el artículo sobre cómo crear copias de seguridad del almacenamiento de discos persistentes mediante capturas de volumen.

Para crear el volumen de Hyperdisk ML multizona, sigue estos pasos:

Crea un VolumeSnapshot de tu disco

  1. Guarda el siguiente manifiesto como un archivo llamado disk-image-vsc.yaml.

    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshotClass
    metadata:
      name: disk-image-vsc
    driver: pd.csi.storage.gke.io
    # The snapshot will be deleted when the "VolumeSnapshot" object is deleted.
    deletionPolicy: Delete
    parameters:
      snapshot-type: images
    
  2. Para crear el recurso VolumeSnapshotClass, ejecuta el siguiente comando:

    kubectl apply -f disk-image-vsc.yaml
    
  3. Guarda el siguiente manifiesto como un archivo llamado my-snapshot.yaml. Hacer referencia al PersistentVolumeClaim que has creado anteriormente en Crear un PersistentVolumeClaim ReadWriteOnce (RWO).

    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
      name: my-snapshot
    spec:
      volumeSnapshotClassName: disk-image-vsc
      source:
        # The name of the PersistentVolumeClaim to snapshot.
        persistentVolumeClaimName: producer-pvc
    
  4. Para crear el recurso VolumeSnapshot, ejecuta el siguiente comando:

    kubectl apply -f my-snapshot.yaml
    
  5. Cuando el VolumeSnapshot esté marcado como "Ready", ejecuta el siguiente comando para crear el volumen de Hyperdisk ML:

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

Crear un StorageClass multizona

Si quieres que se pueda acceder a copias de tus datos en más de una zona, especifica el parámetro enable-multi-zone-provisioning en tu StorageClass, que crea discos en las zonas que hayas especificado en el campo allowedTopologies.

Para crear el StorageClass, sigue estos pasos:

  1. Guarda el siguiente manifiesto como un archivo llamado 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: "4800Mi"
      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
    mountOptions:
      - read_ahead_kb=8192
    

    Sustituye ZONE_1, ZONE_2, ..., ZONE_N por las zonas en las que se puede acceder a tu almacenamiento.

    En este ejemplo, se define el valor Immediate en volumeBindingMode, lo que permite a GKE aprovisionar el PersistentVolumeClaim antes de que cualquier consumidor haga referencia a él.

  2. Para crear el recurso StorageClass, ejecuta el siguiente comando:

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

Crea un PersistentVolumeClaim que use el StorageClass multizona

El siguiente paso es crear un PersistentVolumeClaim que haga referencia a StorageClass.

GKE usa el contenido de la imagen de disco especificada para aprovisionar automáticamente un volumen de Hyperdisk ML en cada zona especificada en tu snapshot.

Para crear el PersistentVolumeClaim, sigue estos pasos:

  1. Guarda el siguiente manifiesto como un archivo llamado hdml-consumer-pvc.yaml.

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: hdml-consumer-pvc
    spec:
      # Specifies that the new PersistentVolumeClaim should be provisioned from the
      # contents of the volume snapshot named "my-snapshot".
      dataSource:
        name: my-snapshot
        kind: VolumeSnapshot
        apiGroup: snapshot.storage.k8s.io
      accessModes:
      - ReadOnlyMany
      storageClassName: hyperdisk-ml-multi-zone
      resources:
        requests:
          storage: 300Gi
    
  2. Para crear el PersistentVolumeClaim, ejecuta el siguiente comando:

    kubectl apply -f hdml-consumer-pvc.yaml
    

Crear un Deployment para consumir el volumen de Hyperdisk ML

Cuando utilices pods con PersistentVolumes, te recomendamos que uses un controlador de carga de trabajo (como un Deployment o un StatefulSet).

Si quieres usar un objeto PersistentVolume preexistente en modo ReadOnlyMany con un objeto Deployment, consulta Usar discos persistentes con varios lectores.

Para crear y probar tu implementación, sigue estos pasos:

  1. Guarda el siguiente manifiesto de ejemplo como vllm-gemma-deployment.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-gemma-deployment
    spec:
      replicas: 2
      selector:
        # Labels used to select the Pods managed by this Deployment.
        matchLabels:
          app: gemma-server
      template:
        metadata:
          labels:
            app: gemma-server
            # Labels for AI/GKE integration.
            ai.gke.io/model: gemma-7b
            ai.gke.io/inference-server: vllm
        spec:
          affinity:
            # Node affinity ensures Pods run on nodes with L4 GPUs.
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                - matchExpressions:
                  - key: cloud.google.com/gke-accelerator
                    operator: In
                    values:
                    - nvidia-l4
            # Pod anti-affinity prefers scheduling Pods in different zones for
            # higher availability.
            podAntiAffinity:
              preferredDuringSchedulingIgnoredDuringExecution:
              - weight: 100
                podAffinityTerm:
                  labelSelector:
                    matchExpressions:
                    - key: app
                      operator: In
                      values:
                      - gemma-server
                  topologyKey: topology.kubernetes.io/zone
          containers:
          - name: inference-server
            # The container image for the vLLM 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 to run the vLLM API server.
            command: ["python3", "-m", "vllm.entrypoints.api_server"]
            args:
            # Specifies the model to load, using an environment variable.
            - --model=$(MODEL_ID)
            - --tensor-parallel-size=2
            env:
            # Environment variable to define the model path.
            - name: MODEL_ID
              value: /models/gemma-7b
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
            # Mount point for the Hyperdisk ML volume containing the model.
            - mountPath: /models
              name: gemma-7b
          volumes:
          - name: dshm
            emptyDir:
                medium: Memory
          - name: gemma-7b
            # References the PersistentVolumeClaim for the Hyperdisk ML volume.
            persistentVolumeClaim:
              claimName: CLAIM_NAME
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: llm-service
    spec:
      # Selects Pods with the label "app: gemma-server".
      selector:
        app: gemma-server
      # The "ClusterIP" field makes the Service reachable only within the cluster.
      type: ClusterIP
      ports:
        - protocol: TCP
          port: 8000
          targetPort: 8000
    

    Sustituye CLAIM_NAME por uno de estos valores:

    • hdml-static-pvc: si usas un volumen de Hyperdisk ML de un Hyperdisk de Google Cloud.
    • hdml-consumer-pvc: si usas un volumen de Hyperdisk ML a partir de una imagen de disco de VolumeSnapshot.
  2. Ejecuta el siguiente comando para esperar a que el servidor de inferencia esté disponible:

    kubectl wait --for=condition=Available --timeout=700s deployment/vllm-gemma-deployment
    
  3. Para comprobar que tu servidor vLLM está en funcionamiento, sigue estos pasos:

    1. Ejecuta el siguiente comando para configurar el reenvío de puertos al modelo:

      kubectl port-forward service/llm-service 8000:8000
      
    2. Ejecuta un comando curl para enviar una solicitud al modelo:

      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
      

    En el siguiente resultado se muestra un ejemplo de la respuesta del modelo:

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

Ajustar el valor de lectura anticipada

Si tienes cargas de trabajo que realizan operaciones de E/S secuenciales, puede que te convenga ajustar el valor de lectura anticipada. Esto suele aplicarse a cargas de trabajo de inferencia o entrenamiento que necesitan cargar pesos de modelos de IA o aprendizaje automático en la memoria. La mayoría de las cargas de trabajo con E/S secuencial suelen experimentar una mejora del rendimiento con un valor de lectura anticipada de 1024 KB o superior.

Ajustar el valor de lectura anticipada de los nuevos volúmenes

Para especificar esta opción, añade read_ahead_kb al campo mountOptions de tu StorageClass. En el siguiente ejemplo se muestra cómo puedes ajustar el valor de lectura anticipada a 4096 KB. Esto se aplicará a los volúmenes persistentes aprovisionados dinámicamente que se creen con la clase de almacenamiento hyperdisk-ml.

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
mountOptions:
  - read_ahead_kb=4096

Ajustar el valor de lectura anticipada de los volúmenes

En el caso de los volúmenes aprovisionados de forma estática o los PersistentVolumes preexistentes, puedes especificar esta opción añadiendo read_ahead_kb al campo spec.mountOptions. En el siguiente ejemplo se muestra cómo ajustar el valor de lectura anticipada a 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
    # The unique identifier of the Compute Engine disk resource backing this volume.
    volumeHandle: projects/PROJECT/zones/ZONE/disks/DISK_NAME
  # Node affinity ensures that Pods are scheduled in the zone where the volume exists.
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: topology.gke.io/zone
          operator: In
          values:
          - ZONE
  storageClassName: hyperdisk-ml
  mountOptions:
  - read_ahead_kb=4096

Sustituye los siguientes valores:

  • DISK_NAME: el nombre del volumen de Google Cloud Hyperdisk que ya existe.
  • ZONE: la zona en la que se crea el volumen de Google Cloud Hyperdisk preexistente.

Probar y comparar el rendimiento de tu volumen de Hyperdisk ML

En esta sección se muestra cómo puede usar Flexible I/O Tester (FIO) para comparar el rendimiento de sus volúmenes de Hyperdisk ML al leer datos preexistentes . Puede usar estas métricas para evaluar el rendimiento de su volumen en cargas de trabajo y configuraciones específicas.

  1. Guarda el siguiente manifiesto de ejemplo como 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
            # Specifies the files to use for the benchmark. Multiple files can be separated by colons.
            - --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
            # Use non-buffered I/O.
            - --direct=1
            # Set the I/O pattern to read.
            - --rw=read
            # Open files in read-only mode.
            - --readonly
            # Block size for I/O operations.
            - --bs=4096k
            # I/O engine to use.
            - --ioengine=libaio
            # Number of I/O units to keep in flight against each file.
            - --iodepth=8
            # Duration of the test in seconds.
            - --runtime=60
            # Number of jobs to run.
            - --numjobs=1
            # Name of the job.
            - --name=read_benchmark
            volumeMounts:
            - mountPath: "/models"
              name: volume
          restartPolicy: Never
          volumes:
          - name: volume
            persistentVolumeClaim:
              claimName: hdml-static-pvc
      parallelism: 1
      completions: 1
      backoffLimit: 1
    

    Sustituye CLAIM_NAME por el nombre de tu PersistentVolumeClaim (por ejemplo, hdml-static-pvc).

  2. Para crear el trabajo, ejecuta el siguiente comando:

    kubectl apply -f benchmark-job.yaml.
    
  3. Usa los kubectlregistros para ver el resultado de la herramienta fio:

    kubectl logs benchmark-job-nrk88 -f
    

    El resultado es similar al siguiente:

    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%
    

Monitorizar el rendimiento o las IOPS de un volumen de Hyperdisk ML

Para monitorizar el rendimiento aprovisionado de tu volumen de Hyperdisk ML, consulta el artículo Analizar las IOPS y el rendimiento aprovisionados de la documentación de Compute Engine.

Para actualizar el rendimiento o las IOPS aprovisionadas de un volumen de Hyperdisk ML, o para obtener información sobre los parámetros adicionales de Hyperdisk de Google Cloud que puede especificar en su StorageClass, consulte Escalar el rendimiento del almacenamiento con Hyperdisk de Google Cloud.

Solución de problemas

En esta sección se proporcionan directrices para solucionar problemas con los volúmenes de Hyperdisk ML en GKE.

No se puede actualizar el modo de acceso al disco

El siguiente error se produce cuando un volumen de aprendizaje automático de Hyperdisk ya está en uso y conectado por un nodo en modo de acceso 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 actualiza automáticamente el valor de accessMode del volumen de Hyperdisk ML de READ_WRITE_SINGLE a READ_ONLY_MANY cuando lo utiliza un PersistentVolume con el modo de acceso ReadOnlyMany. Esta actualización se realiza cuando el disco se conecta a un nuevo nodo.

Para solucionar este problema, elimina todos los pods que hagan referencia al disco mediante un PersistentVolume en modo ReadWriteOnce. Espera a que se desmonte el disco y, a continuación, vuelve a crear la carga de trabajo que consume el objeto PersistentVolume en modo ReadOnlyMany.

El disco no se puede adjuntar en el modo READ_WRITE

El siguiente error indica que GKE ha intentado adjuntar un volumen de Hyperdisk ML en modo de acceso READ_ONLY_MANY a un nodo de GKE mediante el modo de acceso 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 actualiza automáticamente el valor de accessMode del volumen de Hyperdisk ML de READ_WRITE_SINGLE a READ_ONLY_MANY cuando lo utiliza un PersistentVolume con el modo de acceso ReadOnlyMany. Sin embargo, GKE no actualizará automáticamente el modo de acceso de READ_ONLY_MANY a READ_WRITE_SINGLE. Se trata de un mecanismo de seguridad para asegurarse de que no se escriba en los discos multizona por error, ya que esto podría provocar que el contenido de los discos multizona sea diferente.

Para solucionar este problema, te recomendamos que sigas el flujo de trabajo Pre-cache data to a Persistent Disk disk image (Pre-almacenar en caché datos en una imagen de disco de Persistent Disk) si necesitas contenido actualizado. Si necesitas más control sobre el modo de acceso y otros ajustes del volumen de Hyperdisk ML, consulta Modificar los ajustes de un volumen de Hyperdisk Trusted Cloud by S3NS .

Se ha superado la cuota: cuota de rendimiento insuficiente

El siguiente error indica que no había suficiente cuota de cantidad de datos provisionados de Hyperdisk ML en el momento del aprovisionamiento del disco.

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

Para solucionar este problema, consulte Cuotas de disco para obtener más información sobre la cuota de Hyperdisk y cómo aumentarla en su proyecto.

Para obtener más información sobre cómo solucionar problemas, consulta el artículo Escalar el rendimiento del almacenamiento con Hyperdisk de Google Cloud.

Siguientes pasos