네. 다만 “여러 사용자가 GPU를 공유한다 = LiteLLM이 표준”이라고 보기는 어렵습니다.
정확히는 LiteLLM은 GPU를 공유하는 계층이 아니라, 여러 사용자의 LLM 요청을 관리하는 AI Gateway 계층입니다.
현재 말씀하신 B300 1대 / 8 GPU / 여러 모델 / 여러 사용자 구조라면 다음처럼 나누는 것이 일반적입니다.
Users / Applications
│
Keycloak / AD
│
▼
Cilium Gateway API
│
▼
┌─────────────┐
│ LiteLLM │ ← 사용자/팀/모델/API 관리
│ Proxy │ Rate limit / quota / routing
└──────┬──────┘
│
┌────────────┼────────────┐
▼ ▼ ▼
vLLM-70B vLLM-32B vLLM-8B
GPU 0-3 GPU 4-5 GPU 6
TP4 TP2 TP1
│ │ │
└────────────┴────────────┘
│
GPU 0 ~ 7
| 계층 | 담당 | 핵심 역할 |
|---|---|---|
| Kubernetes + NVIDIA GPU Operator | GPU 자원 | GPU 할당/격리, scheduling |
| vLLM | 추론 엔진 | batching, KV cache, prefix cache, TP |
| LiteLLM | AI Gateway | 사용자 인증, API key, quota, RPM/TPM, model routing |
| Envoy Gateway/Cilium | 네트워크 Gateway | TLS, JWT/OIDC, L7 routing, NetworkPolicy |
| Keycloak | Identity | 사용자/그룹/서비스 인증 |
| Prometheus/DCGM | Observability | GPU/LLM/사용자별 사용량 모니터링 |
LiteLLM 자체도 공식적으로 Gateway/Proxy를 중심으로 authentication, logging, cost tracking, rate limiting을 제공하고, virtual key/user/team 단위의 관리가 가능합니다. :chatgpt-content-reference{index="0"}
특히 현재 LiteLLM은 team/user/key별로 RPM, TPM, max parallel requests를 설정할 수 있고, 모델별 제한도 가능합니다. :chatgpt-content-reference{index="1"}
LiteLLM이 GPU를 "공유"하는 것은 아닙니다.
예를 들어:
User A ─┐
User B ─┼─> LiteLLM ──> vLLM 70B ──> GPU 0-3
User C ─┘
이 경우 LiteLLM은
A: max 10 concurrent
B: max 5 concurrent
C: max 20 concurrent
처럼 요청을 제어합니다.
하지만 GPU 0~3에서 실제로
A 요청
B 요청
C 요청
을 어떻게 batching하고 KV cache를 어떻게 사용하는지는 vLLM이 담당합니다.
즉,
LiteLLM = GPU scheduler가 아니라 LLM request scheduler/gateway
라고 이해하는 게 정확합니다.
여기서 Kubernetes/NVIDIA 쪽이 필요합니다.
대표적인 방법은:
현재 B300 테스트에는 이 방법이 가장 자연스럽습니다.
GPU 0-3 → 70B TP4
GPU 4-5 → 32B TP2
GPU 6 → 8B TP1
GPU 7 → embedding/reranker 또는 spare
그리고 여러 사용자가 LiteLLM을 통해 같은 모델을 호출합니다.
User A ─┐
User B ─┼──> LiteLLM ──> vLLM 70B ──> GPU 0-3
User C ─┘
이때 GPU는 공유되지만 모델 프로세스가 GPU를 점유하고, vLLM이 여러 요청을 continuous batching으로 처리합니다.
저라면 지금 진행 중인 B300 POC에서는 이 구조를 1차 기준선으로 잡겠습니다.
Kubernetes NVIDIA GPU Operator에는 GPU time-slicing 기능이 있습니다. GPU를 여러 replica처럼 노출하여 여러 Pod가 하나의 GPU를 공유할 수 있습니다. 다만 NVIDIA 문서에서도 설명하듯이 MIG와 달리 메모리/장애 격리가 없습니다. :chatgpt-content-reference{index="2"}
예:
GPU 6
├── Pod A
├── Pod B
├── Pod C
└── Pod D
이것은 작은 모델이나 개발/테스트 환경에는 유용하지만,
70B inference
+ 32B inference
+ 8B inference
처럼 HBM 사용량이 큰 production inference를 하나의 GPU에 무작정 섞는 방식은 별개의 문제입니다.
MIG가 가능한 GPU에서는 GPU를 하드웨어 파티션으로 나눌 수도 있습니다.
하지만 현재 B300 8-GPU inference benchmark에서는 저는 MIG를 기본 구조로 두기보다는 MIG OFF 상태에서 먼저 검증하는 쪽이 좋습니다.
특히 TP4/TP8 모델은 여러 GPU를 하나의 inference instance로 묶어야 하므로 MIG와 궁합이 좋지 않은 경우가 많습니다.
여러 사용자가 들어오면 단순히 vLLM만 노출하는 것보다 관리할 것이 급격히 늘어납니다.
예를 들어:
LiteLLM
│
┌───────────────┼────────────────┐
│ │ │
User A User B User C
Team-A Team-A Team-B
│ │ │
100K TPM 50K TPM 200K TPM
│ │ │
└───────────────┼────────────────┘
│
Model routing
│
┌────────────┼────────────┐
▼ ▼ ▼
70B 32B 8B
LiteLLM은 현재 virtual key → user → team 단위로 모델 접근, rate limit, budget 등을 관리할 수 있습니다. :chatgpt-content-reference{index="3"}
따라서 기업 내부 AI 플랫폼에서는 상당히 유용한 계층입니다.
제가 권하는 구조는 오히려 다음에 가깝습니다.
┌──────────────┐
│ Keycloak/AD │
└──────┬───────┘
OIDC
│
▼
┌─────────────────┐
│ Cilium Gateway │
│ API / Envoy │
└────────┬────────┘
│
▼
┌─────────────────┐
│ LiteLLM │
│ │
│ Auth / Quota │
│ User / Team │
│ Model routing │
│ RPM / TPM │
│ concurrency │
└────────┬────────┘
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
vLLM-70B vLLM-32B vLLM-8B
TP4 TP2 TP1
│ │ │
▼ ▼ ▼
GPU 0-3 GPU 4-5 GPU 6
그리고 LiteLLM 아래에 vLLM replica가 여러 개 생기면 LiteLLM의 routing/load balancing이 의미가 더 커집니다.
LiteLLM Router는 같은 model group에 여러 deployment를 두고 load balancing/fallback/retry를 수행할 수 있습니다. :chatgpt-content-reference{index="4"}
예를 들어:
LiteLLM
│
model = llama-70b
│
┌─────────┴─────────┐
▼ ▼
vLLM-70B-A vLLM-70B-B
GPU 0-3 GPU 4-7
이 경우에는 LiteLLM이 단순 인증 gateway를 넘어서 inference deployment 간 traffic distribution까지 담당할 수 있습니다.
제가 표현한다면 이렇게 정리하겠습니다.
| 질문 | 답 |
|---|---|
| 여러 사용자가 GPU를 공유할 때 LiteLLM이 GPU를 관리하나? | ❌ |
| 여러 사용자의 LLM API를 하나로 관리하는 데 LiteLLM을 많이 쓰나? | 예 |
| 사용자별 API key/quota/RPM/TPM 관리 | LiteLLM이 적합 |
| 모델별 routing | LiteLLM이 적합 |
| 여러 vLLM deployment load balancing | LiteLLM이 가능 |
| GPU 자체 할당 | Kubernetes + NVIDIA GPU Operator |
| GPU isolation | MIG / time-slicing / Pod allocation |
| inference batching/KV cache | vLLM |
| 인증/SSO | Keycloak/AD + Gateway |
| network isolation | Cilium |
저는 "LiteLLM이 GPU를 공유한다"는 설계보다는
Kubernetes가 GPU 자원을 나누고 → vLLM이 GPU 안에서 inference concurrency를 관리하고 → LiteLLM이 사용자/팀/모델 단위의 API 및 quota를 관리한다
라는 3계층 구조로 잡는 것을 권합니다.
특히 지금처럼 8-GPU B300 한 대에서 70B/32B/8B 등 서로 다른 모델을 여러 사용자가 호출하는 구조라면, 다음 단계에서는 "GPU allocation → vLLM instance → LiteLLM model deployment → 사용자 quota"를 실제 Kubernetes YAML 수준으로 어떻게 구성할지 정하는 것이 핵심입니다.
네. 지금 말씀하신 B300 8-GPU / Kubernetes / vLLM / Keycloak / 여러 사용자 환경이라면, 저는 아래처럼 설계하는 것을 권합니다.
핵심은 GPU를 사용자별로 직접 나누지 않고, GPU를 모델 serving instance에 할당한 다음 LiteLLM이 사용자 요청을 그 instance로 제어하는 것입니다.
Keycloak / AD
│
OIDC / JWT
│
▼
Cilium Gateway API / Envoy
│
▼
┌──────────────┐
│ LiteLLM │
│ Proxy │
└──────┬───────┘
│
model_name / quota / routing
│
┌─────────────┼─────────────┐
▼ ▼ ▼
llama-70b qwen-32b llama-8b
TP4 TP2 TP1
GPU 0-3 GPU 4-5 GPU 6
│ │ │
└─────────────┴─────────────┘
GPU 7
spare / embedding
Kubernetes의 NVIDIA device plugin은 nvidia.com/gpu 리소스를 Pod에 할당하고, vLLM은 할당받은 GPU 안에서 tensor parallelism과 batching을 수행합니다. vLLM의 Kubernetes 예제도 nvidia.com/gpu를 resource limit으로 지정하는 방식을 사용합니다. :chatgpt-content-reference{index="0"}
LiteLLM은 그 위에서 model routing, RPM/TPM, max parallel requests, user/team budget 등을 담당합니다. :chatgpt-content-reference{index="1"}
예를 들어 B300 노드가:
b300-01
├─ GPU 0
├─ GPU 1
├─ GPU 2
├─ GPU 3
├─ GPU 4
├─ GPU 5
├─ GPU 6
└─ GPU 7
이라고 하면 Kubernetes 입장에서는 특별히
GPU 0-3
GPU 4-5
GPU 6
이라는 자원 풀이 존재하는 것이 아닙니다.
각 vLLM Pod가:
resources:
limits:
nvidia.com/gpu: 4
처럼 GPU 개수를 요청합니다.
따라서 GPU ID를 직접 지정하는 것보다 Kubernetes가 GPU allocation을 담당하도록 하는 것이 기본입니다.
예를 들어 70B 모델을 GPU 4장으로 서비스한다고 하겠습니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-70b
namespace: llm
spec:
replicas: 1
selector:
matchLabels:
app: vllm-70b
template:
metadata:
labels:
app: vllm-70b
model: llama-70b
spec:
nodeSelector:
accelerator: b300
containers:
- name: vllm
image: vllm/vllm-openai:0.9.x
args:
- "meta-llama/Llama-3.1-70B-Instruct"
- "--tensor-parallel-size"
- "4"
- "--gpu-memory-utilization"
- "0.90"
- "--max-model-len"
- "32768"
- "--host"
- "0.0.0.0"
- "--port"
- "8000"
ports:
- containerPort: 8000
resources:
requests:
cpu: "16"
memory: "64Gi"
nvidia.com/gpu: "4"
limits:
cpu: "32"
memory: "128Gi"
nvidia.com/gpu: "4"
volumeMounts:
- name: shm
mountPath: /dev/shm
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 120
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 180
periodSeconds: 20
volumes:
- name: shm
emptyDir:
medium: Memory
sizeLimit: 16Gi
그리고 Service:
apiVersion: v1
kind: Service
metadata:
name: vllm-70b
namespace: llm
spec:
selector:
app: vllm-70b
ports:
- port: 8000
targetPort: 8000
이렇게 됩니다.
vllm-70b Pod
│
├── nvidia.com/gpu = 4
│
└── vLLM
│
└── TP=4
│
├── GPU
├── GPU
├── GPU
└── GPU
여기서 중요한 점은 CUDA_VISIBLE_DEVICES를 사용자가 직접 0,1,2,3으로 고정하는 방식으로 운영하지 않는 것입니다.
Kubernetes/NVIDIA device plugin이 Pod에 할당한 GPU를 컨테이너에 노출시키고, vLLM은 그 GPU 집합을 대상으로 TP=4를 수행하게 하는 구조가 좋습니다.
같은 방식입니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-32b
namespace: llm
spec:
replicas: 1
selector:
matchLabels:
app: vllm-32b
template:
metadata:
labels:
app: vllm-32b
model: qwen-32b
spec:
nodeSelector:
accelerator: b300
containers:
- name: vllm
image: vllm/vllm-openai:0.9.x
args:
- "Qwen/Qwen3-32B"
- "--tensor-parallel-size"
- "2"
- "--gpu-memory-utilization"
- "0.90"
- "--max-model-len"
- "32768"
ports:
- containerPort: 8000
resources:
requests:
cpu: "8"
memory: "32Gi"
nvidia.com/gpu: "2"
limits:
cpu: "16"
memory: "64Gi"
nvidia.com/gpu: "2"
Service:
apiVersion: v1
kind: Service
metadata:
name: vllm-32b
namespace: llm
spec:
selector:
app: vllm-32b
ports:
- port: 8000
targetPort: 8000
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-8b
namespace: llm
spec:
replicas: 1
selector:
matchLabels:
app: vllm-8b
template:
metadata:
labels:
app: vllm-8b
model: llama-8b
spec:
nodeSelector:
accelerator: b300
containers:
- name: vllm
image: vllm/vllm-openai:0.9.x
args:
- "meta-llama/Llama-3.1-8B-Instruct"
- "--tensor-parallel-size"
- "1"
- "--gpu-memory-utilization"
- "0.90"
- "--max-model-len"
- "32768"
ports:
- containerPort: 8000
resources:
requests:
cpu: "4"
memory: "16Gi"
nvidia.com/gpu: "1"
limits:
cpu: "8"
memory: "32Gi"
nvidia.com/gpu: "1"
그러면 대략:
B300
┌─────────────────────────────────────┐
│ GPU 0 ─┐ │
│ GPU 1 │ │
│ GPU 2 ├── vLLM 70B TP4 │
│ GPU 3 ─┘ │
│ │
│ GPU 4 ─┐ │
│ GPU 5 ─┘── vLLM 32B TP2 │
│ │
│ GPU 6 ──── vLLM 8B TP1 │
│ │
│ GPU 7 ──── spare │
└─────────────────────────────────────┘
가 됩니다.
단, 실제 GPU 번호가 이렇게 배정된다고 가정해서는 안 됩니다. Kubernetes가 어느 GPU를 해당 Pod에 제공하는지는 device plugin에 맡기고, 실제 TP 그룹과 NUMA/NVLink topology는 nvidia-smi topo -m 및 실제 Pod allocation으로 검증하는 것이 좋습니다.
LiteLLM에서는 Kubernetes Service를 deployment로 등록합니다.
예를 들어:
model_list:
# ------------------------------------------------
# 70B
# ------------------------------------------------
- model_name: llama-70b
litellm_params:
model: openai/llama-70b
api_base: http://vllm-70b.llm.svc.cluster.local:8000/v1
api_key: dummy
max_parallel_requests: 8
# ------------------------------------------------
# 32B
# ------------------------------------------------
- model_name: qwen-32b
litellm_params:
model: openai/qwen-32b
api_base: http://vllm-32b.llm.svc.cluster.local:8000/v1
api_key: dummy
max_parallel_requests: 16
# ------------------------------------------------
# 8B
# ------------------------------------------------
- model_name: llama-8b
litellm_params:
model: openai/llama-8b
api_base: http://vllm-8b.llm.svc.cluster.local:8000/v1
api_key: dummy
max_parallel_requests: 32
router_settings:
num_retries: 0
default_max_parallel_requests: 16
여기서 아주 중요한 부분이 있습니다.
max_parallel_requests이것은 GPU utilization을 직접 제한하는 값이 아닙니다.
예를 들어:
max_parallel_requests: 8
이면 LiteLLM이 해당 deployment로 동시에 보낼 수 있는 요청 수를 제한합니다.
현재 LiteLLM 문서상 이 제한을 초과하면 요청을 queue에 무한정 쌓는 것이 아니라 429가 발생할 수 있고, deployment별 max_parallel_requests가 우선 적용됩니다. :chatgpt-content-reference{index="2"}
따라서 이 값을 vLLM의 --max-num-seqs와 동일하게 생각하면 안 됩니다.
예:
apiVersion: apps/v1
kind: Deployment
metadata:
name: litellm
namespace: llm
spec:
replicas: 2
selector:
matchLabels:
app: litellm
template:
metadata:
labels:
app: litellm
spec:
containers:
- name: litellm
image: ghcr.io/berriai/litellm:latest
args:
- "--config"
- "/app/config.yaml"
- "--port"
- "4000"
ports:
- containerPort: 4000
env:
- name: REDIS_HOST
value: redis.llm.svc.cluster.local
- name: REDIS_PORT
value: "6379"
volumeMounts:
- name: config
mountPath: /app/config.yaml
subPath: config.yaml
readinessProbe:
httpGet:
path: /health/liveliness
port: 4000
periodSeconds: 10
volumes:
- name: config
configMap:
name: litellm-config
Service:
apiVersion: v1
kind: Service
metadata:
name: litellm
namespace: llm
spec:
selector:
app: litellm
ports:
- port: 4000
targetPort: 4000
LiteLLM 자체도 Kubernetes에서는 ConfigMap + Secret + Deployment + Service 형태를 공식 예시로 제공하고 있으며, production 구성에서는 Redis와 database 등을 이용할 수 있습니다. :chatgpt-content-reference{index="3"}
apiVersion: v1
kind: ConfigMap
metadata:
name: litellm-config
namespace: llm
data:
config.yaml: |
model_list:
- model_name: llama-70b
litellm_params:
model: openai/llama-70b
api_base: http://vllm-70b.llm.svc.cluster.local:8000/v1
api_key: dummy
max_parallel_requests: 8
- model_name: qwen-32b
litellm_params:
model: openai/qwen-32b
api_base: http://vllm-32b.llm.svc.cluster.local:8000/v1
api_key: dummy
max_parallel_requests: 16
- model_name: llama-8b
litellm_params:
model: openai/llama-8b
api_base: http://vllm-8b.llm.svc.cluster.local:8000/v1
api_key: dummy
max_parallel_requests: 32
router_settings:
num_retries: 0
default_max_parallel_requests: 16
이 부분이 중요합니다.
예를 들어:
Team A
├── User A1
├── User A2
└── User A3
Team B
├── User B1
└── User B2
라고 하면 LiteLLM DB에서 관리하는 것이 좋습니다.
예:
Team A
├─ TPM: 100,000
├─ RPM: 100
└─ Max Parallel: 10
Team B
├─ TPM: 30,000
├─ RPM: 30
└─ Max Parallel: 5
LiteLLM은 user/team/key 단위로 tpm_limit, rpm_limit, max_parallel_requests를 지원하고, team에 특정 model별 RPM/TPM 제한도 줄 수 있습니다. :chatgpt-content-reference{index="4"}
예를 들어 Team A:
curl -X POST http://litellm:4000/team/new \
-H "Authorization: Bearer $MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"team_id": "team-a",
"team_alias": "AI Research",
"tpm_limit": 100000,
"rpm_limit": 100,
"max_parallel_requests": 10,
"model_rpm_limit": {
"llama-70b": 20,
"qwen-32b": 50,
"llama-8b": 100
},
"model_tpm_limit": {
"llama-70b": 30000,
"qwen-32b": 50000,
"llama-8b": 100000
}
}'
이렇게 하면:
LiteLLM
│
┌───────────┴───────────┐
│ │
Team A Team B
│ │
┌───────┼───────┐ ┌────┴────┐
│ │ │ │ │
A1 A2 A3 B1 B2
│ │ │ │ │
└───────┴───────┘ └─────────┘
│ │
shared quota shared quota
가 됩니다.
현재 환경에서는 저는 LiteLLM API key를 사용자 인증의 중심으로 두지 않을 것입니다.
다음 구조가 더 적합합니다.
Keycloak
│
OIDC
│
▼
Cilium Gateway
│
JWT validation
│
▼
LiteLLM
│
user/team mapping
│
▼
vLLM
예를 들어 AD group이:
AI-RESEARCH
AI-ENGINEERING
AI-ADMIN
이라면:
AD Group
│
▼
Keycloak
│
└── JWT
│
├── user
├── groups
└── roles
그리고 gateway/LiteLLM에서 해당 사용자를:
youngkyoo
↓
AI-RESEARCH
↓
team-a
↓
llama-70b / qwen-32b / llama-8b
처럼 연결하는 형태입니다.
이 부분은 설계할 때 반드시 구분하는 게 좋습니다.
예를 들어:
Team A
TPM = 100K
max_parallel = 10
이라고 해도
GPU 사용량 = 10 GPU
라는 의미는 아닙니다.
실제로는:
Team A
│
max 10 concurrent
│
┌──────┼──────┐
▼ ▼ ▼
70B 32B 8B
TP4 TP2 TP1
│ │ │
4 GPU 2 GPU 1 GPU
입니다.
GPU resource allocation은 Kubernetes,
request concurrency는 LiteLLM/vLLM,
사용자/팀 quota는 LiteLLM입니다.
현재 B300 POC에서는 다음 4개를 별도로 관리하는 것을 추천합니다.
| 계층 | 제한 | 담당 |
|---|---|---|
| GPU | 4 GPU / 2 GPU / 1 GPU | Kubernetes |
| Inference concurrency | 8 / 16 / 32 | vLLM + LiteLLM |
| Team TPM/RPM | 100K / 50K 등 | LiteLLM |
| User quota | 개인별 TPM/RPM | LiteLLM |
그리고 vLLM 자체에도 concurrency/batching 관련 설정을 둡니다.
예를 들어:
LiteLLM
max_parallel_requests = 8
↓
vLLM
max_num_seqs = 8~16
↓
GPU
실제 KV cache / batching
이렇게 여러 단계의 admission control을 둡니다.
다만 두 값을 무조건 동일하게 맞출 필요는 없습니다.
예를 들어 나중에 70B TP4를 두 개 만들면:
GPU 0-3 → vLLM-70B-A
GPU 4-7 → vLLM-70B-B
LiteLLM은:
model_list:
- model_name: llama-70b
litellm_params:
model: openai/llama-70b
api_base: http://vllm-70b-a:8000/v1
max_parallel_requests: 8
tpm: 50000
rpm: 20
- model_name: llama-70b
litellm_params:
model: openai/llama-70b
api_base: http://vllm-70b-b:8000/v1
max_parallel_requests: 8
tpm: 50000
rpm: 20
처럼 같은 model_name 아래 여러 deployment를 둘 수 있습니다.
LiteLLM Router가 deployment들을 routing 대상으로 사용할 수 있고, RPM/TPM-aware routing 등의 전략도 제공합니다. :chatgpt-content-reference{index="5"}
이게 향후에는 상당히 중요합니다.
처음부터 너무 복잡하게 하지 않고:
┌──────────────┐
│ Keycloak AD │
└──────┬───────┘
│
▼
Cilium Gateway API
│
▼
┌─────────────┐
│ LiteLLM │
│ replicas=2 │
└──────┬──────┘
│
┌────────────────┼────────────────┐
▼ ▼ ▼
llama-70b qwen-32b llama-8b
TP4 TP2 TP1
│ │ │
4 GPU 2 GPU 1 GPU
└────────────────┴────────────────┘
│
GPU 7
spare
그리고 사용자 측에서는 모델별 URL을 알 필요 없이:
client = OpenAI(
base_url="https://llm.example.com/v1",
api_key="..."
)
client.chat.completions.create(
model="llama-70b",
...
)
처럼 사용하게 합니다.
현재 사용자가 약 7,000명 규모의 플랫폼을 염두에 두고 있다면, 개인별 GPU allocation을 만드는 것보다 Team → User → Model 3단계가 훨씬 관리하기 쉽습니다.
User
│
┌───────┴───────┐
│ │
Team A Team B
│ │
┌─────┼─────┐ ┌─┴─┐
│ │ │ │ │
A1 A2 A3 B1 B2
│ │ │ │ │
└─────┴─────┘ └───┘
│ │
▼ ▼
Model Policy Model Policy
│ │
┌─────┼─────┐ ┌─┴────┐
▼ ▼ ▼ ▼ ▼
70B 32B 8B 32B 8B
예를 들어:
| Team | 70B | 32B | 8B | 총 TPM | Max concurrent |
|---|---|---|---|---|---|
| AI Research | 30K | 50K | 100K | 180K | 10 |
| AI Engineering | 10K | 30K | 50K | 90K | 5 |
| General | - | 10K | 30K | 40K | 3 |
이렇게 GPU를 직접 사용자에게 배정하지 않고 API capacity를 배정합니다.
그리고 실제 GPU가 포화되면:
User
↓
Keycloak
↓
Gateway
↓
LiteLLM
↓
[quota/admission]
↓
vLLM
↓
[continuous batching]
↓
GPU
순서로 자연스럽게 제어됩니다.
앞서 제가 예로 든 --gpu-memory-utilization 0.85~0.90은 고정 권장값으로 보면 안 됩니다. 지금 하시는 Stage 3a의 context/concurrency/prefix-cache 테스트 결과를 가지고 모델별로 결정하는 것이 맞습니다. 특히 70B TP4와 32B TP2는 KV cache 요구량이 크게 달라질 수 있으므로, GPU allocation YAML은 고정하되 vLLM 메모리/sequence 설정은 benchmark 결과에 따라 별도로 튜닝하는 것이 좋습니다.
또 하나 중요한 것은 LiteLLM을 2 replica 이상으로 운영할 경우 Redis 기반의 shared rate-limit state를 같이 구성하는 것입니다. LiteLLM 문서상 여러 proxy instance에서 TPM/RPM/max-parallel 제한을 공유하려면 Redis가 사용되며, Redis가 없으면 제한이 instance별로 적용될 수 있습니다. :chatgpt-content-reference{index="6"}
즉, 최종적으로는 Kubernetes GPU allocation → vLLM → Service → LiteLLM deployment → Redis-backed Team/User quota → Keycloak/AD를 하나의 표준 템플릿으로 만들어두는 게 현재 B300 플랫폼에 가장 잘 맞습니다.