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 は 4 つの主要レイヤーで構成される。

  • 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 の複雑さをカプセル化する。1 つの 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 3 つのコアコンポーネント:Predictor、Transformer、Explainer

KServe InferenceService は 3 つのコンポーネントで構成され、このうち 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 は 2 つの主要デプロイモードをサポートする。

  • 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 は以下の主要機能を提供する。

  • マルチフレームワークサポート:1 つのサーバーインスタンスで異なるフレームワークの複数モデルを同時にサービング
  • Dynamic Batching:個別の推論リクエストを動的にまとめて GPU 活用率を最大化
  • Concurrent Model Execution:同一 GPU で複数モデルを同時実行
  • Model Ensemble:複数モデルをパイプラインで接続して複合推論を実行
  • Model Analyzer:最適なデプロイ設定を自動的に探索

5. モデルフォーマットサポート

5.1 Triton Backend アーキテクチャ

Triton は Backend プラグインアーキテクチャを通じて様々なモデルフォーマットをサポートする。各モデルは必ず 1 つの 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 SavedModelmodel_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 の最も強力なパフォーマンス最適化機能の 1 つである。個別に到着する推論リクエストを 1 つのバッチにまとめて GPU に送ることで、スループットを大幅に向上させる。

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:バッチを埋めるために追加リクエストを待つ最大時間。この時間が過ぎると、現在集まったリクエストで即座に実行する。レイテンシとスループット間のトレードオフを調整する重要なパラメータである。

7.2 Concurrent Model Execution

Triton は同一 GPU 上で複数のモデルインスタンスを同時に実行できる。これにより GPU の計算リソースをより効率的に活用する。

# 1 つの 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 でサポートされる機能で、1 つの物理 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. オートスケーリング戦略

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 あたりの 1 秒間のリクエスト数

9.3 GPU メトリクスベースのオートスケーリング

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. モニタリングで新バージョンのレイテンシ、エラー率などを確認
  3. 問題がなければ canaryTrafficPercent を 20 から 50、100 へと段階的に増加
  4. 問題発生時は canaryTrafficPercent: 0 で即座にロールバック

10.2 Blue-Green Deployment

Blue-Green Deployment では、2 つの完全な環境(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 の各段階のレイテンシをミリ秒単位で可視化する。

KServe Triton Latency Dashboard

Triton 専用ダッシュボードで、5 つのレイテンシグラフを提供する。

  • 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 リソースを効率的に共有できる。オートスケーリングは HPA、KPA、KEDA をワークロード特性に合わせて選択し、Canary/Blue-Green Deployment で安全なモデル更新を保証する。最後に Prometheus + Grafana + DCGM Exporter の組み合わせでモデルパフォーマンスと GPU リソースを総合的にモニタリングすべきである。

これら全ての構成要素を有機的に組み合わせることで、大規模 ML ワークロードを安定的かつ効率的に運用できるプロダクションレベルのモデルサービングプラットフォームを構築できる。


References