26O01d

QK·약 21시간 전

네. 다만 “여러 사용자가 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 OperatorGPU 자원GPU 할당/격리, scheduling
vLLM추론 엔진batching, KV cache, prefix cache, TP
LiteLLMAI Gateway사용자 인증, API key, quota, RPM/TPM, model routing
Envoy Gateway/Cilium네트워크 GatewayTLS, JWT/OIDC, L7 routing, NetworkPolicy
KeycloakIdentity사용자/그룹/서비스 인증
Prometheus/DCGMObservabilityGPU/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

라고 이해하는 게 정확합니다.


그렇다면 GPU 자체를 여러 사용자가 공유하려면?

여기서 Kubernetes/NVIDIA 쪽이 필요합니다.

대표적인 방법은:

1. GPU를 모델별로 고정 할당

현재 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차 기준선으로 잡겠습니다.


2. GPU 하나를 여러 Pod가 time-slicing

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에 무작정 섞는 방식은 별개의 문제입니다.


3. MIG

MIG가 가능한 GPU에서는 GPU를 하드웨어 파티션으로 나눌 수도 있습니다.

하지만 현재 B300 8-GPU inference benchmark에서는 저는 MIG를 기본 구조로 두기보다는 MIG OFF 상태에서 먼저 검증하는 쪽이 좋습니다.

특히 TP4/TP8 모델은 여러 GPU를 하나의 inference instance로 묶어야 하므로 MIG와 궁합이 좋지 않은 경우가 많습니다.


그러면 LiteLLM은 왜 필요한가?

여러 사용자가 들어오면 단순히 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 플랫폼에서는 상당히 유용한 계층입니다.


다만 지금 환경에서는 LiteLLM 하나로 끝내면 안 됩니다

제가 권하는 구조는 오히려 다음에 가깝습니다.

                   ┌──────────────┐
                   │  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이 적합
모델별 routingLiteLLM이 적합
여러 vLLM deployment load balancingLiteLLM이 가능
GPU 자체 할당Kubernetes + NVIDIA GPU Operator
GPU isolationMIG / time-slicing / Pod allocation
inference batching/KV cachevLLM
인증/SSOKeycloak/AD + Gateway
network isolationCilium

현재 B300 환경이라면

저는 "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"}


1. 먼저 GPU allocation

예를 들어 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을 담당하도록 하는 것이 기본입니다.


2. 70B TP4 vLLM

예를 들어 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를 수행하게 하는 구조가 좋습니다.


3. 32B TP2

같은 방식입니다.

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

4. 8B TP1

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으로 검증하는 것이 좋습니다.


5. 이제 LiteLLM이 등장합니다

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와 동일하게 생각하면 안 됩니다.


6. LiteLLM은 별도 Kubernetes Deployment

예:

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"}


7. ConfigMap

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

8. 사용자 quota는 ConfigMap에 넣지 않습니다

이 부분이 중요합니다.

예를 들어:

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

가 됩니다.


9. 그러면 Keycloak은 어디에 들어가나?

현재 환경에서는 저는 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

처럼 연결하는 형태입니다.


10. 가장 중요한 부분: 사용자 quota ≠ GPU quota

이 부분은 설계할 때 반드시 구분하는 게 좋습니다.

예를 들어:

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입니다.


11. 그래서 실제 운영에서는 한 단계 더 추가하는 게 좋습니다

현재 B300 POC에서는 다음 4개를 별도로 관리하는 것을 추천합니다.

계층제한담당
GPU4 GPU / 2 GPU / 1 GPUKubernetes
Inference concurrency8 / 16 / 32vLLM + LiteLLM
Team TPM/RPM100K / 50K 등LiteLLM
User quota개인별 TPM/RPMLiteLLM

그리고 vLLM 자체에도 concurrency/batching 관련 설정을 둡니다.

예를 들어:

LiteLLM
  max_parallel_requests = 8
          ↓
vLLM
  max_num_seqs = 8~16
          ↓
GPU
  실제 KV cache / batching

이렇게 여러 단계의 admission control을 둡니다.

다만 두 값을 무조건 동일하게 맞출 필요는 없습니다.


12. 여러 vLLM replica가 생기면 더 중요해집니다

예를 들어 나중에 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"}

이게 향후에는 상당히 중요합니다.


13. 그런데 지금 B300 한 대에서는 이렇게 시작하는 것을 권합니다

처음부터 너무 복잡하게 하지 않고:

                  ┌──────────────┐
                  │  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",
    ...
)

처럼 사용하게 합니다.


제가 특히 권하고 싶은 quota 구조

현재 사용자가 약 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

예를 들어:

Team70B32B8B총 TPMMax concurrent
AI Research30K50K100K180K10
AI Engineering10K30K50K90K5
General-10K30K40K3

이렇게 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 플랫폼에 가장 잘 맞습니다.

profile
engineer

0개의 댓글