Note:

Despliegue de NVIDIA NIM en OKE para la inferencia con el repositorio de modelos almacenado en OCI Object Storage

Introducción

En este tutorial se muestra cómo desplegar NVIDIA NIM en Oracle Cloud Infrastructure Container Engine for Kubernetes (OKE) con el backend NVIDIA TensorRT-LLM y el servidor de inferencia NVIDIA Triton para ofrecer modelos de lenguaje grande (LLM) en una arquitectura de Kubernetes. El modelo utilizado es Llama2-7B-chat en una GPU A10. Para la escalabilidad, alojamos el repositorio de modelos en un cubo de OCI Object Storage.

Nota: Todas las pruebas de este tutorial se han publicado con una versión de acceso anticipado de NVIDIA NIM para LLM con nemollm-inference-ms:24.02.rc4.

Objetivos

Requisitos

Tarea 1: Creación de una instancia de GPU en OCI Compute

  1. Conéctese a la consola de OCI, vaya al menú de OCI, Recursos informáticos, Instancias y haga clic en Crear instancia.

  2. Seleccione VM.GPU.A10.1 con la imagen de Oracle Cloud Marketplace, la imagen de la máquina NVIDIA GPU Cloud y un volumen de inicio de 250 GB. Para obtener más información, consulte Uso de NVIDIA GPU Cloud con Oracle Cloud Infrastructure.

  3. Una vez que la máquina esté activa, conéctese a ella utilizando su clave privada y la IP pública de la máquina.

    ssh -i <private_key> ubuntu@<public_ip>
    
  4. Asegúrese de que el volumen de inicio haya aumentado el espacio.

    df -h     # check the initial space on disk
    sudo growpart /dev/sda 1
    sudo resize2fs /dev/sda1
    df -h     # check the space after the commands execution
    

Tarea 2: Actualización de los controladores NVIDIA (Opcional)

Se recomienda actualizar los controladores a la última versión según la guía proporcionada por NVIDIA con la matriz de compatibilidad entre los controladores y su versión CUDA. Para obtener más información, consulte CUDA Compatibility y CUDA Toolkit 12.4 Update 1 Downloads.

sudo apt purge nvidia* libnvidia*
sudo apt-get install -y cuda-drivers-545
sudo apt-get install -y nvidia-kernel-open-545
sudo apt-get -y install cuda-toolkit-12-3
sudo reboot

Asegúrese de tener nvidia-container-toolkit.

sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

Ejecute el siguiente comando para comprobar la nueva versión.

nvidia-smi
/usr/local/cuda/bin/nvcc --version

Tarea 3: Preparación del registro del modelo

Es posible utilizar modelos incorporados. Sin embargo, elegimos ejecutar Llama2-7B-chat en una GPU A10. En el momento de escribir, esta opción no está disponible y, por lo tanto, tenemos que crear el repositorio de modelos nosotros mismos.

  1. Cree un cubo denominado NIM en OCI Object Storage. Para obtener más información, consulte Creación de un cubo de Object Storage.

  2. Vaya a la ventana de terminal, conéctese al registro de contenedores de NVIDIA con su nombre de usuario y contraseña y extraiga el contenedor. Ejecute el siguiente comando.

    docker login nvcr.io
    docker pull nvcr.io/ohlfw0olaadg/ea-participants/nemollm-inference-ms:24.02.rc4
    
  3. Clone el modelo HuggingFace.

    # Install git-lfs
    curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
    sudo apt-get install git-lfs
    
    # clone the model from HF
    git clone https://huggingface.co/meta-llama/Llama-2-7b-chat-hf
    
  4. Cree la configuración del modelo.

    Copie el archivo model_config.yaml y cree el directorio para alojar el almacén de modelos. Aquí es donde el comando del generador del repositorio del modelo almacenará la salida.

    mkdir model-store
    chmod -R 777 model-store
    
  5. Ejecute el comando del generador del repositorio de modelos.

    docker run --rm -it --gpus all -v $(pwd)/model-store:/model-store -v $(pwd)/model_config.yaml:/model_config.yaml -v $(pwd)/Llama-2-7b-chat-hf:/engine_dir nvcr.io/ohlfw0olaadg/ea-participants/nemollm-inference-ms:24.02.rc4 bash -c "model_repo_generator llm --verbose --yaml_config_file=/model_config.yaml"
    
  6. Exportar el repositorio de modelos a un cubo de OCI Object Storage.

    El repositorio de modelos se encuentra en el directorio model-store. Puede utilizar la interfaz de línea de comandos (CLI de OCI) de Oracle Cloud Infrastructure para realizar una carga masiva en uno de sus cubos de la región. Para este tutorial, el cubo es NIM donde queremos que se cargue el almacén de modelos en NIM/llama2-7b-hf (en caso de que cargamos una configuración de modelo diferente en el mismo cubo).

    cd model-store
    oci os object bulk-upload -bn NIM --src-dir . --prefix llama2-7b-hf/ --auth instance_principal
    

Tarea 4: Envío de una solicitud a la máquina virtual (IaaS Ejecución)

Ahora, el repositorio de modelos se carga en un cubo de OCI Object Storage.

Nota: El parámetro de opción --model-repository está actualmente codificado en el contenedor; no podemos simplemente apuntar al cubo cuando lo iniciamos. Una opción será adaptar el script de Python dentro del contenedor, pero necesitaremos el privilegio sudo. El otro será montar el cubo como un sistema de archivos en la máquina directamente. Para este tutorial, elegimos el segundo método con rclone. Asegúrese de que fuse3 y jq están instalados en la máquina. En Ubuntu, puede ejecutar sudo apt install fuse3 jq.

  1. Obtenga el espacio de nombres, el OCID de compartimento y la región, recuperándolos de la consola de OCI o ejecutando los siguientes comandos desde la instancia informática.

    #NAMESPACE:
    echo namespace is : `oci os ns get --auth instance_principal | jq .data`
    
    #COMPARTMENT_OCID:
    echo compartment ocid is: `curl -H "Authorization: Bearer Oracle" -L http://169.254.169.254/opc/v2/instance/ | jq .compartmentId`
    
    #REGION:
    echo region is: `curl -H "Authorization: Bearer Oracle" -L http://169.254.169.254/opc/v2/instance/ | jq .region`
    
  2. Descargue e instale rclone.

    curl https://rclone.org/install.sh | sudo bash
    
  3. Prepare el archivo de configuración de rclone. Asegúrese de actualizar ##NAMESPACE## ##COMPARTMENT_OCID## ##REGION## con los valores.

    mkdir -p ~/rclone
    mkdir -p ~/test_directory/model_bucket_oci
    
    
    cat << EOF > ~/rclone/rclone.conf
    [model_bucket_oci]
    type = oracleobjectstorage
    provider = instance_principal_auth
    namespace = ##NAMESPACE##
    compartment = ##COMPARTMENT_OCID##
    region = ##REGION##
    
    EOF
    
  4. Monte el cubo mediante rclone.

    sudo /usr/bin/rclone mount --config=$HOME/rclone/rclone.conf --tpslimit 50 --vfs-cache-mode writes --allow-non-empty --transfers 10 --allow-other model_bucket_oci:NIM/llama2-7b-hf $HOME/test_directory/model_bucket_oci
    
  5. En otra ventana de terminal, puede comprobar que ls $HOME/test_directory/model_bucket_oci devuelve el contenido del cubo.

  6. En otra ventana de terminal, inicie el contenedor transfiriendo la ruta de acceso a model-store como argumento.

    docker run --gpus all -p9999:9999 -p9998:9998 -v  $HOME/test_directory/model_bucket_oci:/model-store nvcr.io/ohlfw0olaadg/ea-participants/nemollm-inference-ms:24.02.rc4 nemollm_inference_ms --model llama2-7b-chat --openai_port="9999" --nemo_port="9998" --num_gpus 1
    
  7. Después de 3 minutos, el servidor de inferencia debe estar listo para servir. En otra ventana de terminal, puede ejecutar la siguiente solicitud.

    Nota: Si desea ejecutarlo desde la máquina local, tendrá que utilizar la IP pública y abrir el puerto 9999 en el nivel de máquina y de subred.

    curl -X "POST" 'http://localhost:9999/v1/completions' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{ "model": "llama2-7b-chat", "prompt": "Can you briefly describe Oracle Cloud?", "max_tokens": 100, "temperature": 0.7, "n": 1, "stream": false, "stop": "string", "frequency_penalty": 0.0 }' | jq ".choices[0].text"
    

Tarea 5: Actualización del script cloud-init

Nota: Idealmente, una forma más limpia de utilizar rclone en Kubernetes sería utilizar el contenedor rclone como sidecar antes de iniciar el servidor de inferencia. Esto funciona bien localmente mediante Docker, pero debido a que necesita la opción --device para utilizar fuse, esto dificulta su uso con Kubernetes debido a la falta de soporte para esta función (Volúmenes FUSE, una solicitud de función de 2015 todavía muy activa a partir de marzo de 2024). Para este tutorial, la solución alternativa que elegimos es configurar rclone como servicio en el host y montar el cubo en el inicio.

En la secuencia de comandos cloud-init, sustituya el valor de las líneas 17, 18 y 19 de ##NAMESPACE##, ##COMPARTMENT_OCID## y ##REGION## por los valores recuperados en la tarea 4.1. También puede actualizar el valor del bloque en la línea 57. Por defecto, se denomina NIM y tiene un directorio denominado llama2-7b-hf.

Este script cloud-init se cargará en el nodo de GPU del cluster de OKE. La primera parte consiste en aumentar el volumen de inicio al conjunto de valores. A continuación, descarga rclone, crea los directorios correctos y crea el archivo de configuración, de la misma manera que lo hemos hecho en la máquina virtual de GPU. Por último, inicia rclone como servicio y monta el cubo en /opt/mnt/model_bucket_oci.

Tarea 6: Despliegue en OKE

La arquitectura de destino al final del despliegue es la que se muestra en la siguiente imagen.

Diagrama de arquitectura

Ahora, reúna todo en OKE.

Cree un cluster de OKE con ligeras adaptaciones. Para obtener más información, consulte Uso de la consola para crear un cluster con valores por defecto en el flujo de trabajo "Creación rápida".

Tarea 7: Despliegue con Helm en OCI Cloud Shell

Para acceder a OCI Cloud Shell, consulte Para acceder a Cloud Shell mediante la consola.

  1. Puede encontrar la configuración de Helm en el archivo oke.zip, donde debe actualizar values.yaml. Cargue el archivo en OCI Cloud Shell y descomprímalo. Para obtener más información, consulte Para cargar un archivo en Cloud Shell mediante el menú.

    unzip oke.zip
    cd oke
    
  2. Revise las credenciales del secreto para extraer la imagen en values.yaml. Para obtener más información, consulte Creación de secretos de extracción de imágenes.

    registry: nvcr.io
    username: $oauthtoken
    password: <YOUR_KEY_FROM_NVIDIA>
    email: someone@host.com
    

Tarea 8: Despliegue de Monitoring

La supervisión consta de pods de Grafana y Prometheus. La configuración proviene de kube-prometheus-stack.

Aquí agregamos un equilibrador de carga público para acceder al panel de control de Grafana desde Internet. Utilice username=admin y password=xxxxxxxxx para conectarse. El indicador serviceMonitorSelectorNilUsesHelmValues es necesario para que Prometheus pueda encontrar las métricas del servidor de inferencia en la versión de ejemplo desplegada.

  1. Despliegue los pods de supervisión.

    helm install example-metrics --set prometheus.prometheusSpec.serviceMonitorSelectorNilUsesHelmValues=false --set grafana.service.type=LoadBalancer prometheus-community/kube-prometheus-stack --debug
    

Nota: El equilibrador de carga por defecto creado con una unidad fija y un ancho de banda de 100 Mbps. Puede cambiar a una unidad flexible y adaptar el ancho de banda según sus límites de OCI en caso de que el ancho de banda sea un cuello de botella. Para obtener más información, consulte Aprovisionamiento de equilibradores de carga de OCI para servicios de Kubernetes de tipo LoadBalancer.

  1. Un ejemplo de panel de control de Grafana está disponible en dashboard-review.json, ubicado en oke.zip. Utilice la función de importación de Grafana para importar y ver este panel de control.

  2. Puede ver la IP pública del panel de control de Grafana ejecutando el siguiente comando.

    $ kubectl get svc
    NAME                                       TYPE           CLUSTER-IP     EXTERNAL-IP       PORT(S)                      AGE
    alertmanager-operated                      ClusterIP      None           <none>            9093/TCP,9094/TCP,9094/UDP   2m33s
    example-metrics-grafana                    LoadBalancer   10.96.82.33    141.145.220.114   80:31005/TCP                 2m38s
    

Tarea 9: Despliegue del servidor de inferencia

  1. Ejecute el siguiente comando para desplegar el servidor de inferencia con la configuración predeterminada.

    cd <directory containing Chart.yaml>
    helm install example . -f values.yaml --debug
    
  2. Utilice kubectl para ver el estado y esperar hasta que se estén ejecutando los pods del servidor de inferencia. El primer tirón puede tardar unos minutos. Una vez creado el contenedor, la carga del modelo también tarda unos minutos. Puede supervisar el pod con el siguiente comando.

    kubectl describe pods <POD_NAME>
    kubectl logs <POD_NAME>
    
  3. Una vez completada la configuración, el contenedor debe estar en ejecución.

    $ kubectl get pods
    NAME                                               READY   STATUS    RESTARTS   AGE
    example-triton-inference-server-5f74b55885-n6lt7   1/1     Running   0          2m21s
    

Tarea 10: Uso del servidor de inferencia Triton en el contenedor NVIDIA NIM

El servidor de inferencia se está ejecutando, puede enviarle solicitudes HTTP o de llamada a procedimiento remoto de Google (gRPC) para realizar la inferencia. Por defecto, el servicio de inferencia se expone con un tipo de servicio LoadBalancer. Utilice lo siguiente para buscar la IP externa para el servidor de inferencia. En este tutorial, se trata de 34.83.9.133.

  1. Obtenga los servicios para obtener la IP pública de su servidor de inferencia.

    $ kubectl get services
    NAME                             TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                        AGE
    ...
    example-triton-inference-server  LoadBalancer   10.18.13.28    34.83.9.133   8000:30249/TCP,8001:30068/TCP,8002:32723/TCP   47m
    
  2. El servidor de inferencia muestra un punto final HTTP en el puerto 8000 y un punto final gRPC en el puerto 8001 y un punto final de métricas de Prometheus en el puerto 8002. Puede utilizar curl para obtener los metadatos del servidor de inferencia del punto final HTTP.

    $ curl 34.83.9.133:8000/v2
    
  3. Desde la máquina cliente, puede enviar una solicitud a la IP pública en el puerto 9999.

    curl -X "POST" 'http://34.83.9.133:9999/v1/completions' -H 'accept: application/json' -H 'Content-Type: application/json' -d '{ "model": "llama2-7b-chat", "prompt": "Can you briefly describe Oracle Cloud?", "max_tokens": 100, "temperature": 0.7, "n": 1, "stream": false, "stop": "string", "frequency_penalty": 0.0 }' | jq ".choices[0].text"
    

    La salida debe ser similar a:

    "\n\nOracle Cloud is a comprehensive cloud computing platform offered by Oracle Corporation. It provides a wide range of cloud services, including Infrastructure as a Service (IaaS), Platform as a Service (PaaS), and Software as a Service (SaaS). Oracle Cloud offers a variety of benefits, including:\n\n1. Scalability: Oracle Cloud allows customers to scale their resources up or down as needed, providing the flexibility to handle changes in business demand."
    

Tarea 11: Limpiar el despliegue

  1. Una vez que haya terminado de utilizar el servidor de inferencia, debe utilizar el timón para suprimir el despliegue.

    $ helm list
    NAME            REVISION  UPDATED                   STATUS    CHART                          APP VERSION   NAMESPACE
    example         1         Wed Feb 27 22:16:55 2019  DEPLOYED  triton-inference-server-1.0.0  1.0           default
    example-metrics	1       	Tue Jan 21 12:24:07 2020	DEPLOYED	prometheus-operator-6.18.0   	 0.32.0     	 default
    
    $ helm uninstall example --debug
    $ helm uninstall example-metrics
    
  2. Para los servicios Prometheus y Grafana, debe suprimir de forma explícita las CRD. Para obtener más información, consulte Desinstalación del gráfico de Helm.

    $ kubectl delete crd alertmanagerconfigs.monitoring.coreos.com alertmanagers.monitoring.coreos.com podmonitors.monitoring.coreos.com probes.monitoring.coreos.com prometheuses.monitoring.coreos.com prometheusrules.monitoring.coreos.com servicemonitors.monitoring.coreos.com thanosrulers.monitoring.coreos.com
    
  3. También puede suprimir el cubo de OCI Object Storage creado para contener el repositorio de modelos.

    $ oci os bucket delete --bucket-name NIM --empty
    

Agradecimientos

Más recursos de aprendizaje

Explore otros laboratorios en docs.oracle.com/learn o acceda a más contenido de aprendizaje gratuito en el canal YouTube de Oracle Learning. Además, visite education.oracle.com/learning-explorer para convertirse en Oracle Learning Explorer.

Para obtener documentación sobre el producto, visite Oracle Help Center.