콘텐츠로 이동

VAST Data 통합 가이드

Continuum Router는 두 지점에서 VAST Data 스토리지와 연동됩니다: 응답 캐시 L2 티어, 그리고 서빙 엔진이 VAST로 오프로드한 KV 텐서를 추적하는 KV 캐시 인덱스입니다. 이 가이드는 두 연동 지점을 실용적인 배포 예시와 함께 설명하고, 분리형 prefill/decode 서빙 환경에서 VAST의 역할을 정리한 뒤 전체 프로덕션 설정 예시를 제시합니다.

VAST는 분리형 서빙의 prefill-decode 간 KV 전송 계층으로 사용되지 않습니다. prefill 워커에서 decode 워커로의 KV 블록 전송은 서빙 엔진이 직접 수행하며(예: Dynamo 배포의 워커 간 NIXL), 라우터는 참여할 두 워커만 선택합니다. 자세한 내용은 KV 전송을 참고하세요. 과거 이 역할을 위해 정의되었던 external_storage 필드는 레거시 호환용으로만 남아 있으며 레거시 external_storage 필드에서 설명합니다.

목차


VAST Data 연결 방법

VAST Data는 여러 스토리지 액세스 프로토콜을 제공합니다. Continuum Router는 응답 캐시 L2 저장을 위해 S3 호환 API만 직접 호출합니다. KV 캐시 연동은 서빙 엔진을 통해 이루어집니다. 엔진이 자체 커넥터 프로토콜로 KV 텐서를 오프로드하거나 다시 로드하면, 라우터는 VAST를 직접 읽지 않고 KV 캐시 이벤트를 수신해 텐서 위치를 추적합니다.

프로토콜 Continuum Router 사용 용도 VAST Data 기능 일반적인 대역폭 비고
S3 API (HTTP/HTTPS) 응답 캐시 L2 티어 VAST S3 게이트웨이 10–100 Gbps 표준 AWS S3 SDK 호환; 캐시된 응답 블롭 저장에 사용
HTTP 엔드포인트 라우터에서 미사용 VAST Element Store 10–100 Gbps 엔진 KV 커넥터가 오프로딩에 사용 가능; 레거시 external_storage 필드는 URL을 허용하지만 요청 경로에서 읽지 않음
NFS 라우터에서 직접 미사용 VAST Universal Storage 10–40 Gbps vLLM에서 모델 가중치 로드에 직접 사용 가능
NVMe-oF / RDMA 라우터에서 직접 미사용 VAST NVMe-over-Fabric 100–400 Gbps 초저지연 텐서 액세스를 위해 vLLM 백엔드에서 사용 가능

라우터 수준 연동에 필요한 VAST Data 리소스는 응답 캐시용 버킷과 자격 증명이 준비된 S3 호환 엔드포인트 하나뿐입니다. KV 오프로딩을 사용하려면 엔진 호스트에서 접근 가능한 VAST 엔드포인트를 라우터가 아니라 서빙 엔진에 직접 설정해야 합니다.


사전 요구사항

VAST Data 클러스터 요구사항

  • VAST Data 소프트웨어 버전 4.0 이상
  • 응답 캐시 통합을 위한 S3 게이트웨이 활성화
  • 워크로드에 맞는 충분한 스토리지 용량:
    • 응답 캐시: 고유 요청당 2–20 KB 추정, 수백만 개 항목 기준으로 산정
    • KV 텐서: 캐시된 프리픽스당 2 × num_layers × num_heads × head_dim × seq_len × 2 바이트 추정

자격 증명 및 액세스

  • 대상 버킷에 대한 읽기/쓰기 권한이 있는 S3 액세스 키와 시크릿 키
  • 사전에 생성된 버킷 (라우터는 버킷을 자동으로 생성하지 않음)
  • 각 라우터 인스턴스에서 VAST 클러스터로의 네트워크 경로

네트워크 요구사항

  • 라우터 호스트와 VAST S3 게이트웨이 간 L3 네트워크 연결
  • 라우터 호스트에서 VAST S3 게이트웨이로의 TCP 포트 443 또는 80 허용 방화벽 규칙 (응답 캐시용)
  • KV 오프로딩 사용 시: 각 엔진 호스트에서 KV 커넥터가 사용하는 VAST 엔드포인트로의 네트워크 경로 (대용량 텐서 전송을 위해 점보 프레임 권장). 라우터는 이 엔드포인트에 직접 연결하지 않음
  • NVMe-oF/RDMA 사용 시: 엔진 호스트의 전용 RDMA NIC 및 패브릭 (라우터 수준 연동에는 불필요)

환경 변수

민감한 자격 증명은 설정 파일에 직접 적는 대신 환경 변수로 주입하세요:

export VAST_ACCESS_KEY="your-access-key"
export VAST_SECRET_KEY="your-secret-key"

응답 캐시 S3 설정의 access_key와 secret_key 필드는 캐시 초기화 시 ${ENV_VAR} 참조를 자동으로 치환합니다.


예시: VAST 응답 캐시 (S3 API)

이 설정은 Redis를 핫 L1 캐시로, VAST Data S3를 영속적인 L2 캐시로 사용합니다. L1에 없는 응답은 백엔드를 호출하기 전에 VAST L2에서 먼저 조회하며, L2 적중 시 이후 요청을 빠르게 처리할 수 있도록 L1으로 다시 승격합니다.

동작 방식

  1. 클라이언트가 결정론적 요청(temperature = 0)을 전송
  2. 라우터가 요청 파라미터로부터 캐시 키를 계산
  3. L1(Redis) 조회 후 적중 시 즉시 응답 반환
  4. L1 미스 시 L2(VAST S3)를 조회하고, 적중 시 응답을 반환하면서 L1으로 승격
  5. 두 티어 모두 미스 시 백엔드를 호출하고 응답을 L1과 L2에 모두 저장

설정

response_cache:
  enabled: true

  # "tiered"로 L1 + L2 아키텍처 활성화
  backend: tiered

  # 모든 캐시 항목의 전역 TTL
  ttl: "24h"

  # 캐시 대상 최대 응답 본문 크기
  max_response_size: 1048576         # 1 MiB
  max_stream_buffer_size: 10485760   # 10 MiB

  # L1: Redis (핫 캐시 - 빠른 조회, 제한된 용량)
  l1:
    type: memory   # 분산 L1에는 "redis" 사용
    max_value_size: 1048576   # 1 MiB 초과 값은 L2로 직접 저장

  # l1.type이 "redis"일 때 L1에 사용되는 Redis 설정
  redis:
    url: "redis://redis-service:6379"
    pool_size: 16
    key_prefix: "cr:resp:"
    fallback_to_memory: true

  # L2: VAST Data S3 (웜 캐시 - 고용량, 내구성)
  l2:
    type: s3
    endpoint: "https://vast-s3.example.com"
    bucket: "llm-response-cache"
    key_prefix: "response-cache/"
    region: "us-east-1"
    access_key: "${VAST_ACCESS_KEY}"
    secret_key: "${VAST_SECRET_KEY}"
    # 선택 사항: L2 항목에 대한 TTL 재정의 (기본값: 전역 ttl 상속)
    ttl_override: "168h"

  # 계층형 캐시 승격 동작
  tiered:
    promote_on_hit: true       # L2 적중을 L1으로 승격
    l1_promotion_ttl: "30m"    # 승격된 L1 항목의 TTL

필드 참조

필드 설명
l2.type S3 호환 백엔드를 사용하려면 "s3"로 설정
l2.endpoint VAST S3 게이트웨이 URL (HTTP 또는 HTTPS)
l2.bucket 사전에 생성된 S3 버킷 이름
l2.key_prefix 버킷 내 키 프리픽스 (기본값: "response-cache/")
l2.region AWS 호환 리전 문자열 (기본값: "us-east-1")
l2.access_key S3 액세스 키 (${ENV_VAR} 치환 지원)
l2.secret_key S3 시크릿 키 (${ENV_VAR} 치환 지원, 로그에서 마스킹됨)
l2.ttl_override L2 항목의 선택적 TTL 재정의 (예: "168h", "24h")
tiered.promote_on_hit L2 적중 항목을 L1으로 복사할지 여부 (기본값: true)
tiered.l1_promotion_ttl 승격으로 생성된 L1 항목에 적용할 TTL (기본값: "5m")

예시: KV 텐서 오프로딩 (vLLM + VAST)

이 설정은 스토리지 오프로딩을 인식하는 KV 캐시 인덱스를 활성화합니다. vLLM이 GPU KV 텐서를 VAST로 오프로드하면 라우터는 해당 항목을 StorageWarm 티어로 추적하며, GPU 상주(GpuHot) 데이터보다 할인된 점수 가중치를 적용합니다.

동작 방식

  1. vLLM이 프롬프트의 KV 텐서를 계산하고 cache_created 이벤트를 발행 (GpuHot 티어)
  2. GPU 메모리 부족 시 vLLM이 텐서를 VAST로 오프로드하고 cache_offloaded 이벤트를 발행
  3. KV 인덱스가 해당 항목을 StorageWarm으로 다운그레이드
  4. 동일한 프리픽스를 가진 후속 요청이 들어오면 라우터가 GpuHot 대비 할인된 점수(storage_tier_weight)를 적용해 StorageWarm 데이터를 보유한 백엔드로 라우팅
  5. vLLM이 VAST에서 텐서를 다시 로드하고 cache_reloaded를 발행하면 인덱스가 다시 GpuHot으로 업그레이드

Continuum Router 설정

kv_cache_index:
  enabled: true
  backend: memory   # 멀티 인스턴스 배포에는 "redis" 사용

  # 고유 프롬프트 수 × 백엔드 수에 맞게 max_entries 조정
  max_entries: 500000

  # 항목은 15분 후 만료; vLLM 축출 속도에 따라 조정
  entry_ttl_seconds: 900

  scoring:
    overlap_weight: 0.6
    load_weight: 0.3
    health_weight: 0.1

    # 백엔드가 ≥30% 커버리지를 보유할 때만 KV 인식 라우팅 활성화
    min_overlap_threshold: 0.30

    # GPU 상주 데이터는 전체 overlap 점수 부여
    gpu_tier_weight: 1.0

    # 스토리지 오프로드 데이터는 가치 있지만 재로드 지연 발생 - 할인 적용
    storage_tier_weight: 0.6

  # GPU 핫 vs. VAST 웜 티어 추적
  storage_offloading:
    enabled: true
    # vLLM이 cache_created/cache_evicted만 내보낼 때 (cache_offloaded 없음),
    # 축출을 영구 제거가 아닌 VAST 오프로드로 처리
    treat_eviction_as_offload: true

  # 각 백엔드의 continuum-kv-listener SSE 스트림 구독
  event_sources:
    - backend_name: vllm-1
      endpoint: "http://kv-listener.internal:7817/events/vllm-1"
      reconnect_interval_ms: 5000

    - backend_name: vllm-2
      endpoint: "http://kv-listener.internal:7817/events/vllm-2"
      reconnect_interval_ms: 5000

vLLM 실행 명령어

vLLM이 continuum-kv-listener로 KV 이벤트를 발행하고 VAST Data로 텐서를 오프로드하도록 구성합니다:

vllm serve meta-llama/Llama-3.1-70B-Instruct \
  --host 0.0.0.0 \
  --port 8000 \
  --enable-prefix-caching \
  --kv-cache-dtype auto \
  --max-model-len 32768 \
  --kv-transfer-config '{"kv_connector":"LMCacheConnectorV1","kv_role":"kv_both"}'

주요 플래그:

  • --enable-prefix-caching: 백엔드에서 KV 프리픽스 캐싱을 활성화합니다.
  • --kv-cache-dtype auto: 캐시 스토리지에 모델의 기본 데이터 타입을 사용합니다.
  • --kv-transfer-config: 스토리지 오프로딩에 사용할 KV 커넥터를 선택합니다. 업스트림 vLLM에는 VAST 전용 내장 커넥터가 없으므로(커밋 8c1557a7 기준 vllm/distributed/kv_transfer/kv_connector/factory.py에 VastKVConnector 없음), 이 예시에서는 내장 LMCacheConnectorV1을 사용하고 LMCache 설정 파일에서 VAST 마운트 기반 디스크 백엔드를 지정합니다. 실제 운영 환경에서는 사용하는 커넥터 및 VAST 공식 문서의 설정 값을 따르세요.

또한 엔진이 tcp://kv-listener.internal:5557 같은 리스너 소스로 ZMQ msgpack KVEventBatch 프레임을 발행하도록 kv_events_config(또는 --kv-events-config)를 함께 설정해야 합니다.

vLLM은 /v1/kv_events 같은 HTTP 경로를 제공하지 않으므로 라우터는 엔진이 아니라 continuum-kv-listener의 SSE URL을 구독합니다. 리스너는 수신한 vLLM 블록 해시에서 토큰 프리픽스를 복원하고 라우터의 extract_prefix_key를 통해 SHA-256 프리픽스 키로 변환한 뒤 라우터에 전달합니다.

VAST 오프로딩 시 스코어링 동작

시나리오 티어 점수 배율 효과
GPU VRAM에 텐서 존재 GpuHot 1.0 (전체 점수) 최고 라우팅 우선순위
VAST로 텐서 오프로드됨 StorageWarm 0.6 (할인됨) 중간 라우팅 우선순위; 적중 시 vLLM이 재로드
텐서 캐시 없음 없음 0.0 설정된 기본 선택 전략으로 폴백

VAST와 함께 쓰는 분리형 Prefill/Decode

분리형 서빙은 prefill(프롬프트 처리)과 decode(토큰 생성) 단계를 서로 다른 워커로 분리합니다. prefill 중에 계산된 KV 블록은 서빙 엔진 자체의 전송 계층(Dynamo 배포의 워커 간 NIXL, 또는 NCCL 및 엔진 스토리지 티어)을 통해 prefill 워커에서 decode 워커로 직접 이동합니다. 라우터는 텐서 바이트를 읽거나 쓰지 않으며, 요청을 처리할 prefill 워커, decode 워커, 라우팅 경로만 선택합니다. 전체 아키텍처는 분리형 Prefill/Decode 서빙을 참고하세요.

따라서 VAST는 prefill-decode 간 직접 전송 경로에 관여하지 않습니다. 대신 통합형 배포와 마찬가지로 엔진이 KV 텐서를 오프로드하는 스토리지 티어로 동작하며, KV 캐시 인덱스가 이를 StorageWarm으로 추적합니다(KV 텐서 오프로딩 참고). fast-decode 경로는 프리픽스를 처음부터 다시 계산하는 대신 오프로드된 텐서를 스토리지에서 다시 로드할 decode 워커로 요청을 라우팅할 수 있습니다.

동작 방식

  1. 라우터가 요청의 프리픽스 키로 KV 인덱스를 조회 (prefix_routing.enabled: true 필요)
  2. decode 워커가 GPU 상주 텐서(GpuHot)를 보유한 경우 해당 워커로 직접 라우팅 (fast_decode)
  3. 엔진이 텐서를 VAST 등으로 오프로드한 경우(StorageWarm), 최소 부하의 정상 decode 워커로 라우팅하여 엔진이 스토리지 티어에서 텐서를 다시 로드하도록 함 (fast_decode)
  4. 캐시된 텐서가 없는 경우 prefill 워커와 decode 워커를 선택(prefill_then_decode)하고, 엔진이 자체 전송 계층으로 두 워커 간 KV 블록을 전달

범용 prefill-then-decode 와이어 프로토콜은 이번 릴리스에서 아직 제공되지 않습니다. 엔진 전용 피커가 없는 상태에서는 두 워커를 선택한 뒤 503 disaggregated_prefill_decode_unavailable을 반환하거나, fallback_to_unified가 켜져 있으면 통합형 서빙으로 폴백합니다.

현재 실제로 동작하는 분리형 배포는 direct 모드 shim 뒤에 구성된 Dynamo 플릿입니다. 이 구성에서는 라우터가 워커 쌍을 선택하고 Dynamo 프런트엔드가 prefill 홉, NIXL 전송, decode 홉을 실행합니다. 자세한 내용은 Direct 모드 shim을 통한 라우팅을 참고하세요.

설정

prefix_routing:
  enabled: true

kv_cache_index:
  enabled: true
  storage_offloading:
    enabled: true   # 엔진이 오프로드한 텐서(예: VAST)를 StorageWarm으로 추적

disaggregated_serving:
  enabled: true

  # prefill 연산 단계 타임아웃
  prefill_timeout: "60s"

  # 워커 간 엔진 소유 KV 전송 타임아웃
  kv_transfer_timeout: "15s"

  # 분리형 백엔드 사용 불가 시 통합형 백엔드로 폴백
  fallback_to_unified: true

backends:
  # Prefill 워커: 입력 프롬프트의 KV 텐서 계산
  - name: prefill-worker-1
    url: "http://vllm-prefill-1:8000"
    role: prefill

  - name: prefill-worker-2
    url: "http://vllm-prefill-2:8000"
    role: prefill

  # Decode 워커: 엔진이 전송한 KV 블록으로 토큰 생성
  - name: decode-worker-1
    url: "http://vllm-decode-1:8000"
    role: decode
    weight: 2

  - name: decode-worker-2
    url: "http://vllm-decode-2:8000"
    role: decode
    weight: 2

  - name: decode-worker-3
    url: "http://vllm-decode-3:8000"
    role: decode
    weight: 2

  # 통합형 폴백: 분리형 풀 사용 불가 시 두 단계 모두 처리
  - name: unified-fallback
    url: "http://vllm-unified:8000"
    role: unified

이 라우터 설정에는 VAST 엔드포인트가 포함되지 않습니다. 각 워커의 VAST 오프로딩은 KV 텐서 오프로딩 예시와 같이 서빙 엔진에서 설정하며, 오프로딩 이벤트는 kv_cache_index.event_sources를 통해 라우터에 전달됩니다.

워커 설정

prefill에서 decode로의 KV 전송은 라우터가 아니라 서빙 엔진에서 설정합니다. Dynamo 배포에서는 워커가 prefill 및 decode 분리 모드로 실행되며 NIXL을 통해 KV 블록을 주고받습니다. deploy/examples/dynamo-direct-shim/에서 GPU 없이 실행 가능한 예제 구성을 확인할 수 있습니다. KV 텐서를 VAST로도 오프로드하는 엔진은 전송 설정과 함께 스토리지 커넥터를 엔진에 구성하며, 라우터 설정은 동일하게 유지됩니다.

라우팅 경로 헤더

헤더 값 의미
X-Continuum-Routing-Path prefill_then_decode, fast_decode, unified, fallback 선택된 라우팅 경로
X-Continuum-Prefill-Backend 백엔드 이름 prefill 단계에 선택된 prefill 워커
X-Continuum-Decode-Backend 백엔드 이름 토큰 생성에 선택된 decode 워커

풀 크기 권장사항

  • decode 대 prefill 비율 3:1로 시작하세요. 일반적으로 decode 워커의 토큰 생성 시간이 prefill 워커의 프롬프트 처리 시간보다 길기 때문입니다.
  • 고유 시스템 프롬프트가 많아 프롬프트 다양성이 높은 워크로드에서는 prefill 풀을 늘리세요.
  • 출력 시퀀스가 길거나 동시 요청 수가 많은 워크로드에서는 decode 풀을 늘리세요.

레거시 external_storage 필드

VAST는 prefill 워커가 텐서를 기록하고 decode 워커가 {endpoint}/{kv_namespace}/{prefix_hash} 경로로 읽어 가는 라우터 지정 전송 계층이 아닙니다. 현재 이러한 참조 형식을 사용하는 서빙 엔진은 없습니다.

disaggregated_serving.default_external_storage와 백엔드별 external_storage 필드는 기존 설정 파일과의 호환성을 위해서만 허용되며, 요청 경로에서는 이 값을 읽지 않습니다:

disaggregated_serving:
  enabled: true
  # 레거시: 호환성을 위해 허용되며 요청 경로는 읽지 않음
  default_external_storage:
    endpoint: "http://vast-cluster:8080"
    kv_namespace: "inference/kv-cache"
    # credentials: "${VAST_CREDENTIALS}"   # 맵이 아닌 단일 문자열

backends:
  - name: prefill-worker-1
    url: "http://vllm-prefill-1:8000"
    role: prefill
    # 레거시: 호환성을 위해 허용되며 요청 경로는 읽지 않음
    external_storage:
      endpoint: "http://vast-cluster:8080"
      kv_namespace: "inference/kv-cache"

이 필드가 포함된 설정 파일도 오류 없이 로드되지만 제거해도 런타임 동작은 동일합니다. 상세 필드 정의는 external_storage (백엔드별, 레거시)를 참고하세요.


예시: 전체 프로덕션 설정

이 설정은 계층형 응답 캐시(Redis L1 + VAST S3 L2)와 스토리지 오프로딩 인식 KV 캐시 인덱스를 분리형 prefill/decode 서빙과 함께 구성한 전체 프로덕션 예시입니다. prefill에서 decode로의 KV 전송은 서빙 엔진이 직접 처리합니다.

server:
  bind_address: "0.0.0.0:8080"

selection_strategy: LeastLatency

# ─── Prefix 인식 라우팅 (티어 1) ─────────────────────────────────────────────
prefix_routing:
  enabled: true
  max_prefix_length: 2048
  load_factor_epsilon: 0.20

# ─── 계층형 응답 캐시 (티어 2 + VAST S3 L2) ──────────────────────────────────
response_cache:
  enabled: true
  backend: tiered
  ttl: "24h"
  max_response_size: 2097152       # 2 MiB
  max_stream_buffer_size: 20971520 # 20 MiB

  # L1: Redis (핫, 빠름, 제한된 용량)
  l1:
    type: redis
    max_value_size: 524288   # 512 KiB 초과 값은 L2로 직접 저장

  redis:
    url: "redis://redis-cluster:6379"
    pool_size: 32
    key_prefix: "cr:resp:"
    connect_timeout_ms: 3000
    command_timeout_ms: 1000
    fallback_to_memory: true

  # L2: VAST Data S3 (웜, 내구성, 고용량)
  l2:
    type: s3
    endpoint: "https://vast-s3.prod.example.com"
    bucket: "prod-llm-response-cache"
    key_prefix: "response-cache/"
    region: "us-east-1"
    access_key: "${VAST_ACCESS_KEY}"
    secret_key: "${VAST_SECRET_KEY}"
    ttl_override: "168h"

  tiered:
    promote_on_hit: true
    l1_promotion_ttl: "30m"

# ─── VAST 오프로딩 인식 KV 캐시 인덱스 (티어 4) ─────────────────────────────
kv_cache_index:
  enabled: true
  backend: redis   # response_cache.redis의 redis 풀 재사용
  max_entries: 1000000
  entry_ttl_seconds: 1800

  scoring:
    overlap_weight: 0.6
    load_weight: 0.3
    health_weight: 0.1
    min_overlap_threshold: 0.25
    gpu_tier_weight: 1.0
    storage_tier_weight: 0.6

  storage_offloading:
    enabled: true
    treat_eviction_as_offload: true

  event_sources:
    - backend_name: prefill-worker-1
      endpoint: "http://kv-listener.internal:7817/events/prefill-worker-1"
      reconnect_interval_ms: 5000
    - backend_name: prefill-worker-2
      endpoint: "http://kv-listener.internal:7817/events/prefill-worker-2"
      reconnect_interval_ms: 5000
    - backend_name: decode-worker-1
      endpoint: "http://kv-listener.internal:7817/events/decode-worker-1"
      reconnect_interval_ms: 5000
    - backend_name: decode-worker-2
      endpoint: "http://kv-listener.internal:7817/events/decode-worker-2"
      reconnect_interval_ms: 5000
    - backend_name: decode-worker-3
      endpoint: "http://kv-listener.internal:7817/events/decode-worker-3"
      reconnect_interval_ms: 5000

# ─── 분리형 Prefill/Decode 서빙 ──────────────────────────────────────────────
disaggregated_serving:
  enabled: true
  prefill_timeout: "60s"
  kv_transfer_timeout: "15s"   # 워커 간 엔진 소유 전송
  fallback_to_unified: true

# ─── 백엔드 ───────────────────────────────────────────────────────────────────
backends:
  - name: prefill-worker-1
    url: "http://vllm-prefill-1:8000"
    role: prefill
    models: ["meta-llama/Llama-3.1-70B-Instruct"]

  - name: prefill-worker-2
    url: "http://vllm-prefill-2:8000"
    role: prefill
    models: ["meta-llama/Llama-3.1-70B-Instruct"]

  - name: decode-worker-1
    url: "http://vllm-decode-1:8000"
    role: decode
    weight: 2
    models: ["meta-llama/Llama-3.1-70B-Instruct"]

  - name: decode-worker-2
    url: "http://vllm-decode-2:8000"
    role: decode
    weight: 2
    models: ["meta-llama/Llama-3.1-70B-Instruct"]

  - name: decode-worker-3
    url: "http://vllm-decode-3:8000"
    role: decode
    weight: 2
    models: ["meta-llama/Llama-3.1-70B-Instruct"]

  - name: unified-fallback
    url: "http://vllm-unified:8000"
    role: unified
    models: ["meta-llama/Llama-3.1-70B-Instruct"]

# ─── 헬스 체크 ────────────────────────────────────────────────────────────────
health_checks:
  interval: "15s"
  timeout: "5s"
  unhealthy_threshold: 3
  healthy_threshold: 2
  endpoint: "/health"

logging:
  level: info
  format: json

전체 프로덕션 설정을 위한 워커 실행 참고사항

  • VAST로의 KV 오프로딩: KV 텐서를 VAST로 오프로드할 각 prefill 및 decode 워커는 KV 텐서 오프로딩 예시와 같이 KV 커넥터를 프로덕션 VAST 엔드포인트로 설정하고, kv_cache_index.event_sources에 지정된 리스너로 KV 이벤트를 발행합니다.
  • prefill에서 decode로의 전송: 서빙 엔진에서 설정합니다(Dynamo 배포에서는 워커 간 NIXL). 자세한 내용은 워커 설정을 참고하세요. VAST는 이 경로에 관여하지 않습니다.
  • 통합형 폴백: 프리픽스 캐싱을 활성화한 표준 엔진으로 실행합니다:
vllm serve meta-llama/Llama-3.1-70B-Instruct \
  --host 0.0.0.0 \
  --port 8000 \
  --tensor-parallel-size 4 \
  --enable-prefix-caching \
  --kv-cache-dtype auto \
  --max-model-len 32768

통합형 폴백 백엔드는 두 단계를 자체적으로 처리하므로 워커 간 KV 전송에 참여하지 않습니다.


성능 벤치마크

다음 수치는 일반적인 LLM 서빙 워크로드에서 측정한 예시 추정값입니다. 실제 성능은 프롬프트 다양성, GPU 메모리 용량, VAST 네트워크 대역폭, 동시 요청 수에 따라 달라집니다.

응답 캐시 적중률 (VAST L2 포함)

워크로드 패턴 L1 (Redis) 적중률 L2 (VAST S3) 적중률 총 적중률
문서 QA (고정 문서 + 다양한 질문) 30–50% 20–35% 50–75%
RAG 파이프라인 (고정 system prompt + 검색) 15–30% 10–20% 25–45%
동일 요청 반복 API 70–95% 3–10% 75–98%
완전히 고유한 요청 < 5% < 2% < 7%

L2 캐시는 L1 TTL이 만료된 이후에도 수 시간 또는 수 일 간격으로 동일한 요청이 반복되는 워크로드에서 큰 효과를 발휘합니다.

분리형 서빙 지연 시간

70B 파라미터 모델에서 통합형(단일 워커) 추론 대비 지연 시간 개선 폭:

라우팅 경로 TTFT (첫 번째 토큰까지의 시간) 통합형 대비
fast_decode (GPU 상주 KV) 50–100 ms 40–60% 감소
fast_decode (엔진이 VAST에서 오프로드된 KV 재로드) 100–200 ms 15–35% 감소
prefill_then_decode (엔진 소유 전송, 예: NIXL) 200–500 ms 0–10% 오버헤드 (일회성 prefill 비용)
unified (폴백) 300–600 ms 기준값

prefill_then_decode 경로는 특정 프리픽스의 첫 번째 요청에서 약간의 오버헤드가 발생하지만, 동일한 프리픽스를 공유하는 후속 요청은 fast_decode 경로를 통해 지연 시간을 크게 단축할 수 있습니다.

KV 캐시 인덱스 라우팅 효과

시나리오 KV 인식 라우팅 비율 TTFT 감소
높은 prefix 중복 (동일 system prompt, 다수 사용자) 70–85% 20–40%
중간 prefix 중복 (다양한 system prompt) 40–60% 10–25%
낮은 prefix 중복 (완전히 고유한 프롬프트) < 10% < 5%

VAST Data 액세스 지연 시간

작업 지연 시간 범위 대역폭
S3 GET (응답 캐시 읽기) 1–10 ms 연결당 최대 10 Gbps
S3 PUT (응답 캐시 쓰기) 2–15 ms 연결당 최대 10 Gbps
KV 텐서 오프로드 (엔진 GPU → VAST) 5–50 ms 네트워크 제한; RDMA 사용 시 < 5 ms
KV 텐서 재로드 (VAST → 엔진 GPU) 5–50 ms 네트워크 제한; RDMA 사용 시 < 5 ms

오프로드 및 재로드 경로에서 엄격한 지연 시간 요구사항이 있는 프로덕션 환경에서는 VAST 클러스터를 동일 랙에 배치하거나, 엔진 호스트에서 NVMe-oF 프로토콜을 직접 사용하는 RDMA 네트워크 어댑터를 구성하는 것을 권장합니다. prefill-decode 간 KV 전송은 VAST를 거치지 않으며 워커 간 패브릭(RDMA 기반 NIXL, NCCL)의 대역폭에 의해 결정됩니다.