주:

OCI Object Storage에 저장된 모델 저장소를 사용하여 추론을 위해 OKE에 NVIDIA NIM 배포

소개

이 사용지침서에서는 NVIDIA TensorRT-LLM 백엔드와 NVIDIA Triton 추론 서버가 있는 OKE(Oracle Cloud Infrastructure Container Engine for Kubernetes)에 NVIDIA NIM을 배포하여 Kubernetes 아키텍처에서 LLM(Large Language Models)을 제공하는 방법을 보여줍니다. 사용된 모델은 GPU A10에서 Llama2-7B-chat입니다. 확장성을 위해 OCI Object Storage의 버킷에서 모델 저장소를 호스팅하고 있습니다.

주: 이 자습서의 모든 테스트는 nemollm-inference-ms:24.02.rc4를 사용하여 LLM용 NVIDIA NIM의 초기 액세스 버전으로 릴리스되었습니다.

목표

필요 조건

작업 1: OCI 컴퓨트에 GPU 인스턴스 생성

  1. OCI 콘솔에 로그인한 후 OCI 메뉴, 컴퓨트, 인스턴스로 이동하고 인스턴스 생성을 누릅니다.

  2. Oracle Cloud Marketplace 이미지 NVIDIA GPU 클라우드 머신 이미지와 부팅 볼륨이 250GB인 VM.GPU.A10.1을 선택합니다. 자세한 내용은 Oracle Cloud Infrastructure에서 NVIDIA GPU 클라우드 사용을 참조하십시오.

  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 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 Object Storage에 NIM이라는 버킷을 생성합니다. 자세한 내용은 Object Storage 버킷 생성을 참조하십시오.

  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 Object Storage 버킷으로 익스포트합니다.

    모델 저장소는 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 Object Storage 버킷에 업로드됩니다.

주: 옵션 매개변수 --model-repository는 현재 컨테이너에서 하드코딩되어 있으므로 버킷을 시작할 때 간단히 가리킬 수 없습니다. 한 가지 옵션은 컨테이너 내에서 Python 스크립트를 적용하는 것이지만 sudo 권한이 필요합니다. 다른 하나는 버킷을 시스템에 파일 시스템으로 직접 마운트하는 것입니다. 이 자습서에서는 rclone을 사용하여 두번째 방법을 선택합니다. fuse3jq가 시스템에 설치되어 있는지 확인합니다. 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. 다른 터미널 window에서 ls $HOME/test_directory/model_bucket_oci가 버킷의 내용을 반환하는지 확인할 수 있습니다.

  6. 다른 터미널 window에서 경로를 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분 후 추론 서버를 사용할 준비가 되어야 합니다. 다른 터미널 window에서 다음 요청을 실행할 수 있습니다.

    주: 로컬 시스템에서 실행하려면 공용 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에서 사용하기가 복잡합니다(2015년의 기능 요청인 FUSE 볼륨은 2024년 3월 현재 매우 활성 상태임). 이 자습서에서는 호스트에서 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 클러스터를 만듭니다. 자세한 내용은 콘솔을 사용하여 '빠른 생성' 워크플로우의 기본 설정으로 클러스터 생성을 참조하십시오.

작업 7: OCI Cloud Shell에서 Helm을 사용하여 배치

OCI Cloud Shell에 액세스하려면 콘솔을 통해 Cloud Shell에 액세스하려면을 참조하십시오.

  1. Helm 구성은 oke.zip 아카이브에서 찾을 수 있습니다. 여기서 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 Pod로 구성됩니다. 구성은 kube-prometheus-stack에서 제공됩니다.

여기서는 공용 로드 밸런서를 추가하여 인터넷에서 Grafana 대시보드에 연결합니다. username=adminpassword=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를 사용하여 상태를 확인하고 추론 서버 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 RPC(원격 프로시저 호출) 요청을 전송할 수 있습니다. 기본적으로 추론 서비스는 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 Object Storage 버킷을 삭제할 수도 있습니다.

    $ 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를 참조하십시오.