26O06c

QK·5일 전

지금 구조라면 GPU node를 기존 Compute Cluster에 그냥 추가하기보다는, GPU 전용 Kubernetes Cluster를 하나 더 만들고 기존 Compute / Storage / Admin과 역할을 분리하는 안을 우선 추천합니다.

즉 최종적으로는 4-cluster architecture입니다.

                         ┌──────────────────────────────┐
                         │        Admin Cluster         │
                         │                              │
                         │  CI/CD / GitOps              │
                         │  Keycloak / SSO              │
                         │  Cluster Management          │
                         │  Registry / Helm Repo        │
                         │  Monitoring / Logging(*)     │
                         └──────────────┬───────────────┘
                                        │
                         Management / GitOps / API
                                        │
            ┌───────────────────────────┼───────────────────────────┐
            │                           │                           │
            ▼                           ▼                           ▼
 ┌────────────────────┐     ┌────────────────────┐      ┌────────────────────┐
 │  Compute Cluster   │     │    GPU Cluster     │      │  Storage Cluster   │
 │                    │     │                    │      │                    │
 │ CPU workload       │     │ B300 GPU nodes    │      │ AIStor             │
 │ API / Backend      │     │ vLLM / inference  │      │ MinIO/S3            │
 │ preprocessing      │     │ training           │      │ durable dataset    │
 │ application        │     │ OCR/VLM(*)         │      │ model/checkpoint   │
 └─────────┬──────────┘     └─────────┬──────────┘      └─────────┬──────────┘
           │                          │                           │
           └──────────────────────────┼───────────────────────────┘
                                      │
                            Cilium ClusterMesh
                            BGP / Native Routing
                                      │
                           Ethernet L3 Fabric

여기서 중요한 것은 ClusterMesh는 service/workload connectivity를 제공하는 계층이고, AIStor의 대용량 S3 data path나 GPU의 NDR/IB fabric까지 무조건 ClusterMesh에 태우자는 의미는 아닙니다.


1. 각 Cluster 역할

저라면 경계를 다음처럼 잡겠습니다.

ClusterNode핵심 역할넣지 않을 것
Admin일반 CPUGitOps, CI/CD, Keycloak, Registry, cluster lifecycle, observabilityAI workload
ComputeCPU ComputeAPI/backend, preprocessing, orchestration, 일반 application대형 GPU serving
GPUB300vLLM, LLM/VLM inference, training, GPU batchAIStor
StorageStorage nodeAIStor/S3, model/dataset/checkpointapplication/GPU workload

현재 Compute와 Storage가 이미 ClusterMesh라면:

현재

Compute Cluster
      │
      │ Cilium ClusterMesh
      │
Storage Cluster

여기에 GPU cluster를:

                   Compute
                    /    \
                   /      \
                  /        \
               GPU ───── Storage

                 ClusterMesh

로 참여시키는 것입니다.

Admin cluster까지 반드시 동일한 ClusterMesh에 넣을 필요는 없습니다.

오히려 저는 Admin은 management plane으로 분리하는 쪽을 선호합니다.


2. Admin Cluster는 ClusterMesh와 분리하는 게 좋다

Admin cluster 역할을 보면:

Admin
 ├── Argo CD / GitOps
 ├── CI/CD
 ├── Keycloak
 ├── Registry
 ├── Helm repository
 ├── Cluster management
 └── Monitoring

이므로 application data plane과 성격이 다릅니다.

따라서:

                         Admin Cluster
                              │
                 Management Network
                              │
              ┌───────────────┼──────────────┐
              ▼               ▼              ▼
           Compute           GPU          Storage

로 관리하고,

ClusterMesh는:

       ┌──── Compute ────┐
       │                 │
       │   ClusterMesh   │
       │                 │
       GPU ───────── Storage

정도로 제한하는 것이 좋습니다.

이렇게 하면 GPU/Compute/Storage data plane에 문제가 발생해도 관리 plane의 blast radius를 줄일 수 있습니다.


3. GPU Cluster를 별도로 만드는 이유

기존 Compute Cluster에 GPU node를 추가하는 것도 기술적으로 가능합니다.

Compute Cluster

CPU node
CPU node
CPU node
GPU B300
GPU B300
GPU B300

하지만 지금 정도 규모/구조라면 추천하지 않습니다.

GPU node에는 다음처럼 일반 Compute와 상당히 다른 node-level 설정이 들어가기 때문입니다.

GPU Node

RHEL 10
 │
 ├─ NVIDIA Driver
 ├─ Container Toolkit
 ├─ GPU Operator
 ├─ NVIDIA Device Plugin
 ├─ DCGM
 ├─ NFD
 │
 ├─ CPU Manager = static
 ├─ Topology Manager = restricted
 │
 ├─ HugePages(optional)
 │
 ├─ NVLink / NVSwitch
 ├─ NCCL
 │
 ├─ NDR InfiniBand
 ├─ RDMA
 │
 └─ NVMe x8 local cache

운영 lifecycle 자체가 CPU compute node와 다릅니다.

특히 GPU driver/CUDA/NCCL/GPU Operator upgrade 때문에 GPU cluster의 maintenance cycle을 Compute와 독립시키는 가치가 큽니다.


4. GPU Cluster 내부 구성

저라면 GPU cluster는 최소 다음과 같이 만듭니다.

                 GPU Kubernetes Cluster

         ┌────────────────────────────┐
         │ Control Plane x3           │
         │                            │
         │ 일반 CPU server/VM        │
         │ GPU 없음                  │
         └──────────────┬─────────────┘
                        │
               Kubernetes API
                        │
        ┌───────────────┼─────────────────┐
        │               │                 │
        ▼               ▼                 ▼
   GPU Node 01      GPU Node 02       GPU Node N
   B300 x8          B300 x8           B300 x8

   NVMe x8          NVMe x8           NVMe x8
   RAID0            RAID0             RAID0
   XFS              XFS               XFS

   /model-cache     /model-cache      /model-cache

Control Plane을 B300 node 위에 올리는 것은 피합니다.


5. GPU node network는 최소 3가지 성격으로 분리

여기가 특히 중요합니다.

                         GPU Node
                             │
          ┌──────────────────┼───────────────────┐
          │                  │                   │
          ▼                  ▼                   ▼

    Management          Ethernet Data          NDR IB
       Network              Network             Fabric

   K8s API             Cilium/BGP             NCCL
   SSH/OOB             ClusterMesh            GPU↔GPU
   monitoring          AIStor/S3              RDMA
                       inference API

논리적으로:

Ethernet

GPU
 │
 ├── Pod Network
 ├── Service Network
 ├── Cilium
 ├── BGP
 ├── ClusterMesh
 │
 ├── Compute ↔ GPU
 └── GPU ↔ AIStor

현재 사용하는 Cilium native routing + BGP + ECMP를 이쪽에 그대로 확장하는 것이 자연스럽습니다.

InfiniBand/NDR

GPU Node 1
    │
   NDR
    │
GPU Node 2
    │
   NDR
    │
GPU Node N

여기는 ClusterMesh traffic용이 아니라 우선:

NCCL
MPI
GPU collective
RDMA

전용으로 봅니다.


6. GPU Pod에서는 multi-network가 필요해질 수 있다

일반 serving Pod:

vLLM Pod
   │
 eth0
   │
 Cilium
   │
Compute/API

만 있으면 됩니다.

하지만 multi-node GPU workload라면:

                  GPU Pod

              ┌─────┴─────┐
              │           │
            eth0         ib0
              │           │
           Cilium        NDR
              │           │
          API/S3       NCCL/RDMA

형태가 좋습니다.

따라서 GPU cluster에는 Multus + NVIDIA Network Operator / RDMA device plugin 계열을 검토할 가치가 있습니다.

즉:

Primary CNI
────────────
Cilium
 │
 └─ application/service traffic


Secondary Network
─────────────────
Multus
 │
 └─ IB/RDMA
       │
       └─ NCCL

입니다.

Cilium을 없애고 IB를 쓰는 게 아니라 용도가 다른 두 network를 Pod에 제공하는 구조입니다.


7. Compute → GPU inference path

예를 들어 Compute cluster의 backend가 GPU cluster의 vLLM을 호출한다면:

Compute Cluster

Application Pod
      │
      │ HTTP/gRPC
      ▼
Cilium
      │
      │ ClusterMesh
      ▼
GPU Cluster
      │
      ▼
Inference Service
      │
      ▼
vLLM Pod
      │
      ▼
B300

가 됩니다.

ClusterMesh를 이미 운영 중이라면 이 구조가 자연스럽습니다.

서비스 이름도 global service/discovery 전략을 정해서:

llm-serving.gpu...

같은 논리 endpoint로 노출할 수 있습니다.

다만 모든 GPU Pod를 Compute에서 직접 접근시키기보다 GPU cluster에 Gateway/API 계층을 두는 것을 권합니다.

Compute
   │
   ▼
GPU Gateway / LB
   │
   ├── DeepSeek service
   ├── GLM service
   ├── Qwen service
   └── OCR service
          │
          ▼
        GPU Pod

이렇게 해야 backend가 GPU topology/Pod 배치를 몰라도 됩니다.


8. GPU → Storage path는 조금 다르게 봐야 한다

여기서 중요한 설계 포인트가 있습니다.

논리적으로는:

GPU Pod
   │
ClusterMesh
   │
AIStor Service

라고 만들 수 있습니다.

하지만 대규모 model/dataset/checkpoint S3 traffic까지 ClusterMesh service path에 의존할 필요는 없습니다.

저라면:

GPU Cluster
      │
      │ Ethernet L3
      │
      │ S3/HTTPS
      ▼
AIStor VIP / LB
      │
Storage Cluster

형태의 직접 routed data path를 우선 검토합니다.

즉:

Small/control/service traffic

Compute ←── ClusterMesh ──→ GPU
                         ↘ Storage


Bulk storage traffic

GPU =======================> AIStor
       L3 Ethernet / S3

입니다.

Cilium/BGP를 사용하고 있으므로 underlay routing을 잘 설계하면 이 방식과 궁합이 좋습니다.


9. Storage Cluster도 역할을 매우 좁게 유지

Storage cluster는:

Storage Kubernetes Cluster

Control Plane x3

AIStor Node
 ├ NVMe
 ├ NVMe
 ├ ...
 └ high-speed Ethernet

AIStor Node
 ├ NVMe
 └ ...

AIStor Node
 └ ...

로 유지합니다.

여기에 GPU workload나 일반 application을 넣지 않습니다.

그리고 bucket 역할은:

AIStor

s3://models/
s3://datasets/
s3://checkpoints/
s3://artifacts/

정도로 분리합니다.


10. Local NVMe와 AIStor 관계

GPU node에는 앞에서 정한:

NVMe x8
   │
 RAID0
   │
 XFS
   │
/model-cache

를 둡니다.

전체 storage hierarchy는:

                AIStor
           durable / source
                 │
                 │ S3
                 ▼
          GPU Local NVMe
          8× RAID0 + XFS
             cache/stage
                 │
                 ▼
              CPU RAM
                 │
                 ▼
             GPU HBM
                 │
            ┌────┴────┐
            │         │
        Weight       KV

가 됩니다.

AIStor = source of truth, local NVMe는 언제든 재생성 가능한 cache라는 원칙을 유지합니다.


11. Admin Cluster에서는 GitOps로 네 cluster를 통제

Air-gap이므로 이 구조가 특히 중요합니다.

                       Admin Cluster
                            │
          ┌─────────────────┼─────────────────┐
          │                 │                 │
       Git Repo        OCI Registry      Keycloak
          │                 │                 │
          └─────────────────┼─────────────────┘
                            │
                         GitOps
                            │
          ┌─────────────────┼──────────────────┐
          ▼                 ▼                  ▼
       Compute             GPU               Storage

Private registry에는:

NVIDIA GPU Operator
NVIDIA Network Operator
NVIDIA driver container
DCGM exporter
vLLM
NCCL
Cilium
AIStor
application images

등 필요한 모든 artifact를 mirror합니다.

GPU cluster가 인터넷을 직접 볼 필요가 없도록 합니다.


12. Observability도 Admin 쪽으로 집계

각 cluster에는 exporter/agent를 두고:

Compute
 Prometheus agent ─┐

GPU
 DCGM exporter ────┼──> Admin Observability
 Prometheus agent ─┤

Storage
 metrics agent ────┘

형태로 중앙 집계하는 게 좋습니다.

GPU에서는 특히:

GPU utilization
HBM usage
GPU temperature/power
NVLink traffic
PCIe traffic
ECC
XID error
GPU throttling

CPU NUMA
local NVMe throughput

NCCL
IB/RDMA counters

model latency
TTFT
TPOT
tokens/sec
KV-cache utilization

까지 같이 봐야 합니다.

그래야 GPU utilization이 떨어졌을 때:

AIStor?
    ↓
Ethernet?
    ↓
NVMe?
    ↓
CPU/DataLoader?
    ↓
GPU?
    ↓
NVLink/NCCL?

중 어디가 병목인지 찾을 수 있습니다.


13. 최종적으로 제가 권하는 전체 구조

현재 환경을 크게 뜯어고치지 않고 GPU를 추가한다면 이 형태가 가장 자연스럽습니다.

                           ADMIN CLUSTER
                  ┌──────────────────────────┐
                  │ CI/CD / GitOps           │
                  │ Keycloak                 │
                  │ Registry / Helm          │
                  │ Cluster Management       │
                  │ Observability            │
                  └────────────┬─────────────┘
                               │
                       Management Plane
                               │
         ┌─────────────────────┼─────────────────────┐
         │                     │                     │
         ▼                     ▼                     ▼

 ┌───────────────┐     ┌────────────────┐     ┌───────────────┐
 │ COMPUTE       │     │ GPU CLUSTER    │     │ STORAGE       │
 │ CLUSTER       │     │                │     │ CLUSTER       │
 │               │     │ B300 x8/node   │     │               │
 │ CPU workload  │     │                │     │ AIStor        │
 │ backend       │     │ vLLM           │     │ S3            │
 │ API           │     │ LLM/VLM        │     │ model         │
 │ preprocess    │     │ training       │     │ dataset       │
 │               │     │                │     │ checkpoint    │
 └───────┬───────┘     └───────┬────────┘     └───────┬───────┘
         │                     │                      │
         │              Cilium ClusterMesh           │
         └─────────────────────┼──────────────────────┘
                               │
                       Ethernet Fabric
                      BGP + ECMP + L3
                               │
                 ┌─────────────┴────────────┐
                 │                          │
            Service traffic             S3 bulk
                                           │
                                    GPU ↔ AIStor


                   Separate NDR IB Fabric

               GPU Node ───────── GPU Node
                   │                 │
                   └──── NDR IB ─────┘
                         NCCL/RDMA

여기서 제가 특히 설계 원칙으로 고정할 것은 Admin=Management, Compute=CPU application, GPU=accelerated workload, Storage=durable object storage의 4-way separation입니다. 그리고 Cilium ClusterMesh는 Compute/GPU/Storage의 서비스 연결, Ethernet L3 fabric은 AIStor 같은 bulk data path, NDR IB는 GPU collective/RDMA라는 식으로 네트워크 역할도 분리합니다.

추가로 GPU cluster kubelet은 앞에서 이야기한 CPU Manager=static, Topology Manager=restricted, scope=pod를 baseline으로 하고, GPU Operator/NFD/DCGM 및 필요 시 Network Operator+Multus/RDMA를 얹는 구조가 좋습니다. 이 정도면 이후 B300 증설이나 GPU driver/CUDA 업그레이드가 기존 Compute/Storage cluster에 미치는 영향도 상당히 줄일 수 있습니다.

===

가능합니다. 지금 요구사항이면 GPU Cluster 안에 “Inference Platform” 계층을 하나 만드는 것이 좋습니다. 사용자는 개별 vLLM Pod를 직접 호출하지 않고, 항상 Inference Gateway를 통해 접근하게 합니다.

핵심 구조는 아래처럼 잡겠습니다.

                    ┌──────────────────────────────┐
                    │        Admin Cluster         │
                    │                              │
                    │ Keycloak / GitOps / CI/CD    │
                    │ Model Schedule / Policy      │
                    │ Observability / Registry     │
                    └──────────────┬───────────────┘
                                   │
                         configuration / identity
                                   │
                                   ▼
┌──────────────────────────────── GPU Cluster ───────────────────────────────┐
│                                                                            │
│ Users / Compute Cluster                                                    │
│          │                                                                 │
│          ▼                                                                 │
│ ┌─────────────────────┐                                                    │
│ │ Inference Gateway   │                                                    │
│ │                     │                                                    │
│ │ OIDC / Keycloak     │                                                    │
│ │ API Key             │                                                    │
│ │ User/Team Quota     │                                                    │
│ │ RPM / TPM Limit     │                                                    │
│ │ Model ACL           │                                                    │
│ │ Routing             │                                                    │
│ └──────────┬──────────┘                                                    │
│            │                                                               │
│     ┌──────┴────────────────────────────────┐                              │
│     │             Model Router              │                              │
│     │                                       │                              │
│     │ model alias → active deployment       │                              │
│     └──────┬────────────────────────────────┘                              │
│            │                                                               │
│   ┌────────┴────────────────────────────────────────────────────────┐      │
│   │                    GPU Serving Pool                             │      │
│   │                                                                 │      │
│   │  DeepSeek    GLM       Qwen      gpt-oss     PaddleOCR         │      │
│   │   vLLM       vLLM      vLLM       vLLM        VLM              │      │
│   │                                                                 │      │
│   │      GPU HBM ─── KV cache / Prefix cache                       │      │
│   │          │                                                      │      │
│   │          └────────── MemKV (optional L2 KV)                     │      │
│   └──────────────────────────┬──────────────────────────────────────┘      │
│                              │                                             │
│                    ┌─────────▼──────────┐                                  │
│                    │ Local NVMe x8     │                                  │
│                    │ RAID0 + XFS       │                                  │
│                    │                  │                                  │
│                    │ model-cache     │                                  │
│                    │ staging        │                                  │
│                    │ scratch        │                                  │
│                    └─────────┬──────────┘                                  │
└──────────────────────────────┼─────────────────────────────────────────────┘
                               │ S3
                               ▼
                    ┌─────────────────────┐
                    │   Storage Cluster   │
                    │                     │
                    │       AIStor        │
                    │                     │
                    │ models/             │
                    │ datasets/           │
                    │ artifacts/          │
                    │ checkpoints/        │
                    │ Memory Bucket (*)   │
                    └─────────────────────┘

AIStor 자체는 inference engine이 아니라 object/data tier입니다. 공식 문서도 AIStor가 모델 inference를 실행하는 것이 아니라 accelerator가 사용하는 데이터를 공급하는 계층이라고 명확히 구분합니다. MinIO AIStor Documentation

1. 사용자에게는 하나의 API만 보여주는 것을 권장

사용자가 이런 식으로 각 서비스를 직접 호출하게 만들지 않는 게 좋습니다.

deepseek-service:8000
glm-service:8000
qwen-service:8000
...

대신:

                   inference.company.local
                            │
                            ▼
                     Inference Gateway
                            │
           ┌────────────────┼─────────────────┐
           ▼                ▼                 ▼
       DeepSeek            GLM              Qwen

로 만듭니다.

가능하면 API도 OpenAI-compatible 형태로 통일합니다.

POST /v1/chat/completions

model: deepseek-flash
model: glm-flash
model: qwen
model: gpt-oss

그러면 client는 backend가 vLLM인지 다른 inference engine인지 알 필요가 없습니다.


2. Gateway에서 사용자별 사용량을 통제

Keycloak은 이미 Admin cluster에 있으므로 적극 활용할 수 있습니다.

User
 │
 ▼
Keycloak
 │
 │ JWT
 ▼
Inference Gateway
 │
 ├─ identity
 ├─ group/team
 ├─ allowed models
 ├─ RPM
 ├─ TPM
 ├─ concurrency
 └─ daily/monthly token quota

예를 들어 정책을:

GroupModelRPMTPMConcurrent일 사용량
team-AGLM60500K1020M token
team-ADeepSeek30300K510M
team-BQwen1001M2050M
batchGLM105M4200M

처럼 관리합니다.

단순 request count보다 token 단위 quota가 중요합니다.

request A = 500 tokens
request B = 50,000 tokens

은 GPU 비용이 전혀 다르기 때문입니다.

따라서 최소한:

RPM   requests/min
TPM   tokens/min
Concurrent requests
Max input tokens
Max output tokens
Daily token quota

정도는 Gateway에서 제어하는 것을 권합니다.


3. 모델 이름과 실제 Deployment도 분리

사용자에게:

glm-5.3-flash-fp8-tp4-ep4-v20261001

같은 실제 deployment 이름을 노출하면 운영하기 어렵습니다.

논리 alias를 둡니다.

사용자

model="glm-flash"
       │
       ▼
 Model Router
       │
       └──> glm-5.3-flash-fp8-v3

그러면 모델 교체도:

glm-flash
   │
   ├─ old → GLM 5.3 Flash v2
   │
   └─ new → GLM 5.3 Flash v3

처럼 backend만 바꾸면 됩니다.

이 구조가 주간/야간 모델 전환에도 핵심입니다.


4. 주간/야간 전환은 CronJob 하나보다 Controller 방식

예를 들어:

주간 08:00~22:00

GPU0~3     DeepSeek-V4.1-Flash
GPU4~7     GLM-5.3-Flash

+ OCR/Docling 별도 resource


야간 22:00~08:00

GPU0~3     GLM-5.3
GPU4~5     Qwen
GPU6       gpt-oss
GPU7       spare/replica

라고 합시다.

단순히 22:00에:

scale day models = 0
scale night models = 1

하면 안 됩니다.

모델 loading 시간이 있기 때문입니다.

제가 권하는 전환은:

21:30
 │
 ├─ Night model prefetch
 │      AIStor → Local NVMe
 │
21:45
 │
 ├─ GPU allocation 준비
 │
 ├─ model load
 │      NVMe → RAM → HBM
 │
 └─ warm-up
 │
21:55
 │
 ├─ readiness check
 └─ test inference
 │
22:00
 │
 ├─ Model Router switch
 │
 │     day → night
 │
 └─ 신규 request → Night Model
 │
22:00+
 │
 ├─ Day Model request drain
 │
 └─ Day Model unload

즉 Blue/Green deployment와 비슷하게 생각하면 됩니다.


5. 그래서 Model Lifecycle Controller를 하나 두는 게 좋다

Admin/GitOps에는 모델 schedule을 선언합니다.

예를 들면 개념적으로:

day:
  start: "08:00"
  models:
    - deepseek-v4.1-flash
    - glm-5.3-flash
    - paddleocr-vl
    - docling

night:
  start: "22:00"
  models:
    - glm-5.3
    - qwen3.6-35b-a3b
    - gpt-oss-20b

Model Lifecycle Controller가 이를 보고:

Schedule
   │
   ▼
Model Lifecycle Controller
   │
   ├── prefetch
   ├── cache validation
   ├── deployment
   ├── GPU allocation
   ├── warmup
   ├── readiness
   ├── route switch
   ├── drain
   └── unload

을 수행하게 합니다.

그러면 단순 scheduler보다 훨씬 안전합니다.


6. AIStor → Local NVMe → HBM을 명확하게 계층화

모델 weight는:

              COLD / Durable

                  AIStor
                    │
                 S3 GET
                    │
                    ▼
             Local NVMe
             /model-cache
                    │
                    ▼
                 RAM
                    │
                    ▼
                GPU HBM

               HOT / Fast

입니다.

AIStor가 source of truth입니다.

s3://models/

  deepseek/
    v4.1-flash/
      manifest.json
      config.json
      tokenizer/
      weights/

  glm/
    5.3-flash/
    5.3/

  qwen/
    3.6-35b-a3b/

  gpt-oss/
    20b/

Local NVMe는:

/model-cache/

  deepseek-v4.1-flash/
  glm-5.3-flash/
  glm-5.3/
  qwen3.6/
  gpt-oss/

입니다.

Local NVMe는 cache일 뿐 authoritative storage가 아닙니다.


7. Local NVMe cache는 시간표를 알기 때문에 LRU보다 똑똑하게 운영 가능

이게 네 환경의 큰 장점입니다.

보통 cache는:

LRU

로 관리하지만 여기서는 다음에 필요한 모델을 이미 알고 있습니다.

따라서:

19:00

/model-cache

Day models
████████████

Night models
████████
     ↑
     미리 존재

시키는 것이 훨씬 좋습니다.

NVMe capacity가 충분하다면 주간+야간 모델을 전부 cache에 유지하는 게 최선입니다.

AIStor
   │
   │ 최초 1회 / version 변경 시
   ▼
Local NVMe

├── Day model set
└── Night model set

        ↓

시간 전환 시
NVMe → HBM만 수행

그러면 매일 AIStor에서 수백 GB~TB를 다시 가져올 이유가 없습니다.


8. Cache key는 모델 이름보다 version/hash

예를 들어:

/model-cache/
   sha256-AAAA/
       weights...

와 같이 관리합니다.

AIStor에:

models/glm-5.3/manifest.json

version: 2026-10-01
sha256: AAAA...

가 있다면 controller가:

AIStor manifest
       │
       ▼
Local cache manifest
       │
       ├─ same hash
       │     → HIT
       │
       └─ different
             → DOWNLOAD

하게 합니다.

Air-gap 환경에서는 특히 재현성과 artifact integrity 면에서 유리합니다.


9. MemKV는 model cache가 아니라 KV cache tier

여기서는 역할을 정확히 분리해야 합니다.

Model Weight Path
─────────────────

AIStor
   ↓
Local NVMe
   ↓
GPU HBM


KV Path
─────────────────

GPU HBM
   ↓
MemKV

즉 MemKV에 model weight를 저장하려는 게 아닙니다.

MemKV는 inference KV state의 external tier입니다.

현재 MinIO MemKV는 NVIDIA NIXL을 통해 inference framework와 연결하고, distributed RDMA+NVMe 구성뿐 아니라 GPU node에 co-locate하는 구성도 제공합니다. MinIO AIStor Documentation


10. KV hierarchy는 이렇게 설계

                   GPU
                    │
            ┌───────▼───────┐
            │ HBM KV Cache  │
            │     L1        │
            └───────┬───────┘
                    │
               cache pressure
                    │
            ┌───────▼───────┐
            │     MemKV     │
            │      L2       │
            │               │
            │ RAM / NVMe    │
            │ RDMA/NIXL     │
            └───────────────┘

이게 특히 유리한 workload는:

긴 system prompt
긴 document/RAG context
multi-turn conversation
agent loop
동일 prefix 반복

입니다.

MemKV 공식 sizing 문서도 long-context, shared-prefix, multi-turn, HBM prefix cache보다 큰 working set을 주된 유효 영역으로 설명합니다. 반대로 prompt가 대부분 고유하거나 HBM에 전부 들어가면 external KV tier 자체가 overhead가 될 수 있습니다. MinIO AIStor Documentation

따라서 모든 모델에 무조건 MemKV를 켜지는 않겠습니다.


11. 예를 들어 모델별로

초기 정책은 이런 식이 좋습니다.

Model/workloadHBM KVMemKV이유
DeepSeek long-contextOOKV reuse 가능성
GLM agent/RAGOOlong context/multi-turn
Qwen chatOPoCworkload에 따라
gpt-oss short chatO△HBM으로 충분할 수 있음
PaddleOCROXKV externalization 이득 작음
Docling-X해당 없음

MemKV 자체 benchmark에서도 모델과 concurrency에 따라 효과 차이가 상당히 크므로, TTFT / throughput / KV hit ratio를 측정해서 모델별 enable하는 게 맞습니다. MinIO AIStor Documentation


12. AIStor Memory(AIMem)는 조금 다른 위치

여기는 MemKV와 혼동하면 안 됩니다.

AIStor Memory는 LLM inference KV cache가 아닙니다.

현재 AIStor Memory는 agent의 workspace/long-term memory를 AIStor Memory Bucket에 저장하고, local NVMe를 staging/read cache로 사용해 파일 형태로 제공하는 구조입니다. MinIO AIStor Documentation

따라서:

                 Inference Platform

                     LLM
                      │
             ┌────────┴────────┐
             │                 │
         KV Cache           Agent Memory
             │                 │
           MemKV             AIMem
             │                 │
      fast inference       persistent
          state              state
                               │
                               ▼
                             AIStor

로 구분하면 정확합니다.


13. AIMem은 Agent 서비스가 있을 때 넣는다

예를 들어 사용자별 AI agent가:

사용자 A

conversation
documents
preferences
agent workspace
generated files

를 세션을 넘어 유지해야 한다면 AIMem이 유용합니다.

User A
  │
Agent Pod
  │
  ├── LLM inference ─────── GPU/vLLM
  │
  └── /workspace
          │
         AIMem
          │
    local NVMe cache
          │
          ▼
   AIStor Memory Bucket

AIStor Memory는 local directory를 staging + read cache로 사용하고 cache hit 시 local disk에서 FUSE passthrough로 읽습니다. MinIO AIStor Documentation

그래서 일반 inference API에 AIMem을 억지로 넣을 필요는 없습니다.

Agentic AI를 서비스할 때 추가하는 계층입니다.


14. 최종 cache hierarchy

결국 네 환경에서는 서로 다른 세 가지 cache가 존재합니다.

                       GPU HBM
                 ┌─────────────────┐
                 │ Model Weight    │
                 │ KV Cache L1     │
                 └───────┬─────────┘
                         │
               ┌─────────┴─────────┐
               │                   │
             MemKV            Local NVMe
           KV Cache L2        Model Cache
               │                   │
               │                   │
          conversation         Model Weight
          prefix/KV            staging
               │                   │
               └─────────┬─────────┘
                         │
                       AIStor
                  durable storage

AIMem은 별도로:

Agent
  │
AIMem
  │
Local NVMe
  │
AIStor Memory Bucket

입니다.


15. AIStor 자체 cache와 GPU local cache도 다른 것

AIStor에도 object access용 cache 기능이 있지만, 이것을 GPU node의 /model-cache와 동일시하면 안 됩니다.

AIStor cache는 object-store server 쪽 cache이고, 현재 문서상 drive별 accessed-object metadata 등을 node memory에 cache하며 memory 한도도 관리합니다. MinIO AIStor Documentation

우리가 설계한:

GPU node
/model-cache

는 GPU workload를 위해 직접 관리하는 model staging cache입니다.

따라서 두 cache는 동시에 존재할 수 있습니다.


16. 사용량 측정은 Gateway + GPU 양쪽에서

Gateway:

requests/user
tokens/user
model/user
latency
TTFT
TPOT
errors
quota rejection

GPU/vLLM:

tokens/sec
batch size
queue
KV utilization
prefix hit
GPU utilization
HBM

MemKV:

KV hit
KV miss
read BW
write BW
RDMA BW

그리고 DCGM:

GPU utilization
HBM
power
temperature
NVLink
PCIe
XID

를 수집합니다.

Admin cluster의 Prometheus/Grafana 계열로 중앙 집계하면:

User
 ↓
Gateway
 ↓
Model
 ↓
GPU
 ↓
KV

를 하나의 request ID로 추적할 수 있습니다.


17. 장애/전환 구조도 중요

예를 들어 Night GLM warm-up이 실패했다고 해서 22:00에 Day GLM을 내려버리면 안 됩니다.

Controller state machine을:

PREFETCH
    ↓
VERIFY
    ↓
LOAD
    ↓
WARMUP
    ↓
HEALTHY?
  /     \
NO      YES
│        │
ABORT   SWITCH
│        │
keep     ↓
old    DRAIN OLD
model     ↓
        UNLOAD

로 만드는 게 좋습니다.

즉 schedule은 전환을 시작하는 trigger일 뿐, traffic switch는 health condition에 의해 결정되어야 합니다.


18. 최종 권장 구조

전체를 합치면 저는 이 그림을 목표 architecture로 잡겠습니다.

 Users / Applications
          │
          ▼
┌──────────────────────────┐
│    Inference Gateway     │
│                          │
│ Keycloak/OIDC            │
│ API Key                  │
│ Model ACL                │
│ RPM / TPM                │
│ Token Quota              │
│ Concurrency Limit        │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│       Model Router       │◀──────── Model Lifecycle Controller
└────────────┬─────────────┘             │
             │                           │ schedule
             │                           │ prefetch
             │                           │ warmup
             │                           │ switch/drain
             ▼                           │
┌───────────────────────────────────────────────────────────┐
│                     GPU Serving Pool                      │
│                                                           │
│ DeepSeek       GLM          Qwen          gpt-oss         │
│                                                           │
│          vLLM / inference runtime                         │
│                     │                                     │
│               GPU HBM                                     │
│           Weight + KV L1                                  │
│                     │                                     │
│                 MemKV L2                                  │
│              NIXL / RDMA                                  │
└─────────────────────┬─────────────────────────────────────┘
                      │
             ┌────────▼─────────┐
             │ Local NVMe x8   │
             │ RAID0 + XFS     │
             │                 │
             │ /model-cache   │
             │ /scratch       │
             └────────┬────────┘
                      │
                      │ S3 / high-speed Ethernet
                      ▼
             ┌──────────────────┐
             │      AIStor      │
             │                  │
             │ Models           │
             │ Datasets         │
             │ Artifacts        │
             │ Checkpoints      │
             │ Memory Buckets   │◀── AIMem / Agents
             └──────────────────┘

AIStor S3 data path는 우선 기존 high-speed Ethernet을 사용하고, 실제 model staging이 병목이면 S3 over RDMA를 Phase 2로 PoC할 수 있습니다. 현재 AIStor는 Kubernetes에서 RDMA 전용 server image와 single/multi-NIC topology를 공식 지원합니다. MinIO AIStor Documentation

그리고 air-gap 환경에서는 이 모든 이미지와 Helm chart를 Admin cluster의 private registry에 mirror해서 GitOps로 배포하는 게 좋습니다. AIStor도 private registry와 air-gap 배포 절차를 공식 지원합니다. MinIO AIStor Documentation

결국 핵심은 Gateway → Router → Serving → HBM/MemKV → local NVMe → AIStor의 계층화와, 별도의 Model Lifecycle Controller가 주/야간 전환을 책임지는 구조입니다. 이 구조라면 나중에 GPU node가 늘어나도 사용자 API/쿼터 계층은 그대로 두고 serving pool만 수평 확장할 수 있습니다.

===

가능합니다. 지금 요구사항이면 GPU Cluster 안에 “Inference Platform” 계층을 하나 만드는 것이 좋습니다. 사용자는 개별 vLLM Pod를 직접 호출하지 않고, 항상 Inference Gateway를 통해 접근하게 합니다.

핵심 구조는 아래처럼 잡겠습니다.

                    ┌──────────────────────────────┐
                    │        Admin Cluster         │
                    │                              │
                    │ Keycloak / GitOps / CI/CD    │
                    │ Model Schedule / Policy      │
                    │ Observability / Registry     │
                    └──────────────┬───────────────┘
                                   │
                         configuration / identity
                                   │
                                   ▼
┌──────────────────────────────── GPU Cluster ───────────────────────────────┐
│                                                                            │
│ Users / Compute Cluster                                                    │
│          │                                                                 │
│          ▼                                                                 │
│ ┌─────────────────────┐                                                    │
│ │ Inference Gateway   │                                                    │
│ │                     │                                                    │
│ │ OIDC / Keycloak     │                                                    │
│ │ API Key             │                                                    │
│ │ User/Team Quota     │                                                    │
│ │ RPM / TPM Limit     │                                                    │
│ │ Model ACL           │                                                    │
│ │ Routing             │                                                    │
│ └──────────┬──────────┘                                                    │
│            │                                                               │
│     ┌──────┴────────────────────────────────┐                              │
│     │             Model Router              │                              │
│     │                                       │                              │
│     │ model alias → active deployment       │                              │
│     └──────┬────────────────────────────────┘                              │
│            │                                                               │
│   ┌────────┴────────────────────────────────────────────────────────┐      │
│   │                    GPU Serving Pool                             │      │
│   │                                                                 │      │
│   │  DeepSeek    GLM       Qwen      gpt-oss     PaddleOCR         │      │
│   │   vLLM       vLLM      vLLM       vLLM        VLM              │      │
│   │                                                                 │      │
│   │      GPU HBM ─── KV cache / Prefix cache                       │      │
│   │          │                                                      │      │
│   │          └────────── MemKV (optional L2 KV)                     │      │
│   └──────────────────────────┬──────────────────────────────────────┘      │
│                              │                                             │
│                    ┌─────────▼──────────┐                                  │
│                    │ Local NVMe x8     │                                  │
│                    │ RAID0 + XFS       │                                  │
│                    │                  │                                  │
│                    │ model-cache     │                                  │
│                    │ staging        │                                  │
│                    │ scratch        │                                  │
│                    └─────────┬──────────┘                                  │
└──────────────────────────────┼─────────────────────────────────────────────┘
                               │ S3
                               ▼
                    ┌─────────────────────┐
                    │   Storage Cluster   │
                    │                     │
                    │       AIStor        │
                    │                     │
                    │ models/             │
                    │ datasets/           │
                    │ artifacts/          │
                    │ checkpoints/        │
                    │ Memory Bucket (*)   │
                    └─────────────────────┘

AIStor 자체는 inference engine이 아니라 object/data tier입니다. 공식 문서도 AIStor가 모델 inference를 실행하는 것이 아니라 accelerator가 사용하는 데이터를 공급하는 계층이라고 명확히 구분합니다. MinIO AIStor Documentation

1. 사용자에게는 하나의 API만 보여주는 것을 권장

사용자가 이런 식으로 각 서비스를 직접 호출하게 만들지 않는 게 좋습니다.

deepseek-service:8000
glm-service:8000
qwen-service:8000
...

대신:

                   inference.company.local
                            │
                            ▼
                     Inference Gateway
                            │
           ┌────────────────┼─────────────────┐
           ▼                ▼                 ▼
       DeepSeek            GLM              Qwen

로 만듭니다.

가능하면 API도 OpenAI-compatible 형태로 통일합니다.

POST /v1/chat/completions

model: deepseek-flash
model: glm-flash
model: qwen
model: gpt-oss

그러면 client는 backend가 vLLM인지 다른 inference engine인지 알 필요가 없습니다.


2. Gateway에서 사용자별 사용량을 통제

Keycloak은 이미 Admin cluster에 있으므로 적극 활용할 수 있습니다.

User
 │
 ▼
Keycloak
 │
 │ JWT
 ▼
Inference Gateway
 │
 ├─ identity
 ├─ group/team
 ├─ allowed models
 ├─ RPM
 ├─ TPM
 ├─ concurrency
 └─ daily/monthly token quota

예를 들어 정책을:

GroupModelRPMTPMConcurrent일 사용량
team-AGLM60500K1020M token
team-ADeepSeek30300K510M
team-BQwen1001M2050M
batchGLM105M4200M

처럼 관리합니다.

단순 request count보다 token 단위 quota가 중요합니다.

request A = 500 tokens
request B = 50,000 tokens

은 GPU 비용이 전혀 다르기 때문입니다.

따라서 최소한:

RPM   requests/min
TPM   tokens/min
Concurrent requests
Max input tokens
Max output tokens
Daily token quota

정도는 Gateway에서 제어하는 것을 권합니다.


3. 모델 이름과 실제 Deployment도 분리

사용자에게:

glm-5.3-flash-fp8-tp4-ep4-v20261001

같은 실제 deployment 이름을 노출하면 운영하기 어렵습니다.

논리 alias를 둡니다.

사용자

model="glm-flash"
       │
       ▼
 Model Router
       │
       └──> glm-5.3-flash-fp8-v3

그러면 모델 교체도:

glm-flash
   │
   ├─ old → GLM 5.3 Flash v2
   │
   └─ new → GLM 5.3 Flash v3

처럼 backend만 바꾸면 됩니다.

이 구조가 주간/야간 모델 전환에도 핵심입니다.


4. 주간/야간 전환은 CronJob 하나보다 Controller 방식

예를 들어:

주간 08:00~22:00

GPU0~3     DeepSeek-V4.1-Flash
GPU4~7     GLM-5.3-Flash

+ OCR/Docling 별도 resource


야간 22:00~08:00

GPU0~3     GLM-5.3
GPU4~5     Qwen
GPU6       gpt-oss
GPU7       spare/replica

라고 합시다.

단순히 22:00에:

scale day models = 0
scale night models = 1

하면 안 됩니다.

모델 loading 시간이 있기 때문입니다.

제가 권하는 전환은:

21:30
 │
 ├─ Night model prefetch
 │      AIStor → Local NVMe
 │
21:45
 │
 ├─ GPU allocation 준비
 │
 ├─ model load
 │      NVMe → RAM → HBM
 │
 └─ warm-up
 │
21:55
 │
 ├─ readiness check
 └─ test inference
 │
22:00
 │
 ├─ Model Router switch
 │
 │     day → night
 │
 └─ 신규 request → Night Model
 │
22:00+
 │
 ├─ Day Model request drain
 │
 └─ Day Model unload

즉 Blue/Green deployment와 비슷하게 생각하면 됩니다.


5. 그래서 Model Lifecycle Controller를 하나 두는 게 좋다

Admin/GitOps에는 모델 schedule을 선언합니다.

예를 들면 개념적으로:

day:
  start: "08:00"
  models:
    - deepseek-v4.1-flash
    - glm-5.3-flash
    - paddleocr-vl
    - docling

night:
  start: "22:00"
  models:
    - glm-5.3
    - qwen3.6-35b-a3b
    - gpt-oss-20b

Model Lifecycle Controller가 이를 보고:

Schedule
   │
   ▼
Model Lifecycle Controller
   │
   ├── prefetch
   ├── cache validation
   ├── deployment
   ├── GPU allocation
   ├── warmup
   ├── readiness
   ├── route switch
   ├── drain
   └── unload

을 수행하게 합니다.

그러면 단순 scheduler보다 훨씬 안전합니다.


6. AIStor → Local NVMe → HBM을 명확하게 계층화

모델 weight는:

              COLD / Durable

                  AIStor
                    │
                 S3 GET
                    │
                    ▼
             Local NVMe
             /model-cache
                    │
                    ▼
                 RAM
                    │
                    ▼
                GPU HBM

               HOT / Fast

입니다.

AIStor가 source of truth입니다.

s3://models/

  deepseek/
    v4.1-flash/
      manifest.json
      config.json
      tokenizer/
      weights/

  glm/
    5.3-flash/
    5.3/

  qwen/
    3.6-35b-a3b/

  gpt-oss/
    20b/

Local NVMe는:

/model-cache/

  deepseek-v4.1-flash/
  glm-5.3-flash/
  glm-5.3/
  qwen3.6/
  gpt-oss/

입니다.

Local NVMe는 cache일 뿐 authoritative storage가 아닙니다.


7. Local NVMe cache는 시간표를 알기 때문에 LRU보다 똑똑하게 운영 가능

이게 네 환경의 큰 장점입니다.

보통 cache는:

LRU

로 관리하지만 여기서는 다음에 필요한 모델을 이미 알고 있습니다.

따라서:

19:00

/model-cache

Day models
████████████

Night models
████████
     ↑
     미리 존재

시키는 것이 훨씬 좋습니다.

NVMe capacity가 충분하다면 주간+야간 모델을 전부 cache에 유지하는 게 최선입니다.

AIStor
   │
   │ 최초 1회 / version 변경 시
   ▼
Local NVMe

├── Day model set
└── Night model set

        ↓

시간 전환 시
NVMe → HBM만 수행

그러면 매일 AIStor에서 수백 GB~TB를 다시 가져올 이유가 없습니다.


8. Cache key는 모델 이름보다 version/hash

예를 들어:

/model-cache/
   sha256-AAAA/
       weights...

와 같이 관리합니다.

AIStor에:

models/glm-5.3/manifest.json

version: 2026-10-01
sha256: AAAA...

가 있다면 controller가:

AIStor manifest
       │
       ▼
Local cache manifest
       │
       ├─ same hash
       │     → HIT
       │
       └─ different
             → DOWNLOAD

하게 합니다.

Air-gap 환경에서는 특히 재현성과 artifact integrity 면에서 유리합니다.


9. MemKV는 model cache가 아니라 KV cache tier

여기서는 역할을 정확히 분리해야 합니다.

Model Weight Path
─────────────────

AIStor
   ↓
Local NVMe
   ↓
GPU HBM


KV Path
─────────────────

GPU HBM
   ↓
MemKV

즉 MemKV에 model weight를 저장하려는 게 아닙니다.

MemKV는 inference KV state의 external tier입니다.

현재 MinIO MemKV는 NVIDIA NIXL을 통해 inference framework와 연결하고, distributed RDMA+NVMe 구성뿐 아니라 GPU node에 co-locate하는 구성도 제공합니다. MinIO AIStor Documentation


10. KV hierarchy는 이렇게 설계

                   GPU
                    │
            ┌───────▼───────┐
            │ HBM KV Cache  │
            │     L1        │
            └───────┬───────┘
                    │
               cache pressure
                    │
            ┌───────▼───────┐
            │     MemKV     │
            │      L2       │
            │               │
            │ RAM / NVMe    │
            │ RDMA/NIXL     │
            └───────────────┘

이게 특히 유리한 workload는:

긴 system prompt
긴 document/RAG context
multi-turn conversation
agent loop
동일 prefix 반복

입니다.

MemKV 공식 sizing 문서도 long-context, shared-prefix, multi-turn, HBM prefix cache보다 큰 working set을 주된 유효 영역으로 설명합니다. 반대로 prompt가 대부분 고유하거나 HBM에 전부 들어가면 external KV tier 자체가 overhead가 될 수 있습니다. MinIO AIStor Documentation

따라서 모든 모델에 무조건 MemKV를 켜지는 않겠습니다.


11. 예를 들어 모델별로

초기 정책은 이런 식이 좋습니다.

Model/workloadHBM KVMemKV이유
DeepSeek long-contextOOKV reuse 가능성
GLM agent/RAGOOlong context/multi-turn
Qwen chatOPoCworkload에 따라
gpt-oss short chatO△HBM으로 충분할 수 있음
PaddleOCROXKV externalization 이득 작음
Docling-X해당 없음

MemKV 자체 benchmark에서도 모델과 concurrency에 따라 효과 차이가 상당히 크므로, TTFT / throughput / KV hit ratio를 측정해서 모델별 enable하는 게 맞습니다. MinIO AIStor Documentation


12. AIStor Memory(AIMem)는 조금 다른 위치

여기는 MemKV와 혼동하면 안 됩니다.

AIStor Memory는 LLM inference KV cache가 아닙니다.

현재 AIStor Memory는 agent의 workspace/long-term memory를 AIStor Memory Bucket에 저장하고, local NVMe를 staging/read cache로 사용해 파일 형태로 제공하는 구조입니다. MinIO AIStor Documentation

따라서:

                 Inference Platform

                     LLM
                      │
             ┌────────┴────────┐
             │                 │
         KV Cache           Agent Memory
             │                 │
           MemKV             AIMem
             │                 │
      fast inference       persistent
          state              state
                               │
                               ▼
                             AIStor

로 구분하면 정확합니다.


13. AIMem은 Agent 서비스가 있을 때 넣는다

예를 들어 사용자별 AI agent가:

사용자 A

conversation
documents
preferences
agent workspace
generated files

를 세션을 넘어 유지해야 한다면 AIMem이 유용합니다.

User A
  │
Agent Pod
  │
  ├── LLM inference ─────── GPU/vLLM
  │
  └── /workspace
          │
         AIMem
          │
    local NVMe cache
          │
          ▼
   AIStor Memory Bucket

AIStor Memory는 local directory를 staging + read cache로 사용하고 cache hit 시 local disk에서 FUSE passthrough로 읽습니다. MinIO AIStor Documentation

그래서 일반 inference API에 AIMem을 억지로 넣을 필요는 없습니다.

Agentic AI를 서비스할 때 추가하는 계층입니다.


14. 최종 cache hierarchy

결국 네 환경에서는 서로 다른 세 가지 cache가 존재합니다.

                       GPU HBM
                 ┌─────────────────┐
                 │ Model Weight    │
                 │ KV Cache L1     │
                 └───────┬─────────┘
                         │
               ┌─────────┴─────────┐
               │                   │
             MemKV            Local NVMe
           KV Cache L2        Model Cache
               │                   │
               │                   │
          conversation         Model Weight
          prefix/KV            staging
               │                   │
               └─────────┬─────────┘
                         │
                       AIStor
                  durable storage

AIMem은 별도로:

Agent
  │
AIMem
  │
Local NVMe
  │
AIStor Memory Bucket

입니다.


15. AIStor 자체 cache와 GPU local cache도 다른 것

AIStor에도 object access용 cache 기능이 있지만, 이것을 GPU node의 /model-cache와 동일시하면 안 됩니다.

AIStor cache는 object-store server 쪽 cache이고, 현재 문서상 drive별 accessed-object metadata 등을 node memory에 cache하며 memory 한도도 관리합니다. MinIO AIStor Documentation

우리가 설계한:

GPU node
/model-cache

는 GPU workload를 위해 직접 관리하는 model staging cache입니다.

따라서 두 cache는 동시에 존재할 수 있습니다.


16. 사용량 측정은 Gateway + GPU 양쪽에서

Gateway:

requests/user
tokens/user
model/user
latency
TTFT
TPOT
errors
quota rejection

GPU/vLLM:

tokens/sec
batch size
queue
KV utilization
prefix hit
GPU utilization
HBM

MemKV:

KV hit
KV miss
read BW
write BW
RDMA BW

그리고 DCGM:

GPU utilization
HBM
power
temperature
NVLink
PCIe
XID

를 수집합니다.

Admin cluster의 Prometheus/Grafana 계열로 중앙 집계하면:

User
 ↓
Gateway
 ↓
Model
 ↓
GPU
 ↓
KV

를 하나의 request ID로 추적할 수 있습니다.


17. 장애/전환 구조도 중요

예를 들어 Night GLM warm-up이 실패했다고 해서 22:00에 Day GLM을 내려버리면 안 됩니다.

Controller state machine을:

PREFETCH
    ↓
VERIFY
    ↓
LOAD
    ↓
WARMUP
    ↓
HEALTHY?
  /     \
NO      YES
│        │
ABORT   SWITCH
│        │
keep     ↓
old    DRAIN OLD
model     ↓
        UNLOAD

로 만드는 게 좋습니다.

즉 schedule은 전환을 시작하는 trigger일 뿐, traffic switch는 health condition에 의해 결정되어야 합니다.


18. 최종 권장 구조

전체를 합치면 저는 이 그림을 목표 architecture로 잡겠습니다.

 Users / Applications
          │
          ▼
┌──────────────────────────┐
│    Inference Gateway     │
│                          │
│ Keycloak/OIDC            │
│ API Key                  │
│ Model ACL                │
│ RPM / TPM                │
│ Token Quota              │
│ Concurrency Limit        │
└────────────┬─────────────┘
             │
             ▼
┌──────────────────────────┐
│       Model Router       │◀──────── Model Lifecycle Controller
└────────────┬─────────────┘             │
             │                           │ schedule
             │                           │ prefetch
             │                           │ warmup
             │                           │ switch/drain
             ▼                           │
┌───────────────────────────────────────────────────────────┐
│                     GPU Serving Pool                      │
│                                                           │
│ DeepSeek       GLM          Qwen          gpt-oss         │
│                                                           │
│          vLLM / inference runtime                         │
│                     │                                     │
│               GPU HBM                                     │
│           Weight + KV L1                                  │
│                     │                                     │
│                 MemKV L2                                  │
│              NIXL / RDMA                                  │
└─────────────────────┬─────────────────────────────────────┘
                      │
             ┌────────▼─────────┐
             │ Local NVMe x8   │
             │ RAID0 + XFS     │
             │                 │
             │ /model-cache   │
             │ /scratch       │
             └────────┬────────┘
                      │
                      │ S3 / high-speed Ethernet
                      ▼
             ┌──────────────────┐
             │      AIStor      │
             │                  │
             │ Models           │
             │ Datasets         │
             │ Artifacts        │
             │ Checkpoints      │
             │ Memory Buckets   │◀── AIMem / Agents
             └──────────────────┘

AIStor S3 data path는 우선 기존 high-speed Ethernet을 사용하고, 실제 model staging이 병목이면 S3 over RDMA를 Phase 2로 PoC할 수 있습니다. 현재 AIStor는 Kubernetes에서 RDMA 전용 server image와 single/multi-NIC topology를 공식 지원합니다. MinIO AIStor Documentation

그리고 air-gap 환경에서는 이 모든 이미지와 Helm chart를 Admin cluster의 private registry에 mirror해서 GitOps로 배포하는 게 좋습니다. AIStor도 private registry와 air-gap 배포 절차를 공식 지원합니다. MinIO AIStor Documentation

결국 핵심은 Gateway → Router → Serving → HBM/MemKV → local NVMe → AIStor의 계층화와, 별도의 Model Lifecycle Controller가 주/야간 전환을 책임지는 구조입니다. 이 구조라면 나중에 GPU node가 늘어나도 사용자 API/쿼터 계층은 그대로 두고 serving pool만 수평 확장할 수 있습니다.

===

아니요. K8s + Cilium + AIStor만으로 “돌아가게” 만들 수는 있지만, 앞에서 요구한 멀티유저, 사용자/팀별 quota, OpenAI-compatible API, 모델별 접근제어, 주/야간 모델 routing까지 직접 구현해야 해서 운영 부담이 커집니다.

현재 구조에는 LiteLLM 같은 AI Gateway를 하나 추가하는 것을 추천합니다. 다만 LiteLLM이 GPU-aware load balancing까지 전부 맡게 하기보다는 역할을 분리하는 편이 좋습니다.

추천 Stack

                        Users / Applications
                                │
                                ▼
                    ┌──────────────────────┐
                    │       LiteLLM        │
                    │      AI Gateway      │
                    │                      │
 Keycloak ─────────>│ Auth / User / Team   │
                    │ Virtual API Key      │
                    │ Model ACL            │
                    │ RPM / TPM            │
                    │ Concurrency          │
                    │ Usage / Quota        │
                    │ OpenAI-compatible API│
                    └──────────┬───────────┘
                               │
                        logical model
                               │
             ┌─────────────────┼──────────────────┐
             │                 │                  │
             ▼                 ▼                  ▼
        deepseek           glm-flash            qwen
             │                 │                  │
             └─────────────────┼──────────────────┘
                               ▼
                ┌─────────────────────────┐
                │ K8s Inference Routing   │
                │                         │
                │ Gateway API             │
                │ Inference Extension     │
                │ / EPP                   │
                └────────────┬────────────┘
                             │
                GPU/KV-aware endpoint 선택
                             │
              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
          vLLM #1        vLLM #2        vLLM #N
              │              │              │
              └──────────────┼──────────────┘
                             │
                    B300 / NVSwitch
                             │
                   HBM / KV Cache
                             │
                       ┌─────┴─────┐
                       │           │
                    MemKV     Local NVMe
                                 │
                              AIStor

LiteLLM은 user/team/key별 RPM, TPM, 최대 parallel request 및 budget 등을 제공하므로 앞서 말한 멀티테넌트 quota 계층을 직접 개발할 필요를 크게 줄여줍니다. 다만 budget/virtual-key 기능은 DB가 필요하므로 air-gap 내부 PostgreSQL도 stack에 포함해야 합니다. LiteLLM

LiteLLM과 Cilium의 역할은 겹치지 않습니다

이 구분이 중요합니다.

Cilium
────────────────────────────
Network / CNI
NetworkPolicy
BGP
ClusterMesh
Service connectivity
Gateway 기반 network ingress

            ≠

LiteLLM
────────────────────────────
AI API Gateway
User / Team
API Key
Model ACL
RPM / TPM
Token usage
Quota
Logical model routing
OpenAI-compatible API

따라서 Cilium이 있다고 LiteLLM이 불필요해지는 것은 아닙니다.

반대로 LiteLLM을 넣는다고 Cilium이 하던 일을 대체하는 것도 아닙니다.


그리고 LiteLLM 뒤에 K8s Inference Gateway를 검토할 가치가 큽니다

이건 제가 지금 시점이라면 꽤 적극적으로 PoC하겠습니다.

Kubernetes에는 이제 Gateway API Inference Extension이 있고, InferencePool은 현재 stable API입니다. 일반 HTTP load balancer와 달리 KV-cache utilization, queue 상태 등의 inference 정보를 이용해 적절한 model-server Pod를 선택할 수 있습니다. Kubernetes 게이트웨이 API 확장

예를 들어 vLLM replica가 4개라면 일반 LB는:

Request
   │
   ▼
Round Robin

vLLM1 → KV 90%
vLLM2 → KV 20%
vLLM3 → KV 70%
vLLM4 → KV 30%

상태를 모르고 보낼 수 있습니다.

Inference-aware routing은 개념적으로:

                 Request
                    │
                    ▼
            Endpoint Picker
                    │
        ┌───────────┼────────────┐
        │ KV usage              │
        │ queue                 │
        │ prefix cache          │
        ▼                       │
      vLLM2  ◀──────────────────┘
      KV 20%

같은 결정을 할 수 있습니다. Kubernetes Inference Extension 자체도 prefix-cache 상태나 LoRA availability 같은 model-serving 정보를 routing에 활용하도록 설계되어 있습니다. Kubernetes 게이트웨이 API 확장

즉 LiteLLM과 Inference Gateway도 서로 대체 관계가 아닙니다.

LiteLLM
"누가 어떤 모델을 얼마나 사용할 수 있는가?"
                │
                ▼
Inference Gateway/EPP
"그 요청을 어느 GPU/vLLM replica가 처리하는 게 좋은가?"

로 나누면 됩니다.


제가 추천하는 전체 software stack

계층솔루션역할추천
Container orchestrationKubernetes전체 workload필수
CNICiliumPod networking/BGP필수
Multi-clusterCilium ClusterMeshCompute↔GPU↔Storage필수
Identity기존 KeycloakOIDC/SSO필수
AI GatewayLiteLLM사용자/API key/quota/TPM/RPM추천
Gateway DBPostgreSQLLiteLLM state/usage추천
Inference routingGateway API Inference ExtensionGPU/KV-aware routing추천/PoC
Model servervLLM실제 LLM inference필수
GPU managementNVIDIA GPU Operatordriver/device plugin/DCGM필수
Object StorageAIStormodel/dataset/checkpoint필수
Model cacheNVMe RAID0+XFSlocal staging필수
KV L1vLLM HBMhot KV필수
KV L2MemKVexternal KVworkload별 PoC
Agent memoryAIMempersistent agent workspaceAgent 사용 시
ObservabilityPrometheus/Grafana/DCGMmetrics필수
GitOps현재 Admin CI/CD/GitOpslifecycle기존 사용
Model LifecycleArgo Workflow/자체 Controller 등주/야간 전환필요

vLLM 자체에서도 generation/prompt token, KV-cache usage, prefix-cache hit, external prefix-cache hit 등 production metrics를 제공하므로 이 routing/monitoring 계층과 연결하기 좋습니다. vLLM


다만 처음부터 전부 넣지는 않겠습니다

Phase 1은 최대한 단순하게 가는 게 좋습니다.

Users
  │
Keycloak
  │
LiteLLM
  │
  ▼
vLLM
  │
B300

Model:
AIStor → NVMe → HBM

KV:
HBM

여기까지 먼저 안정화합니다.

이 단계만으로도 사용자별 API key/model access/RPM/TPM/concurrency/usage 관리가 가능합니다. LiteLLM의 virtual key와 team 모델은 이런 multi-tenant control을 제공하도록 되어 있습니다. LiteLLM


Phase 2에서 inference-aware routing

GPU node가 늘어나고 동일 모델 replica가 여러 개 생기면:

LiteLLM
   │
   ▼
K8s Gateway API
Inference Extension
   │
   ▼
InferencePool
   │
 ┌─┼───────────┐
 ▼ ▼           ▼
vLLM1 vLLM2   vLLM3

를 넣습니다.

Kubernetes Inference Extension은 model-aware routing, serving priority, model rollout/traffic splitting, endpoint metrics 기반 routing을 목적으로 만들어져 있어서 네 요구사항과 상당히 잘 맞습니다. Kubernetes 게이트웨이 API 확장


Phase 3에서 MemKV

실제 workload를 측정해서:

long context
shared prefix
multi-turn
agent
RAG

        ↓

KV cache miss/recompute 비용이 큼

이면:

vLLM
 │
 ├─ HBM KV L1
 │
 └─ MemKV L2
       │
     RDMA

를 추가합니다.

vLLM 자체의 Automatic Prefix Caching도 있기 때문에 먼저 HBM prefix caching 효과를 측정하고 MemKV를 추가하는 게 맞습니다. vLLM의 prefix caching은 동일 prefix의 KV blocks를 재사용해 반복적인 prompt computation을 줄이는 방식입니다. vLLM


주/야간 전환은 LiteLLM에 맡기지 않는 것이 좋습니다

이 부분도 역할을 분리하겠습니다.

                    Model Lifecycle Controller
                              │
              ┌───────────────┼───────────────┐
              │               │               │
           AIStor          Kubernetes       LiteLLM
              │               │               │
          prefetch          deploy          route
              │               │               │
              ▼               ▼               ▼
           NVMe            vLLM Pod       model alias

예를 들어 22:00 야간 전환:

21:30  Night models
       AIStor → NVMe prefetch

21:40  checksum/version verify

21:45  Night vLLM deployment

21:50  NVMe → HBM load

21:55  warm-up
       health check

22:00  LiteLLM route/alias switch

22:00+ Day request drain

22:05  Day vLLM unload

이 workflow는 기존 Admin cluster의 GitOps + Argo Workflows/CronWorkflow 계열로 시작해도 충분합니다. 처음부터 custom Kubernetes Operator를 개발할 필요는 없습니다.


LiteLLM을 넣을지에 대한 제 결론

넣는 쪽을 추천합니다.

특히 네 요구사항 중:

여러 사용자
      +
사용자/팀별 제한
      +
모델별 접근권한
      +
OpenAI-compatible API
      +
사용량 측정

이 있기 때문에 그렇습니다.

K8s+Cilium만 가지고 이걸 구현하면 결국 별도의 API Gateway에서 JWT→사용자→모델 ACL→TPM/RPM→token accounting→quota DB를 직접 개발하게 됩니다. LiteLLM은 이 부분을 이미 제공합니다. LiteLLM

반대로 LiteLLM에게 GPU scheduling, NUMA, KV-aware replica selection, AIStor cache lifecycle까지 맡기려고 하면 안 됩니다.

최종적으로 역할을 이렇게 자르면 아주 명확합니다.

                ┌─────────────────────────────┐
                │           User              │
                └──────────────┬──────────────┘
                               ▼
Keycloak ────────────────► LiteLLM
                           │
                           │ WHO / HOW MUCH
                           │
                           ▼
                 Inference Gateway
                           │
                           │ WHICH REPLICA
                           │
                           ▼
                        vLLM
                           │
                           │ INFERENCE
             ┌─────────────┼──────────────┐
             │             │              │
           HBM KV       MemKV          NVMe
             │          KV L2        model cache
             │             │              │
             └─────────────┼──────────────┘
                           │
                         AIStor
                      durable data


Kubernetes
   └── scheduling / lifecycle

Cilium
   └── networking / BGP / ClusterMesh

NVIDIA GPU Operator
   └── GPU infrastructure

Model Lifecycle Controller
   └── Day ↔ Night automation

따라서 제가 잡을 1차 production baseline은 K8s + Cilium + NVIDIA GPU Operator + vLLM + LiteLLM + PostgreSQL + Keycloak + AIStor + Local NVMe + Prometheus/Grafana입니다. Gateway API Inference Extension은 replica가 많아지는 시점에 추가하고, MemKV는 KV reuse 측정 후 추가, AIMem은 Agent 서비스를 실제로 제공할 때 추가하는 순서가 과설계를 피하면서도 확장하기 좋습니다.

===

네. 둘을 같이 쓰면 이름 때문에 둘 다 “Gateway”처럼 보여 헷갈리는데, 관심사가 완전히 다릅니다.

가장 간단히 말하면:

LiteLLM = “이 사용자가 어떤 모델을 얼마나 사용할 수 있는가?”
Gateway API Inference Extension = “허용된 이 inference 요청을 어느 vLLM/GPU replica에 보내야 가장 효율적인가?”

입니다.

1. Gateway API Inference Extension이란?

Kubernetes의 일반적인 Service/LB는 inference workload의 내부 상태를 잘 모릅니다.

예를 들어 동일한 GLM 모델을 GPU node 4대에서 서비스한다고 해보겠습니다.

                  GLM Service

                      │
           ┌──────────┼──────────┐
           │          │          │
           ▼          ▼          ▼
        vLLM-A      vLLM-B     vLLM-C
        GPU0-3      GPU0-3     GPU0-3

Queue      20          2          8
KV Cache   90%        30%        60%
Prefix      X          O          X

일반적인 Kubernetes Service가 이런 inference 상태를 고려하지 않으면 요청을 단순하게 여러 endpoint에 분산할 수 있습니다.

문제는 LLM 요청은 동일한 비용을 갖지 않는다는 것입니다.

request A
input = 500 tokens

request B
input = 100,000 tokens

둘 다 HTTP request 하나지만 GPU가 처리해야 하는 양은 전혀 다릅니다.

더구나 vLLM-A에 사용자가 보내는 prompt의 prefix KV가 이미 존재한다면 A로 보내는 것이 훨씬 유리할 수도 있습니다.

Gateway API Inference Extension은 이런 LLM inference 특성을 고려해 endpoint를 선택하는 계층입니다.

Kubernetes Gateway API Inference Extension


2. 핵심 구성 요소는 InferencePool + EPP

개념적으로 보면 다음과 같습니다.

                  Client Request
                        │
                        ▼
                 Gateway / Route
                        │
                        ▼
               ┌──────────────────┐
               │  InferencePool   │
               │                  │
               │ GLM replicas     │
               └────────┬─────────┘
                        │
                        ▼
              ┌───────────────────┐
              │ EPP               │
              │ Endpoint Picker   │
              │                   │
              │ "어느 Pod로?"     │
              └─────────┬─────────┘
                        │
              ┌─────────┼──────────┐
              ▼         ▼          ▼
            vLLM-A    vLLM-B     vLLM-C
              │         │          │
             GPU       GPU        GPU

여기서 특히 중요한 것이 EPP(Endpoint Picker) 입니다.

EPP가 inference workload 정보를 이용해서 적절한 endpoint를 고르는 역할을 합니다.


3. 일반 Load Balancing과 무엇이 다른가?

일반적인 LB를 아주 단순화하면:

request 1 → Pod A
request 2 → Pod B
request 3 → Pod C
request 4 → Pod A

같은 접근입니다.

Inference-aware routing은 다음과 같은 정보를 활용할 수 있는 구조입니다.

Request
   │
   ▼
EPP
   │
   ├── model availability
   ├── request queue
   ├── KV/cache 관련 상태
   ├── serving capacity
   └── endpoint 상태
            │
            ▼
        best endpoint

그래서 LLM inference에서 중요한 latency, GPU utilization, KV reuse 등을 개선할 가능성이 생깁니다.


4. 특히 Prefix/KV cache 때문에 중요하다

예를 들어 사용자들이 공통으로 아주 긴 system prompt를 사용한다고 합시다.

System prompt 20K tokens
        +
user prompt

Pod A에 이미 이 prefix에 대한 cache가 있다면:

vLLM-A

[20K system prompt KV]
████████████████████

→ HIT

반면 Pod B에는 없다면:

vLLM-B

[empty]

→ 다시 계산

일 수 있습니다.

따라서 단순히:

GPU utilization 낮은 Pod

를 고르는 것만이 항상 최선은 아닙니다.

LLM에서는 경우에 따라:

prefix/KV locality
        +
queue
        +
GPU capacity
        +
model availability

를 같이 고려해야 합니다.

이런 이유로 Kubernetes 쪽에서 일반적인 HTTP load balancing과 inference-aware load balancing을 분리하려는 것입니다.


5. 네 환경에서는 어디에 들어가는가?

우리가 지금 설계한 구조에 넣으면:

                    Users
                      │
                      ▼
                  LiteLLM
                      │
                      │
                model="glm"
                      │
                      ▼
             Gateway API / Route
                      │
                      ▼
                InferencePool
                      │
                      ▼
                     EPP
                      │
       ┌──────────────┼───────────────┐
       │              │               │
       ▼              ▼               ▼
   GLM Pod-1       GLM Pod-2       GLM Pod-3
    vLLM            vLLM            vLLM
       │              │               │
     GPU             GPU             GPU

라고 보면 됩니다.

즉 LiteLLM이 굳이:

Pod-1의 KV cache가 83%이고 Pod-2의 queue가 3이니 Pod-2로 보내자.

같은 GPU-level scheduling까지 책임질 필요가 없습니다.

그건 아래 inference routing layer가 담당하도록 분리하는 겁니다.


6. 그러면 LiteLLM은 정확히 무엇을 하는가?

LiteLLM은 GPU scheduler라기보다 AI API Gateway라고 이해하는 게 좋습니다.

LiteLLM 공식 문서

네 환경에서 제가 LiteLLM에게 맡기고 싶은 것은 크게 다음입니다.

기능LiteLLM
OpenAI-compatible APIO
API KeyO
사용자/Team 관리O
모델 접근 권한O
RPM 제한O
TPM 제한O
Budget/사용량 관리O
모델 logical aliasO
요청/비용 accountingO
GPU 선택X
NUMA 선택X
GPU schedulingX
NVLink/NVSwitch 관리X
Kubernetes schedulingX
AIStor model cache 관리X
주/야간 model lifecycle 전체X

즉 North-South의 AI API control plane 역할에 가깝습니다.


7. Keycloak과 LiteLLM의 관계

Keycloak이 이미 있으므로 역할을 중복시키지 않습니다.

                 User
                   │
                   ▼
               Keycloak
                   │
             Authentication
                   │
                  JWT
                   │
                   ▼
               LiteLLM
                   │
            Authorization /
             AI Policy

역할을 구분하면:

Keycloak
────────────────────────
"당신은 누구인가?"

user = kim
group = AI-Team-A


LiteLLM
────────────────────────
"그 사람이 AI를 어떻게 사용할 수 있는가?"

Team-A
 ├─ DeepSeek     allowed
 ├─ GLM          allowed
 ├─ Qwen         denied
 │
 ├─ RPM          100
 ├─ TPM          1M
 └─ Budget       ...

이런 식입니다.

Keycloak을 identity provider로 유지하고 AI-specific policy는 LiteLLM에서 관리하는 것이 깔끔합니다.


8. LiteLLM의 중요한 역할: API 표준화

뒤에서는 모델별 serving 방식이 달라도 됩니다.

DeepSeek
    ↓
vLLM

GLM
    ↓
vLLM

Qwen
    ↓
vLLM

PaddleOCR
    ↓
별도 inference runtime

사용자는 가능한 한 하나의 API를 사용합니다.

             LiteLLM

POST /v1/chat/completions

model="deepseek"
model="glm"
model="qwen"

따라서 나중에 backend가 바뀌어도 client application 변경을 최소화할 수 있습니다.


9. Logical model name도 매우 중요

예를 들어 실제 Kubernetes deployment가:

glm-5.3-flash-fp8-vllm-0.15-prod-v3

라고 해도 사용자는 그냥:

model = "glm-flash"

만 사용하게 합니다.

중간 mapping을:

glm-flash
     │
     ▼
glm-5.3-flash-v3

로 관리합니다.

새 모델을 배포하면:

glm-flash
     │
     ├──── old → GLM v3
     │
     └──── new → GLM v4

처럼 backend를 교체할 수 있습니다.


10. 주/야간 전환에서도 이게 유용하다

예를 들어 주간에는:

08:00 ~ 22:00

deepseek-flash
glm-flash
paddleocr

야간에는:

22:00 ~ 08:00

glm
qwen
gpt-oss

라고 합시다.

사용자가 Kubernetes Deployment를 알 필요는 없습니다.

Model Lifecycle Controller가:

21:30
AIStor → NVMe
night model prefetch

      ↓

21:45
vLLM Deployment

      ↓

21:50
NVMe → HBM

      ↓

21:55
warm-up

      ↓

health OK

까지 수행하고 나서 routing/API availability를 바꿉니다.

여기서 LiteLLM은 사용자가 볼 수 있는 모델과 logical endpoint를 제어하는 front door 역할을 할 수 있습니다.

다만 실제 Deployment 생성/삭제, prefetch, HBM load 등은 LiteLLM이 아니라 Kubernetes/GitOps/Workflow/Model Lifecycle Controller가 담당해야 합니다.


11. 그래서 전체 control flow를 세 단계로 생각하면 쉽다

사용자 kim이 GLM에 요청했다고 합시다.

① LiteLLM

kim
 │
 ▼
LiteLLM
 │
 ├─ kim 인증됐나?
 ├─ GLM 사용 권한 있나?
 ├─ quota 남았나?
 ├─ TPM 초과했나?
 └─ concurrent request 초과했나?
          │
          │ OK
          ▼

여기까지는 User/AI Policy 문제입니다.

② Inference Extension

       GLM request
           │
           ▼
     InferencePool
           │
           ▼
          EPP
           │
     ┌─────┼──────┐
     ▼     ▼      ▼
   Pod A  Pod B  Pod C

 queue     queue    queue
 cache     cache    cache
   │
   └──────► best endpoint

여기는 Serving optimization 문제입니다.

③ vLLM

request
   │
   ▼
vLLM
   │
   ├─ batching
   ├─ scheduling
   ├─ prefix cache
   ├─ KV management
   ├─ TP / EP
   │
   ▼
GPU

여기가 실제 inference execution입니다.


12. 그리고 Kubernetes Scheduler는 또 다른 역할이다

Inference Extension의 EPP와 Kubernetes Scheduler도 혼동하면 안 됩니다.

Kubernetes Scheduler

"vLLM Pod를 어느 Node에 띄울까?"

             ↓

GPU Node 03

반면:

Inference EPP

"이미 떠 있는 vLLM Pod 중
이 HTTP request를 어디로 보낼까?"

             ↓

vLLM Pod #7

입니다.

즉:

K8s Scheduler
     │
     │ Pod placement
     ▼
GPU Node


EPP
     │
     │ Request placement
     ▼
vLLM Pod

입니다.

이 차이가 굉장히 중요합니다.


13. Cilium Gateway와도 다른 개념이다

네 환경에서는 Cilium을 쓰고 있으니 이것도 구분해야 합니다.

Cilium
───────────────────────
CNI
NetworkPolicy
BGP
ClusterMesh
Gateway API implementation
Network connectivity


Inference Extension
───────────────────────
InferencePool
Endpoint Picker
LLM-aware request routing


LiteLLM
───────────────────────
AI API Gateway
User / Team
API Key
Quota
RPM / TPM
Model ACL
Usage


vLLM
───────────────────────
Model execution
Batching
KV cache
TP / EP
GPU inference

그래서 이것들을 경쟁 제품처럼 볼 필요가 없습니다.

서로 다른 layer를 담당합니다.


14. 우리가 설계 중인 전체 구조에 대입하면

제가 생각하는 목표 구조는 이겁니다.

                         ┌──────────────┐
                         │   Keycloak   │
                         │   Identity   │
                         └──────┬───────┘
                                │
                                ▼
Users ─────────────────────► LiteLLM
                         ┌───────────────┐
                         │ Auth / Team   │
                         │ Model ACL     │
                         │ RPM / TPM     │
                         │ Token Quota   │
                         │ Usage         │
                         │ Model Alias   │
                         └───────┬───────┘
                                 │
                                 ▼
                    Gateway API / HTTPRoute
                                 │
                                 ▼
                         InferencePool
                                 │
                                EPP
                                 │
                  ┌──────────────┼──────────────┐
                  │              │              │
                  ▼              ▼              ▼
               vLLM-1         vLLM-2         vLLM-3
                  │              │              │
                  └──────────────┼──────────────┘
                                 │
                         B300 GPU Pool
                                 │
                    ┌────────────┴────────────┐
                    │                         │
                HBM KV                    MemKV
                 L1                         L2
                    │                         │
                    └────────────┬────────────┘

                     Model Weight Path

                           AIStor
                              │
                           S3 GET
                              ▼
                       Local NVMe
                      /model-cache
                              │
                              ▼
                            RAM
                              │
                              ▼
                             HBM

그리고 이 옆에 별도의:

            Model Lifecycle Controller

                     │
          ┌──────────┼───────────┐
          │          │           │
       AIStor       K8s       LiteLLM
          │          │           │
       prefetch    deploy       route/
       verify      warmup       policy
          │          │           │
          └──────────┼───────────┘
                     │
               Day ↔ Night

가 있는 형태가 가장 명확합니다.

중요한 판단 하나

처음 구축할 때 Gateway API Inference Extension을 반드시 넣어야 하는 것은 아닙니다.

예를 들어 초기 환경이:

GLM → vLLM replica 1개
Qwen → vLLM replica 1개
DeepSeek → vLLM replica 1개

라면 EPP가 고를 endpoint 자체가 없습니다. 이 단계에서는:

Keycloak
   ↓
LiteLLM
   ↓
vLLM

이면 충분합니다.

반면 GPU node가 늘어서:

GLM

vLLM #1
vLLM #2
vLLM #3
vLLM #4

처럼 동일 모델 replica가 여러 개 생기는 시점부터 Inference Extension의 가치가 커집니다.

따라서 지금 프로젝트라면 1차 구축은 Keycloak → LiteLLM → vLLM로 단순하게 만들고, API/metric/interface는 Inference Extension을 나중에 끼울 수 있게 설계한 뒤, multi-node/multi-replica 확장 시 InferencePool + EPP를 추가하는 단계적 접근을 권합니다.

profile
engineer

0개의 댓글