멀티 노드 생성형 AI — Triton Server + TensorRT-LLM

멀티 노드 생성형 AI — Triton Server + TensorRT-LLM (Multi-Node)

대형 언어 모델(LLM)이 크다는 건 두말할 필요가 없죠. LLM은 단일 GPU 메모리에 안 들어가는 경우가 많아서, 여러 GPU가 협력해 아주 큰 모델의 추론 서빙을 가능하게 하는 솔루션이 필요해요. 이 가이드는 쿠버네티스 클러스터에서 Triton Server와 TRT-LLM을 이용해 LLM을 다중 GPU·다중 노드로 배포하는 방법을 설명합니다. 설정 자체는 어렵지 않지만 준비가 필요해요.

다루는 주제:

  • 클러스터 설정 (영구 볼륨 설정, 핵심 클러스터 서비스, Hugging Face 인증)
  • 트리톤 준비 (모델 준비 스크립트, 커스텀 컨테이너 이미지, 쿠버네티스 Pull Secrets)
  • 트리톤 배포 (작동 방식, 개선 가능성 — 자동 확장·Gang Scheduling, 네트워크 토폴로지 인식 스케줄링)
  • 이 가이드 작성 과정

시작 전 준비물: kubectl, helm, docker CLI, YAML 편집기, 쿠버네티스 클러스터, 관리자 권한이 있는 kubectl 설정입니다.

출처: 공식문서 - Multi-Node Distributed Models

클러스터 설정

사전 요구사항

NVIDIA GPU 노드마다 nvidia.com/gpu=present 노드 라벨과 nvidia.com/gpu=present:NoSchedule 테인트가 있다고 가정합니다.

[!팁] AKS, EKS(문서에는 EKA로 표기), GKE 같은 제공자는 kubectl로 직접 구성하기보다 제공자 인터페이스를 쓰는 게 보통 좋아요.

영구 볼륨 설정

여러 노드에 배포된 여러 파드가 같은 모델의 샤드를 로딩해 단일 GPU로는 너무 큰 추론 요청을 협력 처리하려면 공통·공유 저장 위치(쿠버네티스의 영구 볼륨)가 필요해요. 영구 볼륨은 여러 파드에 볼륨 매핑되고, 파드 안 프로세스는 자기 파일시스템의 일부처럼 접근합니다. 또한 영구 볼륨을 파드에 할당할 영구 볼륨 클레임(PVC)도 만들어요.

영구 볼륨 생성은 클러스터 설정 방식에 따라 달라서 이 튜토리얼 범위 밖이지만, 클라우드 제공자(EKS·AKS·GKE·OKE)의 경우 온라인 단계별 가이드가 있습니다.

[!중요] 클러스터가 호스팅할 모델들의 저장 요구량을 고려해, 모든 모델의 결합 저장 크기에 맞게 영구 볼륨을 충분히 잡아야 해요.

내부 테스트에서 얻은 예시 값:

모델 병렬 처리 원본 크기 변환 크기 총 크기
Llama-3-8B 2 15Gi 32Gi 47Gi
Llama-3-8B 4 15Gi 36Gi 51Gi
Llama-3-70B 8 90Gi 300Gi 390Gi

영구 볼륨 클레임 생성

트리톤 서버 파드를 영구 볼륨에 연결하려면 PVC가 필요해요. 이 튜토리얼에 포함된 pvc.yaml을 사용합니다.

[!중요] volumeName 속성이 위에서 만든 영구 볼륨의 metadata.name과 일치해야 해요.

핵심 클러스터 서비스

Kubernetes Node Feature Discovery 서비스

helm repo add kube-nfd https://kubernetes-sigs.github.io/node-feature-discovery/charts \
&& helm repo update

helm install -n kube-system node-feature-discovery kube-nfd/node-feature-discovery \
--set nameOverride=node-feature-discovery \
--set worker.tolerations[0].key=nvidia.com/gpu \
--set worker.tolerations[0].operator=Exists \
--set worker.tolerations[0].effect=NoSchedule

NVIDIA Device Plugin for Kubernetes

이미 설치돼 있으면 건너뜁니다. 확인:

kubectl get daemonsets --all-namespaces

없으면 설치:

kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.15.0/deployments/static/nvidia-device-plugin.yml

NVIDIA GPU Feature Discovery 서비스

이미 설치돼 있으면(출력에 gpu-feature-discovery가 있으면) 건너뜁니다. 없으면:

curl https://raw.githubusercontent.com/NVIDIA/gpu-feature-discovery/v0.8.2/deployments/static/gpu-feature-discovery-daemonset.yaml \
>  nvidia_gpu-feature-discovery_daemonset.yaml

kubectl apply -f ./nvidia_gpu-feature-discovery_daemonset.yaml

Hugging Face 인증

Hugging Face에서 모델을 내려받으려면 파드에 적절한 권한의 액세스 토큰이 필요해요. 토큰을 hf-model-pull 시크릿으로 저장합니다.

kubectl create secret generic hf-model-pull '--from-literal=password=<access_token>'

kubectl get secrets

트리톤 준비

모델 준비 스크립트

이 스크립트는 Hugging Face에서 모델 파일을 가져오고, TensorRT 엔진·plan 파일을 생성하며, 생성된 파일을 캐시하는 역할을 해요. Helm 차트가 쓰는 쿠버네티스 배포 스크립트는 영구 볼륨 클레임을 받쳐주는 영구 볼륨에 의존합니다. 모델·엔진 디렉토리를 영구 볼륨의 폴더에 매핑하고, 이후 배포되는 모든 파드에 다시 매핑해 plan·엔진 생성 단계 완료를 감지해 작업을 반복하지 않게 해요.

[!팁] 이 스크립트는 .model.skipConversion 속성이 false가 아니면 Helm 차트가 설치될 때마다 job으로 실행돼요.

트리톤 서버 시작 시 같은 영구 볼륨 폴더가 컨테이너에 마운트되고, 트리톤은 미리 생성된 plan·엔진 파일을 사용합니다. 덕분에 다른 노드의 파드가 같은 엔진·plan 파일을 공유하고, 같은 노드에서 다음 파드 시작 시간도 크게 줄어요.

커스텀 컨테이너 이미지

triton_trt-llm.containerfile로 이미지를 빌드. 예시는 베이스 24.04-trtllm-python-py3에 맞춰 태그 24.04 사용.

docker build \
--file ./triton_trt-llm.containerfile \
--rm \
--tag triton_trt-llm:24.04 \
.

이 커스텀 이미지는 커스텀 버전의 Triton CLI를 쓰는데, 그 변경점은 Triton CLI 저장소의 토픽 브랜치에서 볼 수 있어요. 주로 TensorRT-LLM 모델 최적화 시 텐서 병렬 처리를 지정하는 기능과 추가 모델 지원이 포함됩니다.

  • 이미지를 클러스터가 볼 수 있게 저장소에 올리기:
docker tag \
triton_trt-llm:24.04 \
nvcr.io/example/triton_trt-llm:24.04

docker push nvcr.io/example/triton_trt-llm:24.04

쿠버네티스 Pull Secrets

이미지 저장소가 인증을 요구하면 docker-registry 시크릿 생성(예시는 가상 저장소 nvcr.io):

kubectl create secret docker-registry ngc-container-pull \
--docker-password='dGhpcyBpcyBub3QgYSByZWFsIHNlY3JldC4gaXQgaXMgb25seSBmb3IgZGVtb25zdHJhdGlvbiBwdXJwb3Nlcy4=' \
--docker-server='nvcr.io' \
--docker-username='\$oauthtoken'

확인·디코딩:

kubectl get secrets
kubectl get secret/ngc-container-pull -o yaml
kubectl get secret/ngc-container-pull -o json | jq -r '.data[".dockerconfigjson"]' | base64 -d | jq

트리톤 배포

[!참고] 단일 GPU에 들어가는 모델의 배포는 이 가이드에서 다루지 않아요. 단일 GPU 또는 단일 노드 다중 GPU 배포는 "Autoscaling and Load Balancing Generative AI w/ Triton Server and TensorRT-LLM" 가이드를 참고하세요.

일부 큰 모델은 단일 기기로 감당할 수 없어요. 트리톤·TensorRT-LLM은 여러 GPU가 협력해 큰 모델을 호스팅하는 메커니즘을 제공합니다. model.tensorrtLlm.parallelism.tensor 값을 1보다 큰 정수로 조정하면 텐서 병렬 처리가 켜져 여러 GPU의 메모리를 합칩니다. model.tensorrtLlm.parallelism.pipeline을 바꾸면 파이프라인 병렬 처리가 켜져 여러 GPU의 연산 능력을 합칩니다.

[!중요] .tensor.pipeline의 곱은 0보다 크고 32 이하인 2의 거듭제곱이어야 해요.

모델 호스팅에 필요한 GPU 수는 .tensor.pipeline의 곱입니다. 모델 배포 시 GPU마다 파드 하나가 생기고, Helm 차트는 리더 파드와 나머지를 담당하는 워커 파드들을 만듭니다. 또한 모델을 Hugging Face에서 내려받아 TRT-LLM 엔진·plan 파일로 변환하는 변환 job도 만들어요. 변환 job을 비활성화하려면 values 파일의 model.skipConversion 속성을 false로 설정합니다.

[!경고] 클러스터에 변환 job·리더 파드·워커 파드들을 만들 리소스가 부족하면, 인스턴스 수가 부족해 job 파드가 스케줄되지 못하면서 리더 파드가 job 완료를 기다려 차트가 "멈출" 수 있어요. 이 경우 Helm 설치를 삭제하고 job 파드가 성공적으로 스케줄될 때까지 재시도하는 게 좋습니다.

배포 명령:

helm install <installation_name> \
--values ./chart/values.yaml \
--values ./chart/<custom_values>.yaml \
--set 'triton.image.name=<custom_image_name>' \
./chart/.

확인:

kubectl get deployments,pods,services,jobs --selector='app=<installation_name>'

예시 출력(설치 이름 "llama-3"):

NAME                      READY   UP-TO-DATE   AVAILABLE
deployment.apps/llama-3   0/1     1            0

NAME                          READY   STATUS    RESTARTS
pod/llama-3-7989ffd8d-ck62t   0/1     Pending   0

NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)
service/llama-3   ClusterIP   10.100.23.237   <none>        8000/TCP,8001/TCP,8002/TCP

제거:

helm uninstall <installation_name>

작동 방식

Helm 차트는 모델 변환 job과 여러 쿠버네티스 deployment를 만들어 분산 모델의 텐서 병렬 처리를 지원해요. 분산 모델 배포 시 리더 파드와 함께 텐서 병렬 처리 요구를 충족하는 수만큼의 워커 파드가 생성됩니다. 리더 파드는 변환 job 완료와 모든 워커 파드 배포 성공을 기다려요. 변환 job은 Hugging Face에서 모델을 내려받아 TensorRT-LLM용 엔진·plan 파일로 변환하고, 모든 파일을 영구 볼륨에 둡니다.

[!참고] Hugging Face 모델 다운로드는 가능하면 재사용됩니다. 변환된 TRT-LLM 모델은 GPU·텐서 병렬 처리별로 특화되므로, 모델이 배포되는 각 GPU와 각 텐서 병렬 처리 구성마다 변환 모델이 존재해요.

조건이 충족되면 리더 파드가 mpirun 프로세스를 만들어 분산 모델의 각 파드에 트리톤 서버 프로세스를 생성합니다. 리더 파드의 프로세스는 추론 요청·응답 기능과 토크나이제이션·디토크나이제이션을 담당하고, 워커 파드 프로세스는 GPU 연산·메모리 용량을 확장합니다. 모든 프로세스는 원래의 mpirun 프로세스가 조율하며, 프로세스 간 통신은 NVIDIA Collective Communications Library(NCCL)가 가속합니다. NCCL은 GPU 간 직접 통신을 가능하게 해 GPU→CPU→GPU로의 비효율적인 데이터 복사를 피합니다.

개선 가능성

자동 확장과 Gang Scheduling

이 가이드는 트리톤 배포의 자동 확장·로드 밸런싱 솔루션을 제공하지 않아요. 쿠버네티스 HPA는 여러 파드로 구성된 배포를 관리하지 못하기 때문입니다. 또 이 튜토리얼의 솔루션은 여러 deployment를 쓰므로, 동시·부분 배포가 가용 리소스를 소진해 어떤 배포도 성공하지 못할 위험이 높습니다.

예를 들어 4노드 × 8GPU = 32 GPU 클러스터에서 8 GPU가 필요한 모델 5개의 복사본을 각각 배포하면 4개는 성공하고 5번째는 리소스가 없어 실패해요. 하지만 5개를 동시에 배포하면 각 복사본이 최소 1개 GPU를 받아, 적어도 2개 복사본은 리소스가 부족해 부분 배포 상태로 멈춥니다. gang scheduler를 쓰면 파드의 전체 코호트(cohort)를 만들 수 있을 때만 파드를 생성하므로 이 문제를 해결할 수 있어요. (참고: gang scheduling on Wikipedia)

단, 위 솔루션은 자동 확장을 제공하지 않으므로, 이를 위해선 gang-scheduler를 이해하는 커스텀 오토스케일러가 필요해요.

네트워크 토폴로지 인식 스케줄링

Triton Server + TensorRT-LLM은 NVIDIA NCCL을 사용해 텐서 병렬화를 활성화합니다. NCCL은 현대 GPU의 RDMA 기반 네트워크 가속을 활용해 같은 기기나 인접 기기의 GPU 간 연산을 최적화하죠. 즉 서로 다른 기기의 GPU 간 네트워크 품질이 분산 모델 성능에 직접 영향을 줍니다. 쿠버네티스용 네트워크 토폴로지 인식 스케줄러를 두면 모델 배포 파드에 할당되는 GPU들이 서로 상대적으로 가까이 있도록 보장할 수 있어요. 이상적으로는 같은 머신, 최소한 같은 네트워크 스위치에 있어 네트워크 지연과 대역폭 제한 영향을 줄이는 겁니다.

이 가이드 작성 과정에서 배운 것

  • 왜 이 소프트웨어 조합인가 — NVIDIA Device Plugin(GPU를 스케줄러 리소스로), GPU Feature Discovery(노드 자동 라벨링 — 없으면 특정 GPU SKU 지정 불가), Node Feature Discovery, DCGM Exporter(하드웨어 메트릭 — 트리톤이 직접 제공하는 것보다 별도 수집이 프로세스 오버헤드·직렬화 지연·수집 주기 차이에서 유리), Prometheus Stack, Prometheus Adapter.
  • 왜 Triton CLI인가 — 모델 변환·최적화를 단일 명령으로 단순화하고, 한 번의 pip install로 컨테이너 생성에 필요한 요구사항을 모두 충족하기 때문이에요. 공식 릴리스에 없는 기능이 필요해 커스텀 브랜치를 썼어요.
  • 차트가 트리톤 서버 대신 파이썬 스크립트를 실행하는 이유 — 모델을 Hugging Face에서 받아 변환·최적화·캐시하는 초기화 컨테이너가 직관적이고, 멀티 GPU 배포의 특수 커맨드라인을 Helm 스크립팅으로 생성하는 것보다 커스텀 server.py가 쉽기 때문이에요. ENGINE_DEST_PATH 같은 일관된 커스텀 환경변수를 초기화 컨테이너와 트리톤 서버 컨테이너가 함께 쓰고 싶어 커스텀 이미지를 선택했어요. (임시 저장소 사용은 파드 축출을 부를 수 있으니 피하세요.)

이 문서에 등장한 소프트웨어 버전:

  • Triton Inference Server v2.45.0 (24.04-trtllm-python-py3)
  • TensorRT-LLM v0.9.0
  • Triton CLI v0.0.7
  • NVIDIA Device Plugin for Kubernetes v0.15.0
  • NVIDIA GPU Discovery Service for Kubernetes v0.8.2
  • NVIDIA DCGM Exporter v3.3.5
  • Kubernetes Node Discovery Service v0.15.4
  • Prometheus Stack for Kubernetes v58.7.2
  • Prometheus Adapter for Kubernetes v4.10.0

더 알아보기 (Learn more)