Skip to content
Published on

Kubernetes ML 모델 서빙: KServe와 NVIDIA Triton 완전 분석

Authors
  • Name
    Twitter

1. 왜 Kubernetes에서 ML 모델을 서빙하는가

머신러닝 모델을 프로덕션 환경에 배포할 때, 단일 서버에서 Flask나 FastAPI로 모델을 서빙하는 방식은 초기 프로토타이핑에는 적합하지만, 실제 프로덕션 트래픽을 처리하기에는 근본적인 한계가 있다. Kubernetes는 이러한 한계를 해결하는 가장 성숙한 플랫폼이다.

1.1 확장성 (Scalability)

Kubernetes의 핵심 강점은 워크로드에 따른 수평적 확장(Horizontal Scaling)이다. 추론 요청이 급증하면 Pod를 자동으로 늘리고, 트래픽이 줄어들면 다시 축소할 수 있다. HPA(Horizontal Pod Autoscaler)를 활용하면 CPU, 메모리, 혹은 커스텀 메트릭(예: GPU 사용률, 요청 큐 길이)을 기준으로 자동 스케일링이 가능하다. 더 나아가 Knative 기반의 KPA(Knative Pod Autoscaler)를 사용하면 트래픽이 전혀 없을 때 Pod를 0으로 축소하는 Scale-to-Zero도 가능하다.

1.2 리소스 관리 (Resource Management)

ML 추론 워크로드는 GPU라는 고가의 리소스를 사용한다. Kubernetes는 resources.requestsresources.limits를 통해 각 Pod가 사용하는 CPU, 메모리, GPU를 정밀하게 제어할 수 있다. NVIDIA Device Plugin을 사용하면 nvidia.com/gpu 리소스를 Kubernetes 네이티브하게 스케줄링할 수 있으며, MIG(Multi-Instance GPU)나 Time-Slicing을 통해 단일 GPU를 여러 Pod가 공유하는 것도 가능하다.

1.3 운영 안정성 (Operational Reliability)

Kubernetes의 Self-Healing 메커니즘은 모델 서빙의 안정성을 높인다. Pod가 비정상 종료되면 자동으로 재시작되고, liveness/readiness probe를 통해 모델 서버의 상태를 지속적으로 모니터링한다. Rolling Update와 Canary Deployment를 통해 모델 업데이트 시 다운타임 없이 안전하게 배포할 수 있다.


2. KServe 아키텍처 분석

KServe(구 KFServing)는 Kubernetes 위에서 ML 모델 서빙을 위해 설계된 표준화된 플랫폼이다. KServe는 Kubernetes CRD(Custom Resource Definition)를 활용하여 모델 서빙의 전체 라이프사이클을 관리한다.

2.1 계층 아키텍처 (Layered Architecture)

KServe 공식 문서에 따르면, KServe는 네 개의 주요 계층으로 구성된다.

  • Control Plane (Go): Kubernetes Controller가 InferenceService의 전체 라이프사이클을 관리한다. 모델 배포, 업데이트, 삭제, 스케일링 등의 작업을 오케스트레이션한다.
  • Data Plane (Python): 프로토콜에 구애받지 않는(protocol-agnostic) 모델 서버 프레임워크로, V1/V2 추론 프로토콜을 통해 실제 추론 요청을 처리한다.
  • Configuration Layer: CRD와 ConfigMap을 통해 시스템의 전체 설정을 관리한다.
  • Storage Layer: S3, GCS, Azure Blob Storage, PVC 등 다양한 모델 아티팩트 스토리지 백엔드를 지원한다.

2.2 InferenceService CRD

InferenceService는 KServe의 핵심 CRD로, ML 모델 서빙에 필요한 autoscaling, networking, health checking, server configuration의 복잡성을 캡슐화한다. 하나의 YAML 정의로 모델 서빙에 필요한 모든 것을 선언적으로 관리할 수 있다.

기본적인 InferenceService 정의는 다음과 같다.

apiVersion: 'serving.kserve.io/v1beta1'
kind: 'InferenceService'
metadata:
  name: 'sklearn-iris'
spec:
  predictor:
    model:
      modelFormat:
        name: sklearn
      storageUri: 'gs://kfserving-examples/models/sklearn/1.0/model'

이 간단한 YAML 하나로 모델 다운로드, 서버 기동, 네트워크 엔드포인트 설정, 오토스케일링까지 모두 자동으로 처리된다.

2.3 세 가지 핵심 컴포넌트: Predictor, Transformer, Explainer

KServe InferenceService는 세 가지 컴포넌트로 구성되며, 이 중 Predictor만 필수이고 나머지는 선택적이다.

Predictor

Predictor는 InferenceService의 핵심 워크로드로, 모델과 모델 서버로 구성된다. 실제 추론 요청을 처리하는 역할을 하며, 네트워크 엔드포인트를 통해 외부에 노출된다. KServe는 다양한 Serving Runtime을 제공한다: TensorFlow Serving, TorchServe, Triton Inference Server, SKLearn, XGBoost, LightGBM 등이 기본 내장되어 있다.

Transformer

Transformer는 추론 전후의 데이터 변환(pre/post-processing)을 담당한다. 예를 들어, 이미지 입력을 정규화하거나, 텍스트를 토큰화하거나, 모델 출력을 사람이 읽을 수 있는 형태로 변환하는 작업을 수행한다. KServe는 Feast와 같은 Feature Store와 통합되는 out-of-the-box Transformer도 제공한다. 커스텀 Transformer는 별도의 컨테이너로 배포되며, 예측 엔드포인트와 같은 환경 변수를 통해 Predictor와 연결된다.

Explainer

Explainer는 모델 예측에 대한 설명(interpretability)을 제공하는 선택적 컴포넌트다. SHAP, LIME 등의 XAI(eXplainable AI) 기법을 활용하여 모델이 왜 특정 예측을 내렸는지에 대한 설명을 제공한다. Predictor의 추론 결과와 별도의 데이터 플레인에서 동작하며, 설명 요청 시에만 활성화된다.

요청 흐름 (Request Flow)

추론 요청이 들어오면 다음과 같은 흐름으로 처리된다.

  1. 클라이언트 요청이 Ingress Gateway를 통해 진입
  2. Transformer에서 입력 데이터 전처리 수행
  3. 전처리된 데이터가 Predictor로 전달되어 추론 실행
  4. Transformer에서 출력 데이터 후처리 수행
  5. 최종 결과가 클라이언트에 반환

Explanation 요청의 경우, Explainer가 추가로 개입하여 모델 설명을 생성한다.


3. KServe 설치 및 기본 사용법

3.1 사전 요구사항

KServe 공식 QuickStart 가이드에 따르면 다음이 필요하다.

  • Kubernetes 1.32 이상
  • 올바르게 설정된 kubeconfig
  • 로컬 개발/테스트 환경에서는 kind(Kubernetes in Docker) 또는 minikube 사용을 권장

3.2 Quick Install

개발 및 테스트 환경에서 가장 빠르게 시작하는 방법은 Quick Install Script를 사용하는 것이다.

# KServe Quick Install (Serverless mode - Knative 포함)
curl -s "https://raw.githubusercontent.com/kserve/kserve/master/hack/quick_install.sh" | bash

# Raw Deployment mode (Knative 없이 설치)
curl -s "https://raw.githubusercontent.com/kserve/kserve/master/hack/quick_install.sh" | bash -s -- -r

이 스크립트는 의존성 설치, 플랫폼 감지, 모드 설정을 자동으로 처리한다.

3.3 배포 모드

KServe는 두 가지 주요 배포 모드를 지원한다.

  • Serverless Mode (Knative): 기본 설치 옵션으로, Knative Serving을 기반으로 동작한다. Scale-to-Zero, revision 기반 트래픽 관리, Canary Deployment 등 서버리스 기능을 제공한다.
  • Standard Mode (Raw Deployment): Knative 없이 Kubernetes 네이티브 리소스(Deployment, Service, HPA)만으로 동작한다. 외부 의존성을 최소화하면서도 예측 추론과 생성형 추론 워크로드 모두를 지원한다.

3.4 첫 번째 모델 배포

설치가 완료되면, 다음과 같이 간단한 SKLearn 모델을 배포할 수 있다.

apiVersion: 'serving.kserve.io/v1beta1'
kind: 'InferenceService'
metadata:
  name: 'sklearn-iris'
spec:
  predictor:
    model:
      modelFormat:
        name: sklearn
      storageUri: 'gs://kfserving-examples/models/sklearn/1.0/model'
      resources:
        requests:
          cpu: '100m'
          memory: '256Mi'
        limits:
          cpu: '1'
          memory: '512Mi'
# 모델 배포
kubectl apply -f sklearn-iris.yaml

# 상태 확인
kubectl get inferenceservice sklearn-iris

# 추론 요청 테스트
curl -v -H "Content-Type: application/json" \
  http://${INGRESS_HOST}:${INGRESS_PORT}/v1/models/sklearn-iris:predict \
  -d '{"instances": [[6.8, 2.8, 4.8, 1.4]]}'

4. NVIDIA Triton Inference Server 기능 분석

NVIDIA Triton Inference Server는 다양한 딥러닝 및 머신러닝 프레임워크의 모델을 동시에 서빙할 수 있는 고성능 추론 서버이다. KServe의 Serving Runtime으로 통합 사용할 수 있으며, 독립적으로도 배포할 수 있다.

4.1 핵심 특징

Triton 공식 문서에 따르면, Triton은 다음과 같은 핵심 기능을 제공한다.

  • 다중 프레임워크 지원: 하나의 서버 인스턴스에서 서로 다른 프레임워크의 여러 모델을 동시에 서빙
  • Dynamic Batching: 개별 추론 요청을 동적으로 묶어 GPU 활용률 극대화
  • Concurrent Model Execution: 동일 GPU에서 여러 모델을 동시 실행
  • Model Ensemble: 여러 모델을 파이프라인으로 연결하여 복합 추론 수행
  • Model Analyzer: 최적의 배포 설정을 자동으로 탐색

5. 모델 포맷 지원

5.1 Triton Backend 아키텍처

Triton은 Backend 플러그인 아키텍처를 통해 다양한 모델 포맷을 지원한다. 각 모델은 반드시 하나의 Backend과 연결되어야 하며, config.pbtxtbackend 또는 platform 필드를 통해 지정한다.

5.2 지원 프레임워크 및 모델 포맷

ONNX Runtime Backend

ONNX(Open Neural Network Exchange) 형식의 모델을 실행한다. PyTorch, TensorFlow, scikit-learn 등 다양한 프레임워크에서 변환된 모델을 지원한다. CPU와 GPU 모두에서 최적화된 추론을 제공하며, ONNX Runtime의 Graph Optimization과 Execution Provider를 활용할 수 있다.

# ONNX 모델 파일 예시
model_repository/
  resnet50_onnx/
    config.pbtxt
    1/
      model.onnx

TensorRT Backend

NVIDIA TensorRT로 최적화된 모델(engine/plan 파일)을 실행한다. TensorRT는 NVIDIA GPU에 특화된 추론 최적화 엔진으로, FP16/INT8 양자화, Layer Fusion, Kernel Auto-Tuning 등을 통해 최고 수준의 GPU 추론 성능을 제공한다.

# TensorRT 모델 파일 예시
model_repository/
  resnet50_tensorrt/
    config.pbtxt
    1/
      model.plan

PyTorch Backend

TorchScript 형식과 PyTorch 2.0의 torch.compile 형식을 모두 지원한다. TorchScript는 torch.jit.trace 또는 torch.jit.script로 변환된 모델이며, 동일한 Backend에서 TorchScript와 PyTorch 2.0 모델을 모두 처리할 수 있다.

# PyTorch 모델 파일 예시
model_repository/
  bert_torchscript/
    config.pbtxt
    1/
      model.pt

TensorFlow Backend

TensorFlow의 SavedModel과 GraphDef 형식을 모두 지원한다. 동일한 Backend이 TensorFlow 1과 TensorFlow 2 모델을 모두 실행할 수 있다. SavedModel이 권장 형식이다.

# TensorFlow SavedModel 예시
model_repository/
  resnet50_tf/
    config.pbtxt
    1/
      model.savedmodel/
        saved_model.pb
        variables/

기타 Backend

  • OpenVINO Backend: Intel 하드웨어에 최적화된 추론 지원
  • FIL Backend (Forest Inference Library): XGBoost, LightGBM, scikit-learn Random Forest, cuML Random Forest 등 트리 기반 모델 지원
  • Python Backend: 커스텀 Python 코드로 전처리/후처리 파이프라인 구현 가능

6. Model Repository 구조와 config.pbtxt 설정

6.1 디렉토리 구조

Triton 공식 문서에서 정의하는 Model Repository의 기본 레이아웃은 다음과 같다.

<model-repository-path>/
  <model-name>/
    [config.pbtxt]
    [<output-labels-file> ...]
    <version>/
      <model-definition-file>
    <version>/
      <model-definition-file>
    ...
  <model-name>/
    [config.pbtxt]
    ...

각 구성 요소의 역할은 다음과 같다.

  • model-name 디렉토리: 모델 이름에 해당하는 최상위 디렉토리
  • config.pbtxt: ModelConfig protobuf 형식의 모델 설정 파일
  • version 디렉토리: 숫자로 된 디렉토리명이 모델 버전을 나타낸다. "0"으로 시작하거나 숫자가 아닌 이름의 디렉토리는 무시된다
  • model-definition-file: Backend별 모델 파일 (model.onnx, model.plan, model.pt 등)

실제 예시를 보면 다음과 같다.

model_repository/
  text_detection/
    config.pbtxt
    1/
      model.onnx
  text_recognition/
    config.pbtxt
    output_labels.txt
    1/
      model.plan
    2/
      model.plan
  ensemble_ocr/
    config.pbtxt
    1/

6.2 config.pbtxt 상세 설정

config.pbtxt는 ModelConfig protobuf 메시지를 텍스트 형식으로 표현한 것이다. 최소한의 설정은 name, backend(또는 platform), max_batch_size, input, output을 포함해야 한다. 다만 일부 모델의 경우 Triton이 자동으로 최소 설정을 생성할 수 있다.

name: "resnet50"
backend: "onnxruntime"
max_batch_size: 8

input [
  {
    name: "input"
    data_type: TYPE_FP32
    dims: [ 3, 224, 224 ]
  }
]

output [
  {
    name: "output"
    data_type: TYPE_FP32
    dims: [ 1000 ]
    label_filename: "labels.txt"
  }
]

instance_group [
  {
    count: 2
    kind: KIND_GPU
    gpus: [ 0 ]
  }
]

dynamic_batching {
  preferred_batch_size: [ 4, 8 ]
  max_queue_delay_microseconds: 100
}

위 예시에서 각 항목의 의미는 다음과 같다.

  • name: 모델 이름 (디렉토리명과 일치해야 함)
  • backend: 사용할 Backend ("onnxruntime", "tensorrt", "pytorch", "tensorflow" 등)
  • max_batch_size: 동적 배칭 시 최대 배치 크기. 0으로 설정하면 배칭을 비활성화한다
  • input/output: 모델의 입출력 텐서 이름, 데이터 타입, 차원
  • instance_group: 모델 인스턴스 수와 할당 GPU 지정
  • dynamic_batching: 동적 배칭 설정

7. Dynamic Batching과 Concurrent Model Execution

7.1 Dynamic Batching

Dynamic Batching은 Triton의 가장 강력한 성능 최적화 기능 중 하나이다. 개별적으로 도착하는 추론 요청들을 하나의 배치로 묶어서 GPU에 전달함으로써 처리량(throughput)을 크게 향상시킨다.

Triton 공식 문서에 따르면, Dynamic Batching은 모델별로 독립적으로 활성화 및 설정할 수 있다. 기본적으로 Triton은 지연 없이 도착한 요청들을 즉시 배칭하지만, 사용자가 제한된 대기 시간을 설정하여 스케줄러가 더 많은 요청을 수집하도록 할 수 있다.

dynamic_batching {
  # 선호하는 배치 크기 (가능하면 이 크기로 배칭)
  preferred_batch_size: [ 4, 8 ]

  # 배치를 구성하기 위해 대기할 최대 시간 (마이크로초)
  max_queue_delay_microseconds: 100

  # 우선순위 설정 (선택)
  priority_levels: 2
  default_priority_level: 1

  # 큐 정책 (선택)
  default_queue_policy {
    timeout_action: REJECT
    default_timeout_microseconds: 5000000
    allow_timeout_override: true
    max_queue_size: 100
  }
}

핵심 파라미터의 역할은 다음과 같다.

  • preferred_batch_size: Triton이 우선적으로 구성하려는 배치 크기. 이 크기의 배치가 구성되면 즉시 실행한다.
  • max_queue_delay_microseconds: 배치를 채우기 위해 추가 요청을 기다리는 최대 시간. 이 시간이 지나면 현재 모인 요청으로 바로 실행한다. latency와 throughput 사이의 트레이드오프를 조절하는 핵심 파라미터이다.

7.2 Concurrent Model Execution

Triton은 동일한 GPU에서 여러 모델 인스턴스를 동시에 실행할 수 있다. 이를 통해 GPU의 연산 자원을 더 효율적으로 활용한다.

# 하나의 GPU에 2개의 모델 인스턴스를 배치
instance_group [
  {
    count: 2
    kind: KIND_GPU
    gpus: [ 0 ]
  }
]
# 여러 GPU에 인스턴스를 분산 배치
instance_group [
  {
    count: 1
    kind: KIND_GPU
    gpus: [ 0 ]
  },
  {
    count: 2
    kind: KIND_GPU
    gpus: [ 1, 2 ]
  }
]
# CPU와 GPU에 동시에 인스턴스 배치
instance_group [
  {
    count: 1
    kind: KIND_CPU
  },
  {
    count: 2
    kind: KIND_GPU
    gpus: [ 0 ]
  }
]

Triton 공식 문서에서 제시하는 최대 처리량을 위한 동시성 공식은 다음과 같다.

최적 동시성 = 2 x <max_batch_size> x <instance_count>

예를 들어, max_batch_size가 8이고 instance_count가 2라면, 최적 동시성은 2 x 8 x 2 = 32이다. 즉, 32개의 동시 요청을 보내야 Triton의 성능을 최대로 끌어낼 수 있다.


8. GPU 리소스 할당

8.1 NVIDIA Device Plugin for Kubernetes

NVIDIA Device Plugin은 Kubernetes 클러스터에서 GPU를 네이티브 리소스로 관리할 수 있게 해주는 DaemonSet이다. 설치되면 각 노드의 GPU를 자동으로 탐지하여 nvidia.com/gpu 리소스로 등록한다.

# NVIDIA Device Plugin 설치
kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.17.0/deployments/static/nvidia-device-plugin.yml

Pod에서 GPU를 요청하는 방법은 다음과 같다.

apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  containers:
    - name: inference
      image: nvcr.io/nvidia/tritonserver:24.01-py3
      resources:
        limits:
          nvidia.com/gpu: 1

8.2 MIG (Multi-Instance GPU)

MIG는 NVIDIA A100, H100 등 최신 GPU에서 지원하는 기능으로, 하나의 물리 GPU를 여러 개의 독립된 GPU 인스턴스로 분할한다. 각 인스턴스는 하드웨어 수준에서 메모리와 연산 자원이 격리되어 있어 장애 격리(fault isolation)가 보장된다.

MIG의 주요 특성은 다음과 같다.

  • 하드웨어 수준 격리: 각 MIG 인스턴스는 독립된 메모리, 캐시, 연산 유닛을 가진다
  • 성능 보장: 한 인스턴스의 워크로드가 다른 인스턴스에 영향을 주지 않는다
  • 사전 정의된 프로파일: GPU 모델에 따라 사용 가능한 분할 구성이 정해져 있다 (예: A100 80GB를 7개의 10GB 인스턴스로 분할)

Kubernetes에서 MIG를 사용하려면 NVIDIA GPU Operator를 통해 MIG 전략을 설정한다.

# MIG 프로파일 설정 예시 (GPU Operator ConfigMap)
apiVersion: v1
kind: ConfigMap
metadata:
  name: mig-parted-config
data:
  config.yaml: |
    version: v1
    mig-configs:
      all-1g.10gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "1g.10gb": 7
      all-3g.40gb:
        - devices: all
          mig-enabled: true
          mig-devices:
            "3g.40gb": 2

8.3 GPU Time-Slicing

Time-Slicing은 MIG를 지원하지 않는 이전 세대 GPU에서도 GPU 공유를 가능하게 하는 방식이다. NVIDIA GPU Operator 공식 문서에 따르면, Time-Slicing은 시스템 관리자가 GPU의 복제본(replica)을 정의하여 각 Pod에 독립적으로 할당할 수 있게 한다.

핵심 특성은 다음과 같다.

  • 소프트웨어 수준 공유: GPU 시간을 균등하게 분배하여 여러 Pod가 공유
  • 메모리/장애 격리 없음: MIG와 달리 메모리와 장애 격리가 제공되지 않는다
  • 유연한 분할: 더 많은 수의 사용자가 GPU를 공유 가능
  • MIG와 결합 가능: MIG 인스턴스에 Time-Slicing을 추가로 적용 가능
# Time-Slicing 설정 (GPU Operator ConfigMap)
apiVersion: v1
kind: ConfigMap
metadata:
  name: time-slicing-config
  namespace: gpu-operator
data:
  any: |-
    version: v1
    sharing:
      timeSlicing:
        resources:
        - name: nvidia.com/gpu
          replicas: 4

위 설정은 각 GPU를 4개의 복제본으로 노출하여, 4개의 Pod가 각각 nvidia.com/gpu: 1을 요청하면 동일한 물리 GPU를 시분할로 공유하게 된다.


9. Auto-scaling 전략

9.1 HPA (Horizontal Pod Autoscaler)

KServe의 Standard Mode(Raw Deployment)에서는 Kubernetes 기본 HPA를 사용한다. CPU, 메모리, 또는 커스텀 메트릭을 기반으로 Pod 수를 자동 조절한다.

apiVersion: 'serving.kserve.io/v1beta1'
kind: 'InferenceService'
metadata:
  name: 'sklearn-iris'
  annotations:
    serving.kserve.io/autoscalerClass: 'hpa'
    serving.kserve.io/targetUtilizationPercentage: '80'
    serving.kserve.io/minReplicas: '1'
    serving.kserve.io/maxReplicas: '10'
spec:
  predictor:
    model:
      modelFormat:
        name: sklearn
      storageUri: 'gs://kfserving-examples/models/sklearn/1.0/model'

9.2 KPA (Knative Pod Autoscaler)

KServe의 Serverless Mode(Knative)에서는 KPA를 사용한다. KPA의 가장 큰 특징은 Scale-to-Zero로, 트래픽이 없을 때 Pod를 0으로 축소하여 리소스를 절약할 수 있다. HPA와 KPA는 동일한 서비스에 동시에 사용할 수 없으며, annotation을 통해 어떤 Autoscaler를 사용할지 지정한다.

apiVersion: 'serving.kserve.io/v1beta1'
kind: 'InferenceService'
metadata:
  name: 'sklearn-iris'
  annotations:
    autoscaling.knative.dev/class: 'kpa.autoscaling.knative.dev'
    autoscaling.knative.dev/metric: 'concurrency'
    autoscaling.knative.dev/target: '10'
    autoscaling.knative.dev/minScale: '0'
    autoscaling.knative.dev/maxScale: '10'
spec:
  predictor:
    model:
      modelFormat:
        name: sklearn
      storageUri: 'gs://kfserving-examples/models/sklearn/1.0/model'

KPA의 주요 메트릭은 다음과 같다.

  • concurrency: Pod당 동시 요청 수 (기본값)
  • rps: Pod당 초당 요청 수

9.3 GPU 메트릭 기반 Auto-scaling

GPU 워크로드의 경우, CPU/메모리 기반 스케일링만으로는 부족하다. NVIDIA DCGM(Data Center GPU Manager) Exporter와 Prometheus Adapter를 결합하면 GPU 메트릭 기반 스케일링이 가능하다.

# KEDA ScaledObject를 사용한 GPU 메트릭 기반 스케일링
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: triton-gpu-scaler
spec:
  scaleTargetRef:
    name: triton-inference-server
  pollingInterval: 15
  cooldownPeriod: 60
  minReplicaCount: 1
  maxReplicaCount: 5
  triggers:
    - type: prometheus
      metadata:
        serverAddress: http://prometheus.monitoring:9090
        metricName: gpu_utilization
        query: avg(DCGM_FI_DEV_GPU_UTIL{pod=~"triton-.*"})
        threshold: '80'

KServe Controller Manager는 HPA와 함께 KEDA(Kubernetes Event-Driven Autoscaling)도 지원하여 커스텀 메트릭 기반 스케일링을 구성할 수 있다.


10. Canary / Blue-Green Deployment

10.1 Canary Rollout

KServe 공식 문서에 따르면, Canary Rollout 전략은 Serverless Deployment Mode에서 지원된다. KServe는 자동으로 마지막으로 100% 트래픽을 받았던 안정 버전(last known good revision)을 추적하며, canaryTrafficPercent 필드를 설정하면 새 버전과 안정 버전 사이에 트래픽을 자동으로 분배한다.

apiVersion: 'serving.kserve.io/v1beta1'
kind: 'InferenceService'
metadata:
  name: 'my-model'
  annotations:
    serving.kserve.io/enable-tag-routing: 'true'
spec:
  predictor:
    canaryTrafficPercent: 10
    model:
      modelFormat:
        name: tensorflow
      storageUri: 'gs://kfserving-examples/models/tensorflow/flowers-2'

위 설정에서 새 모델 버전에 10%의 트래픽이 전달되고, 나머지 90%는 이전 안정 버전으로 라우팅된다. 새 버전의 성능이 검증되면 canaryTrafficPercent를 점진적으로 올려 최종적으로 100%로 전환한다.

Canary Rollout의 일반적인 워크플로우는 다음과 같다.

  1. 새 모델 버전 배포 시 canaryTrafficPercent: 10 설정
  2. 모니터링으로 새 버전의 latency, error rate 등을 확인
  3. 문제가 없으면 canaryTrafficPercent를 20 -> 50 -> 100으로 점진적 증가
  4. 문제 발생 시 canaryTrafficPercent: 0으로 즉시 롤백

10.2 Blue-Green Deployment

Blue-Green Deployment에서는 두 개의 완전한 환경(Blue: 현재 프로덕션, Green: 새 버전)을 동시에 운영하다가, 검증 후 트래픽을 한 번에 전환한다.

KServe에서는 canaryTrafficPercent: 0으로 설정하여 새 버전을 배포하되 트래픽을 보내지 않고, 검증 후 100으로 전환하는 방식으로 Blue-Green Deployment를 구현할 수 있다. 또한 serving.kserve.io/enable-tag-routing: "true" annotation을 사용하면 태그 기반 라우팅으로 특정 버전을 직접 호출하여 테스트할 수 있다.

apiVersion: 'serving.kserve.io/v1beta1'
kind: 'InferenceService'
metadata:
  name: 'my-model'
  annotations:
    serving.kserve.io/enable-tag-routing: 'true'
spec:
  predictor:
    # 트래픽 0%로 새 버전을 배포 (Green)
    canaryTrafficPercent: 0
    model:
      modelFormat:
        name: tensorflow
      storageUri: 'gs://kfserving-examples/models/tensorflow/flowers-v2'

태그 라우팅이 활성화되면, latest 태그로 새 버전을, prev 태그로 이전 버전을 직접 호출하여 테스트할 수 있다. 검증이 완료되면 canaryTrafficPercent를 100으로 설정하여 전체 트래픽을 새 버전으로 전환한다.


11. Prometheus + Grafana 모니터링 설정

11.1 메트릭 수집 아키텍처

ML 모델 서빙의 프로덕션 운영에서 모니터링은 필수적이다. KServe는 Prometheus를 통한 메트릭 수집과 Grafana를 통한 시각화를 기본적으로 지원한다.

메트릭 수집 경로는 다음과 같다.

  1. KServe 서빙 컨테이너: 각 모델 서버(Triton, TorchServe 등)가 자체 메트릭을 노출
  2. Knative Queue Proxy: Serverless Mode에서는 queue-proxy 컨테이너가 자동으로 요청 메트릭 생성
  3. Prometheus: ServiceMonitor를 통해 Pod의 메트릭 엔드포인트를 동적으로 발견하고 스크랩
  4. Grafana: Prometheus를 데이터소스로 사용하여 대시보드 시각화

11.2 Prometheus 설정

Prometheus Operator와 ServiceMonitor를 사용하면 KServe Pod의 메트릭을 자동으로 수집할 수 있다.

# Prometheus ServiceMonitor for KServe
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: kserve-monitor
  namespace: monitoring
spec:
  selector:
    matchLabels:
      serving.kserve.io/inferenceservice: 'my-model'
  endpoints:
    - port: metrics
      interval: 15s
      path: /metrics
  namespaceSelector:
    matchNames:
      - default

Triton은 기본적으로 포트 8002에서 Prometheus 메트릭을 노출한다. 주요 메트릭은 다음과 같다.

  • nv_inference_request_success: 성공한 추론 요청 수
  • nv_inference_request_failure: 실패한 추론 요청 수
  • nv_inference_count: 총 추론 실행 수
  • nv_inference_exec_count: 총 추론 배치 실행 수
  • nv_inference_request_duration_us: 추론 요청 처리 시간 (마이크로초)
  • nv_inference_queue_duration_us: 요청이 큐에서 대기한 시간
  • nv_inference_compute_input_duration_us: 입력 전처리 시간
  • nv_inference_compute_infer_duration_us: 실제 추론 시간
  • nv_inference_compute_output_duration_us: 출력 후처리 시간
  • nv_gpu_utilization: GPU 사용률
  • nv_gpu_memory_used_bytes: GPU 메모리 사용량

11.3 Grafana 대시보드

KServe 공식 문서에서는 Serving Runtime별 템플릿 대시보드를 제공한다.

KServe ModelServer Latency Dashboard

기본 KServe ModelServer(sklearn, xgboost, lgb, paddle, pmml, custom) 런타임에 대한 대시보드로, pre/post-process, predict, explain 단계별 latency를 밀리초 단위로 시각화한다.

KServe Triton Latency Dashboard

Triton 전용 대시보드로, 다섯 가지 latency 그래프를 제공한다.

  • Input (preprocess) latency
  • Infer (predict) latency
  • Output (postprocess) latency
  • Internal queue latency
  • Total latency

추가로 GPU 메모리 사용량의 퍼센티지 게이지도 포함되어 있다.

KServe TorchServe Latency Dashboard

TorchServe 전용 대시보드로, ts_inference_latency_microsecondsts_queue_latency_microseconds 메트릭을 밀리초 단위로 시각화한다.

11.4 GPU 모니터링 (DCGM Exporter)

GPU 전용 모니터링을 위해 NVIDIA DCGM Exporter를 추가로 배포하면 상세한 GPU 메트릭을 수집할 수 있다.

# DCGM Exporter 설치 (Helm)
helm repo add gpu-helm-charts https://nvidia.github.io/dcgm-exporter/helm-charts
helm install dcgm-exporter gpu-helm-charts/dcgm-exporter \
  --namespace monitoring \
  --set serviceMonitor.enabled=true

DCGM Exporter가 제공하는 주요 GPU 메트릭은 다음과 같다.

  • DCGM_FI_DEV_GPU_UTIL: GPU 코어 사용률 (%)
  • DCGM_FI_DEV_MEM_COPY_UTIL: GPU 메모리 대역폭 사용률 (%)
  • DCGM_FI_DEV_FB_USED: 프레임버퍼 사용량 (MB)
  • DCGM_FI_DEV_FB_FREE: 프레임버퍼 여유 공간 (MB)
  • DCGM_FI_DEV_GPU_TEMP: GPU 온도 (C)
  • DCGM_FI_DEV_POWER_USAGE: 전력 사용량 (W)
  • DCGM_FI_DEV_SM_CLOCK: SM 클럭 속도 (MHz)
  • DCGM_FI_PROF_GR_ENGINE_ACTIVE: Graphics Engine 활성 비율

이러한 메트릭들을 Grafana 대시보드에서 종합적으로 시각화하면, 모델별 추론 성능, GPU 리소스 활용률, 병목 구간 등을 실시간으로 파악하여 최적화에 활용할 수 있다.


12. 정리

Kubernetes 환경에서의 ML 모델 서빙은 단순한 배포를 넘어, 확장성, 리소스 효율성, 운영 안정성을 동시에 달성하기 위한 체계적인 접근이 필요하다. KServe는 InferenceService CRD를 통해 모델 서빙의 복잡성을 추상화하고, Predictor/Transformer/Explainer 구조로 유연한 추론 파이프라인을 구성할 수 있게 한다. NVIDIA Triton Inference Server는 다중 프레임워크 지원, Dynamic Batching, Concurrent Model Execution 등을 통해 GPU 활용률을 극대화한다.

GPU 리소스 관리에서는 NVIDIA Device Plugin을 기본으로, MIG와 Time-Slicing을 통해 고가의 GPU 리소스를 효율적으로 공유할 수 있다. Auto-scaling은 HPA, KPA, KEDA를 워크로드 특성에 맞게 선택하고, Canary/Blue-Green Deployment로 안전한 모델 업데이트를 보장한다. 마지막으로 Prometheus + Grafana + DCGM Exporter 조합으로 모델 성능과 GPU 리소스를 종합적으로 모니터링해야 한다.

이 모든 구성 요소를 유기적으로 결합하면, 대규모 ML 워크로드를 안정적이고 효율적으로 운영할 수 있는 프로덕션 수준의 모델 서빙 플랫폼을 구축할 수 있다.


References