NVIDIA Triton 서버는 다양한 프레임워크의 AI 모델에 대해 AI Inference를 지원하는 오픈 소스이다.
대부분의 Train/Inference 프레임워크를 모두 지원하며 Dynamic batching, Parallel Processing, Model Ensemble 등 다양한 기능을 지원하여 고성능 추론을 가능하게 만들어준다.
또한 DevOps, MLOps를 위한 설계가 되어있어 Kubernets에 통합하여 모니터링과 확장이 용이하다는 장점이 있다.
거두절미하고 바로 쿠버네티스 환경에서 triton 서버를 띄우기 위한 환경설정을 시작하자.
GPU-Operator 설치
먼저 쿠버네티스가 NVIDIA GPU 리소스에 접근할 수 있도록 gpu-operator를 설치해야 한다.
gpu-operator는 자동으로 NVIDIA GPU를 자동으로 provisioning 해준다.
gpu-operator의 구성요소는 다음과 같다.
- NVIDIA drivers + CUDA
- GPU를 위한 Kubernetes device plugin
- 컨테이너 내부에서 GPU를 사용할 수 있게 해주는 NVIDIA Container Toolkit
- 자동으로 node labeling을 해주는 GPU Feature Discovery(GFD)
- 클러스터에서 GPU를 모니터링 해주는 DCGM
Prerequisites
먼저 GPU-operator 설치를 위해 kubectl과 helm이 필요하다. 만약 helm이 설치가 되지 않았다면 아래 명령어로 설치를 진행한다.
# helm 설치
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 \
&& chmod 700 get_helm.sh \
&& ./get_helm.sh
또한 node는 container engine으로 cri-o나 containerd를 사용해야한다.
$ k get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
my-node Ready control-plane 240d v1.29.1 <서버 IP 주소> <none> Ubuntu 20.04.6 LTS 5.15.0-72-generic containerd://1.6.28
이후 gpu-operator가 사용할 네임스페이스를 생성해주고, 만약 클러스터에 파드 조작 보안을 위한 Pod Security Admission 설정이 되어있다면 생성한 네임스페이스에 권한을 부여하자.
kubectl create ns gpu-operator
kubectl label --overwrite ns gpu-operator pod-security.kubernetes.io/enforce=privileged
여기까지 하면 gpu-operator 설치를 위한 준비가 끝났다.
Procedure
설치를 위해 helm에서 gpu-operator repo를 가져오고 helm install로 설치를 진행하면 된다.
이 때 다른 버전을 설치하고 싶다면 --version을 명시해주면 되고, 다른 상세 옵션을 명시하면 된다.
상세한 차트 옵션은 여기를 참고하면 된다.
$ helm repo add nvidia https://helm.ngc.nvidia.com/nvidia \
&& helm repo update
$ helm install --wait --generate-name \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v24.9.0
--set <option-name>=<option-value>
몇가지 확인해야 할 옵션은 다음과 같다.
- driver.enabled: NVIDIA driver를 설치할 것인지. 만약 이미 설치된 driver가 있다면 false로 설정 (기본값: true)
- driver.version: 설치하는 gpu-operator 버전에 dependency가 존재한다. 따라서 내 gpu를 확인하고 맞는 driver를 설치해야할 수 있다.
- nfd.enabled: node feature discovery가 이미 클러스터에서 기동중이라면 false로 설정
- sandboxWorkloads.defaultWorkload: 클러스터의 workload 타입을 지정한다. 만약 virtual machine을 이용한다면 vm-passthrough 혹은 vm-vgpu로 설정. (기본값: container)
- toolkit.enabled: 만약 NVIDIA Container Toolkit을 이미 설치했다면 false로 설정 (기본값: true)
만약 드라이버와 툴킷이 이미 설치되었다면, 다음과 같은 설치 명령어를 사용할 수 있다.
$ helm install --wait --generate-name \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--version=v24.9.0 \
--set driver.enabled=false \
--set toolkit.enabled=false
만약 멀티 노드 클러스터로 kubernetes를 구성하고 있다면 gpu-operator는 모든 GPU worker node에 설치된다.
마찬가지로 gpu driver 또한 모든 GPU worker node에 설치된다.
이를 선택적으로 구성하고 싶다면 node label을 변경해주어야 한다.
# gpu-operator 설치 방지
kubectl label nodes $NODE nvidia.com/gpu.deploy.operands=false
# gpu drvier 설치 방지
kubectl label nodes $NODE nvidia.com/gpu.deploy.driver=false
설치가 완료되면 다음과 같이 pod 상태를 확인할 수 있다.
$ k get pod -n gpu-operator
NAME READY STATUS RESTARTS AGE
gpu-feature-discovery-6p5nb 2/2 Running 0 3d22h
gpu-operator-574c687b59-zxmh7 1/1 Running 2 (17h ago) 240d
gpu-operator-node-feature-discovery-master-d8597d549-r87sh 1/1 Running 1 240d
gpu-operator-node-feature-discovery-worker-qrxtn 1/1 Running 1 240d
nvidia-container-toolkit-daemonset-npj2f 1/1 Running 1 240d
nvidia-cuda-validator-xjlf2 0/1 Completed 0 206d
nvidia-dcgm-exporter-mrthr 1/1 Running 2 240d
nvidia-device-plugin-daemonset-zk779 2/2 Running 0 3d22h
nvidia-operator-validator-j9z5s 1/1 Running 1 240d
node에 gpu resource가 인식되는지 확인해보자.
$ k describe nodes | grep nvidia
nvidia.com/cuda.driver.major=550
nvidia.com/cuda.driver.minor=54
nvidia.com/cuda.driver.rev=14
nvidia.com/cuda.runtime.major=12
nvidia.com/cuda.runtime.minor=4
nvidia.com/gfd.timestamp=1731892896
nvidia.com/gpu-driver-upgrade-state=upgrade-done
nvidia.com/gpu.compute.major=8
nvidia.com/gpu.compute.minor=9
nvidia.com/gpu.count=2
nvidia.com/gpu.deploy.container-toolkit=true
nvidia.com/gpu.deploy.dcgm=true
nvidia.com/gpu.deploy.dcgm-exporter=true
nvidia.com/gpu.deploy.device-plugin=true
nvidia.com/gpu.deploy.driver=pre-installed
nvidia.com/gpu.deploy.gpu-feature-discovery=true
nvidia.com/gpu.deploy.node-status-exporter=true
nvidia.com/gpu.deploy.operator-validator=true
nvidia.com/gpu.family=ampere
nvidia.com/gpu.machine=System-Product-Name
nvidia.com/gpu.memory=24564
nvidia.com/gpu.present=true
nvidia.com/gpu.product=NVIDIA-GeForce-RTX-4090-SHARED
nvidia.com/gpu.replicas=8
nvidia.com/mig.capable=false
nvidia.com/mig.strategy=single
nvidia.com/gpu-driver-upgrade-enabled: true
정상적으로 쿠버네티스에서 GPU 리소스가 인식됨을 확인할 수 있다.
Triton Inference 서버 Deploy 하기.
다음은 내 환경에 맞는 Triton Inference Server 컨테이너 이미지를 선택하고,
Kubernets manifets 까지 배포하도록 하겠다.
https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tritonserver
트리톤 서버 컨테이너 이미지의 태그에 따른 차이점은 위 링크에서 확인할 수 있다. 대표적으로는 다음과 같다.
- The xx.yy-py3: Tensorflow, PyTorch, TensorRT, ONNX,OpenVINO models 지원
- The xx.yy-pyt-python-py3: PyTorch, Python backends만 지원
- The xx.yy-tf2-python-py3: TensorFlow 2.x, Python backends만 지원
- The xx.yy-vllm-python-py3: vLLM and Python backends만 지원.
태그 별로 컨테이너 이미지의 용량이 수 GB씩 차이나기 때문에, 자기가 필요한 라이브러리가 뭔지 확인하고 알맞은 태그를 선택하면 되겠다.xx.yy는 컨테이너 버전인데 이 숫자에 따라 지원하는 Triton Inference Server, Ubuntu, CUDA, TensorRT 버전이 모두 상이하기 때문에 꼭 확인해야 한다.https://docs.nvidia.com/deeplearning/triton-inference-server/release-notes/rel-24-10.html#rel-24-10
자신의 환경에 맞는 컨테이너 이미지를 선택했으면 kubernetes manifest를 만들어 보자.
크게 Deployment, Service, PVC를 생성해주면 된다.
본인은 nfs-client를 이용하여 자동으로 nfs volume이 provisioning 되지만, 만약 nfs가 아닌 다른 volume type을 사용한다면 알맞게 PVC yaml 파일을 수정해주면 되겠다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: triton-inference-ner
namespace: triton
labels:
app: triton-inference-ner
spec:
selector:
matchLabels:
app: triton-inference-ner
replicas: 1
template:
metadata:
labels:
app: triton-inference-ner
spec:
imagePullSecrets:
- name: docker-registry
containers:
- name: triton-inference-ner
image: nvcr.io/nvidia/tritonserver:23.04-pyt-python-py3
securityContext:
privileged: true
resources:
requests:
cpu: 1000m
memory: 1Gi
limits:
cpu: 2000m
memory: 8Gi
nvidia.com/gpu: "1"
ports:
- name: http
containerPort: 8000
- name: grpc
containerPort: 8001
- name: metrics
containerPort: 8002
args:
- '--model-control-mode=POLL'
volumeMounts:
- name: shmdir
mountPath: /dev/shm
- name: models
mountPath: /opt/tritonserver/models/
# subPath: models
volumes:
- name: shmdir
emptyDir:
medium: Memory
sizeLimit: "5G"
- name: models
persistentVolumeClaim:
claimName: triton-ner-pvc
---
apiVersion: v1
kind: Service
metadata:
name: triton-inference
namespace: triton
spec:
selector:
app: triton-inference
type: NodePort
ports:
- port: 8000
targetPort: http
name: http-inference-server
nodePort: 31898
- port: 8001
targetPort: grpc
name: grpc-inference-server
- port: 8002
targetPort: metrics
name: metrics-inference-server
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: triton-ner-pvc
namespace: triton
labels:
app: triton-inference-ner
spec:
storageClassName: nfs-client
accessModes:
- ReadWriteMany
resources:
requests:
storage: 500Mi
여기서 한가지 더,
Deployment.yaml에서 template.spec.args에서 '--model-control-mode=POLL'을 명시해준걸 볼 수 있다.
model-control-mode의 기본값은 none이다.
이를 --model-control-mode=POLL로 지정해주면 트리톤은 model_repository 내부를 주시하다가 특정 모델의 설정이 바뀔 때마다 해당 모델을 알아서 reload 해준다.
POLL, none으로 설정하면 triton은 model_repository의 모든 모델들을 일괄적으로 로드하게 되는데, 이를 명시적으로 일부 모델만 로드하고 싶다면 --model-control-mode=explicit 으로 지정하고 args에 추가적으로 --load-model=* 명령어를 주면 해당 모델들만 로드한다. 만약 --load-model을 지정하지 않으면 아무런 모델도 로드되지 않는다.
여기까지가 쿠버네티스에서 triton server를 올리는 방법이고, 다음 포스팅에 model repository를 설정하여 실제 모델을 로드하는 내용을 다루겠다.