Kthena — vLLM 통합
Kthena — vLLM 통합
Kthena는 Kubernetes 네이티브 LLM 추론 플랫폼으로, 조직이 프로덕션에서 대규모 언어 모델을 배포·관리하는 방식을 바꿉니다. 선언적 모델 생명주기 관리와 지능형 요청 라우팅을 기반으로 LLM 추론 워크로드에 고성능·엔터프라이즈급 확장성을 제공합니다.
Kthena는 ModelServing으로 추론 워크로드를 관리하고, ModelServer와 ModelRoute로 모델 인지 요청 라우팅을 제공합니다. 이 가이드는 ModelServing을 사용해 Kubernetes에서 멀티노드 vLLM 서비스를 배포하고 Kubernetes Service로 노출하는 방법을 안내합니다.
출처: 문서
본문
이 가이드에서 할 일:
- 필요한 컴포넌트(Kthena + Volcano)를 설치합니다.
- Kthena의
ModelServingCR로 멀티노드 vLLM 모델을 배포합니다. - 배포를 검증합니다.
1. 사전 준비 (Prerequisites)
필요한 것:
- GPU 노드가 있는 Kubernetes 클러스터.
- cluster-admin 또는 동등 권한의
kubectl접근. - 이 예제에서 사용하는 롤 레벨 gang 스케줄링을 위한 Volcano 1.14 이상.
ModelServingCRD가 있는 Kthena 설치.- Hugging Face Hub에서 모델을 로드할 경우 유효한 Hugging Face 토큰.
1.1 Volcano 설치 (Install Volcano)
helm repo add volcano-sh https://volcano-sh.github.io/helm-charts
helm repo update
helm install volcano volcano-sh/volcano -n volcano-system --create-namespace
Volcano는 이 예제에서 사용하는 gang 스케줄링을 제공합니다. Volcano 스케줄링을 쓰지 않는 Kthena 배포에는 선택 사항입니다.
1.2 Kthena 설치 (Install Kthena)
helm install kthena oci://ghcr.io/volcano-sh/charts/kthena --version v1.0.0 --namespace kthena-system --create-namespace
kthena-system네임스페이스가 생성됩니다.ModelServing을 포함한 Kthena 컨트롤러와 CRD가 설치됩니다.
검증:
kubectl get pods -n kthena-system
kubectl get crd modelservings.workload.serving.volcano.sh
다음이 보여야 합니다:
modelservings.workload.serving.volcano.sh ...
2. 멀티노드 vLLM ModelServing 예제 (The Multi-Node vLLM ModelServing Example)
Kthena는 Llama를 실행하는 멀티노드 vLLM 클러스터를 배포하는 예제 매니페스트를 제공합니다. 각 역할 레플리카는 엔트리 파드와 그 워커 파드로 구성됩니다.
예제(llama-multinode)의 단순화된 형태는 다음과 같습니다:
spec.replicas: 1— 하나의ServingGroup(논리 모델 배포 하나).roles:entryTemplate— 다음을 실행하는 리더 파드를 정의합니다:- vLLM의 멀티노드 클러스터 부트스트랩 스크립트.
- vLLM OpenAI 호환 API 서버.
workerTemplate— 리더의 Ray 클러스터에 합류(Ray 백엔드)하거나 같은 분산 프로세스 그룹에 합류(멀티프로세싱 백엔드)하는 워커 파드를 정의합니다.
예제 YAML의 핵심 포인트: 이미지 vllm/vllm-openai:latest(업스트림 vLLM 이미지와 일치). 멀티프로세싱(기본) 명령:
리더:
command:
- sh
- -c
- >
vllm serve meta-llama/Llama-3.1-405B-Instruct
--tensor-parallel-size 8
--pipeline-parallel-size 2
--nnodes=2
--node-rank=0
--master-addr=$(ENTRY_ADDRESS)
--port 8080
워커:
command:
- sh
- -c
- >
vllm serve meta-llama/Llama-3.1-405B-Instruct
--tensor-parallel-size 8
--pipeline-parallel-size 2
--nnodes=2
--node-rank=1
--master-addr=$(ENTRY_ADDRESS)
--headless
Ray 백엔드 명령:
리더:
command:
- sh
- -c
- >
bash /vllm-workspace/examples/ray_serving/multi-node-serving.sh
leader --ray_cluster_size=2;
vllm serve meta-llama/Llama-3.1-405B-Instruct --port 8080 --tensor-parallel-size 8
--pipeline-parallel-size 2 --distributed-executor-backend ray
워커:
command:
- sh
- -c
- >
bash /vllm-workspace/examples/ray_serving/multi-node-serving.sh
worker --ray_address=$(ENTRY_ADDRESS)
3. Kthena로 멀티노드 llama vLLM 배포 (Deploying Multi-Node llama vLLM via Kthena)
3.1 매니페스트 준비 (Prepare the Manifest)
권장: 원시 환경 변수 대신 Secret을 사용합니다:
kubectl create secret generic hf-token \
-n default \
--from-literal=HUGGING_FACE_HUB_TOKEN='<your-token>'
3.2 ModelServing 적용 (Apply the ModelServing)
다음 매니페스트 중 하나를 modelserving.yaml로 저장합니다. 멀티프로세싱(기본) 매니페스트:
apiVersion: workload.serving.volcano.sh/v1alpha1
kind: ModelServing
metadata:
name: llama-multinode
namespace: default
spec:
schedulerName: volcano
replicas: 1 # group replicas
template:
restartGracePeriodSeconds: 60
gangPolicy:
minRoleReplicas:
llama-405b: 1
roles:
- name: llama-405b
replicas: 2
entryTemplate:
spec:
containers:
- name: leader
image: vllm/vllm-openai:latest
env:
- name: HUGGING_FACE_HUB_TOKEN
valueFrom:
secretKeyRef:
name: hf-token
key: HUGGING_FACE_HUB_TOKEN
command:
- sh
- -c
- "vllm serve meta-llama/Llama-3.1-405B-Instruct --tensor-parallel-size 8 --pipeline-parallel-size 2 --nnodes 2 --node-rank 0 --master-addr $(ENTRY_ADDRESS) --distributed-executor-backend mp --port 8080"
resources:
limits:
nvidia.com/gpu: "8"
memory: 1124Gi
ephemeral-storage: 800Gi
requests:
ephemeral-storage: 800Gi
cpu: 125
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
volumeMounts:
- mountPath: /dev/shm
name: dshm
volumes:
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 15Gi
workerReplicas: 1
workerTemplate:
spec:
containers:
- name: worker
image: vllm/vllm-openai:latest
command:
- sh
- -c
- "vllm serve meta-llama/Llama-3.1-405B-Instruct --tensor-parallel-size 8 --pipeline-parallel-size 2 --nnodes 2 --node-rank 1 --master-addr $(ENTRY_ADDRESS) --distributed-executor-backend mp --headless"
resources:
limits:
nvidia.com/gpu: "8"
memory: 1124Gi
ephemeral-storage: 800Gi
requests:
ephemeral-storage: 800Gi
cpu: 125
env:
- name: HUGGING_FACE_HUB_TOKEN
valueFrom:
secretKeyRef:
name: hf-token
key: HUGGING_FACE_HUB_TOKEN
volumeMounts:
- mountPath: /dev/shm
name: dshm
volumes:
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 15Gi
Ray 백엔드 매니페스트:
apiVersion: workload.serving.volcano.sh/v1alpha1
kind: ModelServing
metadata:
name: llama-multinode
namespace: default
spec:
schedulerName: volcano
replicas: 1 # group replicas
template:
restartGracePeriodSeconds: 60
gangPolicy:
minRoleReplicas:
llama-405b: 1
roles:
- name: llama-405b
replicas: 2
entryTemplate:
spec:
containers:
- name: leader
image: vllm/vllm-openai:latest
env:
- name: HUGGING_FACE_HUB_TOKEN
valueFrom:
secretKeyRef:
name: hf-token
key: HUGGING_FACE_HUB_TOKEN
command:
- sh
- -c
- "bash /vllm-workspace/examples/ray_serving/multi-node-serving.sh leader --ray_cluster_size=2;
vllm serve meta-llama/Llama-3.1-405B-Instruct --port 8080 --tensor-parallel-size 8 --pipeline-parallel-size 2 --distributed-executor-backend ray"
resources:
limits:
nvidia.com/gpu: "8"
memory: 1124Gi
ephemeral-storage: 800Gi
requests:
ephemeral-storage: 800Gi
cpu: 125
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
volumeMounts:
- mountPath: /dev/shm
name: dshm
volumes:
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 15Gi
workerReplicas: 1
workerTemplate:
spec:
containers:
- name: worker
image: vllm/vllm-openai:latest
command:
- sh
- -c
- "bash /vllm-workspace/examples/ray_serving/multi-node-serving.sh worker --ray_address=$(ENTRY_ADDRESS)"
resources:
limits:
nvidia.com/gpu: "8"
memory: 1124Gi
ephemeral-storage: 800Gi
requests:
ephemeral-storage: 800Gi
cpu: 125
env:
- name: HUGGING_FACE_HUB_TOKEN
valueFrom:
secretKeyRef:
name: hf-token
key: HUGGING_FACE_HUB_TOKEN
volumeMounts:
- mountPath: /dev/shm
name: dshm
volumes:
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 15Gi
적용:
kubectl apply -f modelserving.yaml
Kthena가 수행할 일:
ModelServing객체를 생성합니다.- Volcano gang 스케줄링용
PodGroup을 파생합니다. - 각
ServingGroup및Role에 대한 리더·워커 파드를 생성합니다.
4. 배포 검증 (Verifying the Deployment)
4.1 ModelServing 상태 확인 (Check ModelServing Status)
Kthena 문서의 스니펫을 사용합니다:
kubectl get modelserving -oyaml | grep status -A 10
다음과 비슷한 결과가 보여야 합니다:
status:
availableReplicas: 1
conditions:
- type: Available
status: "True"
reason: AllGroupsReady
message: All Serving groups are ready
- type: Progressing
status: "False"
...
replicas: 1
updatedReplicas: 1
4.2 파드 확인 (Check Pods)
배포의 파드를 나열합니다:
kubectl get pod -owide -l modelserving.volcano.sh/name=llama-multinode
출력 예시(문서 기준):
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE ...
default llama-multinode-0-llama-405b-0-0 1/1 Running 0 15m 10.244.0.56 192.168.5.12 ...
default llama-multinode-0-llama-405b-0-1 1/1 Running 0 15m 10.244.0.58 192.168.5.43 ...
default llama-multinode-0-llama-405b-1-0 1/1 Running 0 15m 10.244.0.57 192.168.5.58 ...
default llama-multinode-0-llama-405b-1-1 1/1 Running 0 15m 10.244.0.53 192.168.5.36 ...
파드 이름 패턴: llama-multinode-<group-idx>-<role-name>-<replica-idx>-<ordinal>.
첫 번째 인덱스는 ServingGroup을, 이어서 역할 이름(llama-405b), 역할 레플리카 인덱스, 파드 인덱스를 나타냅니다.
5. vLLM OpenAI 호환 API 접근 (Accessing the vLLM OpenAI-Compatible API)
엔트리 파드를 노출하려면 다음 Service를 service.yaml로 저장합니다:
apiVersion: v1
kind: Service
metadata:
name: llama-multinode-openai
namespace: default
spec:
selector:
modelserving.volcano.sh/name: llama-multinode
modelserving.volcano.sh/entry: "true"
ports:
- name: http
port: 80
targetPort: 8080
type: ClusterIP
Service를 적용한 뒤 로컬 머신에서 포트 포워딩합니다:
kubectl apply -f service.yaml
kubectl port-forward svc/llama-multinode-openai 30080:80 -n default
그다음:
- 모델 나열:
curl -s http://localhost:30080/v1/models
- 완성(completion) 요청 보내기 (vLLM production stack 문서에 맞춤):
curl -X POST http://localhost:30080/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "meta-llama/Llama-3.1-405B-Instruct",
"prompt": "Once upon a time,",
"max_tokens": 10
}'
vLLM의 OpenAI 스타일 응답이 보여야 합니다.
6. 정리 (Clean Up)
배포와 리소스를 제거하려면:
kubectl delete -f service.yaml
kubectl delete modelserving llama-multinode -n default
전체 스택을 마무리하려면:
helm uninstall kthena -n kthena-system # or your Kthena release name
helm uninstall volcano -n volcano-system
모델 인지 라우팅과 prefill-decode 분리에 대한 내용은 Kthena 문서를 참고하세요.
더 알아보기 (Learn more)
- 모든 배포 통합 — vLLM과 연동되는 통합 목록
- Kthena 레포지토리
- Kthena 문서 — 라우팅·라우팅 가이드