Hinweis:

NVIDIA NIM auf OKE für Inferenz mit dem auf OCI Object Storage gespeicherten Modell-Repository bereitstellen

Einführung

Dieses Tutorial zeigt, wie Sie NVIDIA NIM auf Oracle Cloud Infrastructure Container Engine for Kubernetes (OKE) mit NVIDIA TensorRT-LLM-Backend und NVIDIA Triton-Inferenzserver bereitstellen, um Large Language Models (LLMs) in einer Kubernetes-Architektur zu bedienen. Das verwendete Modell ist Llama2-7B-chat auf einer GPU A10. Zur Skalierbarkeit hosten wir das Modell-Repository in einem Bucket in OCI Object Storage.

Hinweis: Alle Tests dieses Tutorials wurden mit einer frühen Zugriffsversion von NVIDIA NIM für LLMs mit nemollm-inference-ms:24.02.rc4 veröffentlicht.

Ziele

Voraussetzungen

Aufgabe 1: GPU-Instanz in OCI Compute erstellen

  1. Melden Sie sich bei der OCI-Konsole an, navigieren Sie zum OCI-Menü, Compute und Instanzen, und klicken Sie auf Instanz erstellen.

  2. Wählen Sie VM.GPU.A10.1 mit dem NVIDIA GPU Cloud-Rechnerimage des Oracle Cloud Marketplace-Images und einem Boot-Volume von 250 GB aus. Weitere Informationen finden Sie unter NVIDIA GPU Cloud mit Oracle Cloud Infrastructure verwenden.

  3. Stellen Sie nach dem Hochfahren des Rechners eine Verbindung mit Ihrem Private Key und der öffentlichen IP des Rechners her.

    ssh -i <private_key> ubuntu@<public_ip>
    
  4. Stellen Sie sicher, dass das Boot-Volume mehr Speicherplatz hat.

    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
    

Aufgabe 2: NVIDIA-Treiber aktualisieren (Optional)

Es wird empfohlen, Ihre Treiber auf die neueste Version basierend auf der Anleitung von NVIDIA mit der Kompatibilitätsmatrix zwischen den Treibern und Ihrer CUDA-Version zu aktualisieren. Weitere Informationen finden Sie unter CUDA-Kompatibilität und 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

Stellen Sie sicher, dass Sie nvidia-container-toolkit haben.

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

Führen Sie den folgenden Befehl aus, um die neue Version zu prüfen.

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

Aufgabe 3: Modell-Registry vorbereiten

Sie können vorgefertigte Modelle verwenden. Sie können Llama2-7B-chat jedoch auf einer A10-GPU ausführen. Zum Zeitpunkt des Schreibens ist diese Option nicht verfügbar. Daher müssen wir das Modell-Repository selbst erstellen.

  1. Erstellen Sie einen Bucket mit dem Namen NIM in OCI Object Storage. Weitere Informationen finden Sie unter Objektspeicher-Bucket erstellen.

  2. Gehen Sie zum Terminalfenster, melden Sie sich mit Ihrem Benutzernamen und Kennwort bei der NVIDIA-Containerregistrierung an, und ziehen Sie den Container. Führen Sie den folgenden Befehl aus.

    docker login nvcr.io
    docker pull nvcr.io/ohlfw0olaadg/ea-participants/nemollm-inference-ms:24.02.rc4
    
  3. Klonen Sie das Modell 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. Erstellen Sie die Modellkonfiguration.

    Kopieren Sie die Datei model_config.yaml, und erstellen Sie das Verzeichnis zum Hosten des Modellspeichers. Hier speichert der Befehl Model Repository Generator die Ausgabe.

    mkdir model-store
    chmod -R 777 model-store
    
  5. Führen Sie den Befehl "model Repository Generator" aus.

    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. Exportieren Sie das Modell-Repository in einen OCI Object Storage-Bucket.

    Das Modell-Repository befindet sich im Verzeichnis model-store. Mit der Oracle Cloud Infrastructure-Befehlszeilenschnittstelle (OCI-CLI) können Sie einen Bulkupload in einen Ihrer Buckets in der Region ausführen. Für dieses Tutorial lautet der Bucket NIM, in den der Modellspeicher in NIM/llama2-7b-hf hochgeladen werden soll (wenn wir eine andere Modellkonfiguration in denselben Bucket hochladen).

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

Aufgabe 4: Anforderung an die virtuelle Maschine weiterleiten (IaaS-Ausführung)

Jetzt wird das Modell-Repository in einen OCI Object Storage-Bucket hochgeladen.

Hinweis: Der Optionsparameter --model-repository ist derzeit hartcodiert im Container. Sie können beim Starten nicht einfach auf den Bucket verweisen. Eine Möglichkeit besteht darin, das Python-Skript im Container anzupassen, aber wir benötigen sudo-Berechtigung. Die andere Möglichkeit besteht darin, den Bucket als Dateisystem direkt auf dem Rechner zu mounten. Für dieses Tutorial wird die zweite Methode mit rclone ausgewählt. Stellen Sie sicher, dass fuse3 und jq auf dem Rechner installiert sind. Auf Ubuntu können Sie sudo apt install fuse3 jq ausführen.

  1. Rufen Sie den Namespace, die Compartment-OCID und die Region ab, indem Sie sie entweder aus der OCI-Konsole abrufen oder die folgenden Befehle aus der Compute-Instanz ausführen.

    #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. rclone herunterladen und installieren.

    curl https://rclone.org/install.sh | sudo bash
    
  3. Bereiten Sie die rclone-Konfigurationsdatei vor. Aktualisieren Sie ##NAMESPACE## ##COMPARTMENT_OCID## ##REGION## mit den Werten.

    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. Mounten Sie den Bucket mit 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. In einem anderen Terminalfenster können Sie prüfen, ob ls $HOME/test_directory/model_bucket_oci den Inhalt des Buckets zurückgibt.

  6. Starten Sie in einem anderen Terminalfenster den Container, der den Pfad zur model-store als Argument übergibt.

    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. Nach 3 Minuten sollte der Inferenzserver bereit sein, zu bedienen. In einem anderen Terminalfenster können Sie die folgende Anforderung ausführen.

    Hinweis: Wenn Sie sie auf dem lokalen Rechner ausführen möchten, müssen Sie die öffentliche IP verwenden und den Port 9999 sowohl auf Rechner- als auch auf Subnetzebene öffnen.

    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"
    

Aufgabe 5: Skript cloud-init aktualisieren

Hinweis: Eine sauberere Möglichkeit, Rclone in Kubernetes zu verwenden, besteht darin, den Rclone-Container als Sidecar zu verwenden, bevor Sie den Inferenzserver starten. Dies funktioniert lokal mit Docker gut, aber da die Option --device zur Verwendung von FUSE erforderlich ist, ist die Verwendung mit Kubernetes aufgrund der fehlenden Unterstützung für dieses Feature kompliziert (FUSE-Volumes, eine Featureanforderung aus dem Jahr 2015, die ab März 2024 noch sehr aktiv ist). In diesem Tutorial richten Sie rclone als Service auf dem Host ein und mounten den Bucket beim Start.

Ersetzen Sie im cloud-init-Skript den Wert der Zeilen 17, 18 und 19 der Zeilen ##NAMESPACE##, ##COMPARTMENT_OCID## und ##REGION## durch die in Aufgabe 4.1 abgerufenen Werte. Sie können auch den Wert des Zeitraums in Zeile 57 aktualisieren. Standardmäßig lautet der Name NIM und enthält ein Verzeichnis namens llama2-7b-hf.

Dieses cloud-init-Skript wird auf den GPU-Knoten in Ihrem OKE-Cluster hochgeladen. Der erste Teil besteht darin, das Boot-Volume auf den Werteset zu erhöhen. Dann lädt er rclone herunter, erstellt die richtigen Verzeichnisse und erstellt die Konfigurationsdatei, wie wir es auf der GPU-VM getan haben. Schließlich wird rclone als Service gestartet und der Bucket in /opt/mnt/model_bucket_oci gemountet.

Aufgabe 6: Deployment auf OKE

Die Zielarchitektur am Ende des Deployments wird im folgenden Bild dargestellt.

Architekturdiagramm

Jetzt alles in OKE zusammenstellen.

Erstellen Sie ein OKE-Cluster mit leichten Anpassungen. Weitere Informationen finden Sie unter Cluster mit Standardeinstellungen im Workflow "Schnellerstellung" mit der Konsole erstellen.

Aufgabe 7: Mit Helm in OCI Cloud Shell bereitstellen

Informationen zum Zugriff auf OCI Cloud Shell finden Sie unter So rufen Sie Cloud Shell über die Konsole auf.

  1. Sie finden die Helm-Konfiguration im Archiv oke.zip, in dem Sie values.yaml aktualisieren müssen. Laden Sie das Archiv in die OCI Cloud Shell hoch, und dekomprimieren Sie es. Weitere Informationen finden Sie unter So laden Sie eine Datei über das Menü in Cloud Shell hoch.

    unzip oke.zip
    cd oke
    
  2. Prüfen Sie Ihre Zugangsdaten für das Secret, um das Image in values.yaml abzurufen. Weitere Informationen finden Sie unter Image Pull-Secrets erstellen.

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

Aufgabe 8: Monitoring bereitstellen

Die Überwachung besteht aus Grafana- und Prometheus-Pods. Die Konfiguration stammt aus dem kube-prometheus-stack.

Hier fügen wir einen öffentlichen Load Balancer hinzu, um das Grafana-Dashboard über das Internet zu erreichen. Verwenden Sie username=admin und password=xxxxxxxxx, um sich anzumelden. Das Flag serviceMonitorSelectorNilUsesHelmValues ist erforderlich, damit Prometheus die Inferenzservermetriken im bereitgestellten Beispielrelease finden kann.

  1. Stellen Sie die Überwachungspods bereit.

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

Hinweis: Der Standard-Load Balancer, der mit einer festen Ausprägung und einer Bandbreite von 100 Mbit/s erstellt wurde. Sie können zu einer flexiblen Ausprägung wechseln und die Bandbreite entsprechend Ihren OCI-Limits anpassen, falls die Bandbreite ein Engpass ist. Weitere Informationen finden Sie unter OCI Load Balancer für Kubernetes-Services vom Typ LoadBalancer bereitstellen.

  1. Ein Beispiel-Grafana-Dashboard ist in dashboard-review.json in oke.zip verfügbar. Verwenden Sie die Importfunktion in Grafana, um dieses Dashboard zu importieren und anzuzeigen.

  2. Sie können die öffentliche IP des Grafana-Dashboards anzeigen, indem Sie den folgenden Befehl ausführen.

    $ 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
    

Aufgabe 9: Inferenzserver bereitstellen

  1. Führen Sie den folgenden Befehl aus, um den Inferenzserver mit der Standardkonfiguration bereitzustellen.

    cd <directory containing Chart.yaml>
    helm install example . -f values.yaml --debug
    
  2. Verwenden Sie kubectl, um den Status anzuzeigen und zu warten, bis die Inferenzserverpods ausgeführt werden. Der erste Zug kann einige Minuten dauern. Nachdem der Container erstellt wurde, dauert das Laden des Modells auch einige Minuten. Sie können den Pod mit folgendem Befehl überwachen.

    kubectl describe pods <POD_NAME>
    kubectl logs <POD_NAME>
    
  3. Sobald die Einrichtung abgeschlossen ist, sollte der Container ausgeführt werden.

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

Aufgabe 10: Verwenden Sie Triton Inference Server auf Ihrem NVIDIA NIM-Container

Der Inferenzserver wird ausgeführt. Sie können HTTP- oder Google Remote Procedure Call-(gRPC-)Anforderungen zur Inferenzierung an ihn senden. Standardmäßig wird der Inferenzierungsservice mit dem Servicetyp LoadBalancer angegeben. Mit dem folgenden Befehl können Sie die externe IP für den Inferenzserver suchen. In diesem Tutorial ist es 34.83.9.133.

  1. Rufen Sie die Services ab, um die öffentliche IP Ihres Inferenzservers abzurufen.

    $ 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. Der Inferenzserver stellt einen HTTP-Endpunkt auf Port 8000 und einen gRPC-Endpunkt auf Port 8001 und einen Prometheus-Metrikendpunkt auf Port 8002 bereit. Mit curl können Sie die Metadaten des Inferenzservers vom HTTP-Endpunkt abrufen.

    $ curl 34.83.9.133:8000/v2
    
  3. Von Ihrem Clientrechner können Sie eine Anforderung an die öffentliche IP auf Port 9999 senden.

    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"
    

    Die Ausgabe sollte folgendermaßen aussehen:

    "\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."
    

Aufgabe 11: Deployment bereinigen

  1. Nachdem Sie den Inferenzserver verwendet haben, sollten Sie das Deployment mit helm löschen.

    $ 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. Bei den Prometheus- und Grafana-Services sollten Sie CRDs explizit löschen. Weitere Informationen finden Sie unter Helm-Diagramm deinstallieren.

    $ 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. Sie können auch den OCI Object Storage-Bucket löschen, der für das Modell-Repository erstellt wurde.

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

Danksagungen

Weitere Lernressourcen

Lernen Sie andere Übungen auf docs.oracle.com/learn kennen, oder greifen Sie auf weitere kostenlose Lerninhalte im Oracle Learning YouTube Channel zu. Außerdem können Sie education.oracle.com/learning-explorer besuchen, um Oracle Learning Explorer zu werden.

Die Produktdokumentation finden Sie im Oracle Help Center.