ノート:

OCI Object Storageに格納されたモデル・リポジトリとの推論のためにOKEにNVIDIA NIMをデプロイ

イントロダクション

このチュートリアルでは、NVIDIA TensorRT-LLMバックエンドおよびNVIDIA Triton推論サーバーを使用してOracle Cloud Infrastructure Container Engine for Kubernetes (OKE)にNVIDIA NIMをデプロイし、Kubernetesアーキテクチャで大規模言語モデル(LLM)を提供する方法を示します。使用されるモデルは、GPU A10のLlama2-7B-chatです。スケーラビリティのために、OCI Object Storageのバケットでモデル・リポジトリをホストしています。

ノート:このチュートリアルのすべてのテストは、nemollm-inference-ms:24.02.rc4を使用したLLMのNVIDIA NIMの早期アクセス・バージョンでリリースされています。

目的

前提条件

タスク1: OCI ComputeでのGPUインスタンスの作成

  1. OCIコンソールにログインし、「OCIメニュー」「コンピュート」「インスタンス」の順に移動し、「インスタンスの作成」をクリックします。

  2. Oracle Cloud MarketplaceイメージのNVIDIA GPU Cloudマシン・イメージおよびブート・ボリュームが250GBのVM.GPU.A10.1を選択します。詳細は、Oracle Cloud InfrastructureでのNVIDIA GPU Cloudの使用を参照してください。

  3. マシンが起動したら、秘密キーとマシン・パブリックIPを使用してマシンに接続します。

    ssh -i <private_key> ubuntu@<public_ip>
    
  4. ブート・ボリュームの領域が増加していることを確認します。

    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
    

タスク2: NVIDIAドライバの更新(オプション)

ドライバとCUDAバージョン間の互換性マトリックスを使用して、NVIDIAが提供するガイダンスに基づいて、ドライバを最新バージョンに更新することをお薦めします。詳細は、CUDA Compatibilityおよび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

nvidia-container-toolkitがあることを確認します。

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

新しいバージョンを確認するには、次のコマンドを実行します。

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

タスク3: モデル・レジストリの準備

事前構築済モデルを使用できます。ただし、A10 GPUでLlama2-7B-chatを実行することを選択します。記述時には、この選択肢を使用できないため、モデル・リポジトリを自分で構築する必要があります。

  1. OCIオブジェクト・ストレージにNIMという名前のバケットを作成します。詳細は、オブジェクト・ストレージ・バケットの作成を参照してください。

  2. ターミナル・ウィンドウに移動し、ユーザー名とパスワードを使用してNVIDIAコンテナ・レジストリにログインし、コンテナをプルします。次のコマンドを実行します

    docker login nvcr.io
    docker pull nvcr.io/ohlfw0olaadg/ea-participants/nemollm-inference-ms:24.02.rc4
    
  3. 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. モデル構成を作成します。

    model_config.yamlファイルをコピーし、モデルストアをホストするディレクトリを作成します。ここでは、モデル・リポジトリ・ジェネレータ・コマンドが出力を格納します。

    mkdir model-store
    chmod -R 777 model-store
    
  5. モデル・リポジトリ・ジェネレータ・コマンドを実行します。

    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. モデル・リポジトリをOCIオブジェクト・ストレージ・バケットにエクスポートします。

    モデル・リポジトリは、ディレクトリmodel-storeにあります。Oracle Cloud Infrastructureコマンドライン・インタフェース(OCI CLI)を使用して、リージョン内のいずれかのバケットへの一括アップロードを実行できます。このチュートリアルでは、バケットはNIMで、モデル・ストアをNIM/llama2-7b-hfにアップロードします(異なるモデル構成を同じバケットにアップロードする場合)。

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

タスク4: 仮想マシンへのリクエストの送信(IaaS実行)

これで、モデル・リポジトリが1つのOCI Object Storageバケットにアップロードされました。

ノート:オプション・パラメータ--model-repositoryは現在コンテナでハードコードされており、起動時にバケットを指すことはできません。1つのオプションは、コンテナ内のPythonスクリプトを適応させることですが、sudo権限が必要です。もう1つは、バケットをファイル・システムとしてマシンに直接マウントすることです。このチュートリアルでは、rcloneで2番目の方法を選択します。fuse3およびjqがマシンにインストールされていることを確認します。Ubuntuでは、sudo apt install fuse3 jqを実行できます。

  1. OCIコンソールからフェッチするか、コンピュート・インスタンスから次のコマンドを実行して、ネームスペースコンパートメントOCIDおよびリージョンを取得します。

    #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をダウンロードしてインストールします。

    curl https://rclone.org/install.sh | sudo bash
    
  3. rclone構成ファイルを準備します。必ず、##NAMESPACE## ##COMPARTMENT_OCID## ##REGION##を値で更新してください。

    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. 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. 別のターミナル・ウィンドウで、ls $HOME/test_directory/model_bucket_ociがバケットの内容を返すことを確認できます。

  6. 別のターミナル・ウィンドウで、model-storeへのパスを引数として渡すコンテナを起動します。

    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. 3分後、推論サーバーは動作する準備ができているはずです。別の端末ウィンドウで、次のリクエストを実行できます。

    ノート:ローカル・マシンから実行する場合は、パブリックIPを使用し、マシン・レベルとサブネット・レベルの両方でポート9999を開く必要があります。

    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"
    

タスク5: cloud-initスクリプトの更新

ノート:理想的には、Kubernetesでrcloneを使用するより簡単な方法は、推論サーバーを起動する前にrclone containerをサイドカーとして使用することです。これはDockerを使用してローカルで正常に動作しますが、FUSEを使用するには--deviceオプションが必要なため、この機能のサポートが不足しているため、Kubernetesでの使用が複雑になります(2024年3月現在、2015年からの機能リクエストであるFUSEボリューム)。このチュートリアルでは、ホストにrcloneをサービスとして設定し、起動時にバケットをマウントします。

cloud-initスクリプトで、##NAMESPACE####COMPARTMENT_OCID##および##REGION##行17、18および19の値を、タスク4.1で取得した値に置き換えます。57行目でバケットの値を更新することもできます。デフォルトでは、NIMと呼ばれ、llama2-7b-hfというディレクトリがあります。

このcloud-initスクリプトは、OKEクラスタのGPUノードにアップロードされます。1つ目の部分は、ブート・ボリュームを値セットに増やすことです。次に、rcloneをダウンロードし、正しいディレクトリを作成し、GPU VMで実行したのと同じ方法で構成ファイルを作成します。最後に、rcloneをサービスとして起動し、バケットを/opt/mnt/model_bucket_ociにマウントします。

タスク6: OKEへのデプロイ

デプロイメントの最後にあるターゲット・アーキテクチャは、次の図のようになります。

アーキテクチャの図

全てをOKEにまとめます。

わずかな適応でOKEクラスタを作成します。詳細は、コンソールを使用した、クイック作成ワークフローでのデフォルト設定でのクラスタの作成を参照してください。

タスク7: OCI Cloud ShellでのHelmを使用したデプロイ

OCIクラウド・シェルにアクセスするには、コンソールを使用してクラウド・シェルにアクセスするにはを参照してください。

  1. Helm構成は、values.yamlを更新する必要があるアーカイブoke.zipにあります。アーカイブをOCI Cloud Shellにアップロードし、解凍します。詳細は、メニューを使用したクラウド・シェルへのファイルのアップロードを参照してください。

    unzip oke.zip
    cd oke
    
  2. values.yamlでイメージをプルするシークレットの資格証明を確認します。詳細は、「イメージ・プル・シークレットの作成」を参照してください。

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

タスク8: モニタリングのデプロイ

監視は、GrafanaとPrometheusポッドで構成されます。構成は、kube-prometheus-stackから取得されます。

ここでは、インターネットからGrafanaダッシュボードにアクセスするためのパブリック・ロード・バランサを追加します。username=adminおよびpassword=xxxxxxxxxを使用してログインします。Prometheusがデプロイされたサンプル・リリースで推論サーバー・メトリックを検索できるようにするには、serviceMonitorSelectorNilUsesHelmValuesフラグが必要です。

  1. モニタリング・ポッドをデプロイします。

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

ノート:固定シェイプおよび帯域幅100Mbpsで作成されたデフォルトのロード・バランサ。帯域幅がボトルネックになっている場合は、柔軟なシェイプに切り替え、OCIの制限に従って帯域幅を適応させることができます。詳細は、タイプLoadBalancerのKubernetesサービスのOCIロード・バランサのプロビジョニングを参照してください。

  1. Grafanaダッシュボードの例は、oke.zipにあるdashboard-review.jsonにあります。Grafanaのインポート機能を使用して、このダッシュボードをインポートおよび表示します。

  2. 次のコマンドを実行すると、GrafanaダッシュボードのパブリックIPを確認できます。

    $ 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
    

タスク9: 推論サーバーのデプロイ

  1. 次のコマンドを実行して、デフォルト構成を使用して推論サーバーをデプロイします。

    cd <directory containing Chart.yaml>
    helm install example . -f values.yaml --debug
    
  2. kubectlを使用してステータスを確認し、推論サーバー・ポッドが実行されるまで待機します。最初のプルには数分かかる場合があります。コンテナが作成されると、モデルのロードにも数分かかります。次のコマンドを使用して、ポッドを監視できます。

    kubectl describe pods <POD_NAME>
    kubectl logs <POD_NAME>
    
  3. 設定が完了したら、コンテナが実行されている必要があります。

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

タスク10: NVIDIA NIMコンテナでのTriton Inference Serverの使用

推論サーバーが実行中です。推論を実行するために、HTTPまたはGoogleリモート・プロシージャ・コール(gRPC)リクエストを送信できます。デフォルトでは、推論サービスはLoadBalancerサービス・タイプで公開されます。推論サーバーの外部IPを検索するには、次を使用します。このチュートリアルでは、34.83.9.133です。

  1. 推論サーバーのパブリックIPを取得するサービスを取得します。

    $ 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. 推論サーバーは、ポート8000のHTTPエンドポイント、ポート8001のgRPCエンドポイント、およびポート8002のPrometheusメトリック・エンドポイントを公開します。curlを使用して、HTTPエンドポイントから推論サーバーのメタデータを取得できます。

    $ curl 34.83.9.133:8000/v2
    
  3. クライアント・マシンから、ポート9999のパブリックIPにリクエストを送信できます。

    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"
    

    出力は次のようになります:

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

タスク11: デプロイメントのクリーン・アップ

  1. 推論サーバーの使用が終了したら、helmを使用してデプロイメントを削除する必要があります。

    $ 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. PrometheusおよびGrafanaサービスの場合、CRDを明示的に削除する必要があります。詳細は、「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. モデル・リポジトリを保持するために作成されたOCIオブジェクト・ストレージ・バケットを削除することもできます。

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

承認

その他の学習リソース

docs.oracle.com/learnの他のラボをご覧いただくか、Oracle Learning YouTubeチャネルで無料のラーニング・コンテンツにアクセスしてください。また、education.oracle.com/learning-explorerにアクセスして、Oracle Learning Explorerになります。

製品ドキュメントは、Oracle Help Centerを参照してください。