注意:

在 OKE 上部署 NVIDIA NIM,以便与存储在 OCI 对象存储上的模型资料档案库推断

简介

本教程演示如何在 Oracle Cloud Infrastructure Container Engine for Kubernetes (OKE) 上部署 NVIDIA NIM 以及 NVIDIA TensorRT-LLM 后端和 NVIDIA Triton 推断服务器,以在 Kubernetes 体系结构中为大型语言模型 (Large Language Models,LLM) 服务。使用的模型是 GPU A10 上的 Llama2-7B-chat。为了实现可扩展性,我们将在 OCI 对象存储中的存储桶上托管模型存储库。

注:本教程的所有测试均已发布,其中包含 NVIDIA NIM 的早期访问版本,适用于 LLM 的 nemollm-inference-ms:24.02.rc4

目标

先决条件

任务 1:在 OCI 计算中创建 GPU 实例

  1. 登录到 OCI 控制台,导航到 OCI 菜单计算实例,然后单击创建实例

  2. 选择 VM.GPU.A10.1,其中包含 Oracle Cloud Marketplace 映像 NVIDIA GPU 云计算机映像和 250GB 引导卷。有关详细信息,请参阅将 NVIDIA GPU 云与 Oracle Cloud Infrastructure 结合使用

  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 驱动程序(可选

建议根据 NVIDIA 提供的指南,将驱动程序更新到最新版本,并在驱动程序与 CUDA 版本之间提供兼容性矩阵。有关更多信息,请参见 CUDA CompatibilityCUDA 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. 运行 model repository generator 命令。

    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 执行)

现在,模型存储库已上载到一个 OCI 对象存储桶。

注:选项参数 --model-repository 当前已在容器中硬编码,启动时不能简单地指向存储桶。一个选项是调整容器中的 Python 脚本,但是我们需要 sudo 特权。另一种方法是直接将存储桶作为文件系统挂载到计算机上。对于本教程,我们使用 rclone 选择第二个方法。确保计算机上安装了 fuse3jq。在 Ubuntu 上,您可以运行 sudo apt install fuse3 jq

  1. 获取名称空间区间 OCID区域,从 OCI 控制台提取它们,或者从计算实例运行以下命令。

    #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,则必须在计算机和子网级别使用公共 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 作为 sidecar。这在本地使用 Docker 正常工作,但由于需要使用 --device 选项才能使用 fuse,这使得与 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 节点上。第一部分包括将引导卷增大到值集。然后,它下载 rclone,创建正确的目录并创建配置文件,就像我们在 GPU VM 上所做的那样。最后,它将 rclone 作为服务启动,并将存储桶挂载到 /opt/mnt/model_bucket_oci

任务 6:在 OKE 上部署

部署结束时的目标体系结构如下图所示。

体系结构图

现在,将所有内容放到 OKE 中。

创建轻微调整的 OKE 群集。有关更多信息,请参见 Using the Console to create a Cluster with Default Settings in the ‘ Quick Create ’ workflow

任务 7:在 OCI Cloud Shell 中使用 Helm 进行部署

要访问 OCI Cloud Shell,请参阅通过控制台访问 Cloud Shell

  1. 您可以在归档文件 oke.zip 中找到 Helm 配置,您需要在其中更新 values.yaml。将档案上载到 OCI Cloud Shell 并解压缩它。有关详细信息,请参阅使用菜单将文件上载到 Cloud Shell

    unzip oke.zip
    cd oke
    
  2. 查看身份证明以获取用于在 values.yaml 中拉取映像的密钥。有关更多信息,请参见 Creating Image Pull Secrets

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

任务 8:部署监视

监控由 Grafana 和 Prometheus pods 组成。配置来自 kube-prometheus-stack

在此处,我们添加一个公共负载平衡器,以便从 Internet 访问 Grafana 仪表盘。使用 username=adminpassword=xxxxxxxxx 登录。需要 serviceMonitorSelectorNilUsesHelmValues 标志,以便 Prometheus 可以在部署的示例发行版中查找推断服务器度量。

  1. 部署监视云池。

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

注:使用固定配置和带宽 100Mbps 创建的默认负载平衡器。您可以切换到灵活的配置,并根据 OCI 限制调整带宽,以防带宽出现瓶颈。有关更多信息,请参见 Provisioning OCI Load Balancers for Kubernetes Services of Type LoadBalancer

  1. dashboard-review.json 中提供了 oke.zip 中的示例 Grafana 仪表盘。使用 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 查看状态并等待推断服务器 pod 运行。第一次拉动可能需要几分钟。创建容器后,加载模型还需要几分钟时间。可以使用以下命令监视 pod。

    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 推断服务器

推断服务器正在运行,您可以向其发送 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。有关更多信息,请参见 Uninstall Helm Chart

    $ 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 帮助中心