mcpField
M
model-serving-kubernetes

model-serving-kubernetes

github.com/bagelholeクラウド・DevOps1.2k329 回インストール23 週間前に更新
リポジトリ

model-serving-kubernetes について

Kubernetes 上で KServe と Triton を使って機械学習モデルを提供するエンジニア向けのスキルです。カナリアリリース、自動スケーリング、GPU 対応スケジューリング、モデルバージョン管理を扱います。

主な機能

  1. 01KServe InferenceService のデプロイ
  2. 02カナリアリリースとトラフィック分割の設定
  3. 03リクエスト数や GPU 指標による自動スケーリング
  4. 04Triton によるモデルバージョン管理
  5. 05動的バッチ処理と GPU スケジューリングの設定

活用シーン

  1. 01Kubernetes 上での機械学習モデル提供
  2. 02新しいモデルバージョンへの段階的なトラフィック移行
  3. 03LLM 推論サービスのスケーリング
  4. 04Triton モデルのロードとアンロード

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill model-serving-kubernetes

インストール後、Claude Code で/model-serving-kubernetesを入力して読み込まれたか確認します。

詳細

Kubernetes でのモデルサービング

KServe と Triton を使用した本番環境向け ML モデルサービング — カナリアデプロイ、自動スケーリング、GPU を考慮したスケジューリング。

このスキルを使用する場面

次のような場合に、このスキルを使用します:

  • scikit-learn、PyTorch、TensorFlow、または ONNX モデルを大規模にサービングする
  • ML モデルのカナリアデプロイと A/B テストを実装する
  • リクエストレートまたは GPU メトリクスに基づいて推論ポッドを自動スケーリングする
  • Kubernetes 上で Triton または KServe を使用して LLM をデプロイする
  • トラフィック分割を使用して複数のモデルバージョンを管理する

前提条件

  • GPU ノードを備えた Kubernetes 1.28+
  • KServe がインストール済み(または Triton スタンドアロン)
  • kubectl と helm が設定済み
  • クラスターに NVIDIA GPU Operator がインストール済み

KServe のインストール

# Install KServe with Helm
helm repo add kserve https://kserve.github.io/helm-charts
helm repo update

helm install kserve kserve/kserve \
  --namespace kserve \
  --create-namespace \
  --set kserve.controller.gateway.ingressGateway.className=nginx

# Verify
kubectl get pods -n kserve
kubectl get crd | grep kserve

基本的な InferenceService(KServe)

apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
  name: sklearn-iris
  namespace: models
spec:
  predictor:
    sklearn:
      storageUri: gs://kfserving-examples/models/sklearn/1.0/model
      resources:
        requests:
          cpu: "1"
          memory: 2Gi
        limits:
          cpu: "2"
          memory: 4Gi
kubectl apply -f inference-service.yaml

# Get inference service URL
kubectl get inferenceservice sklearn-iris -n models
# NAME           URL                                          READY   ...
# sklearn-iris   http://sklearn-iris.models.example.com       True

# Test prediction
curl -X POST http://sklearn-iris.models.example.com/v1/models/sklearn-iris:predict \
  -H "Content-Type: application/json" \
  -d '{"instances": [[6.8, 2.8, 4.8, 1.4]]}'

GPU 対応 LLM InferenceService

apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
  name: llama-3-8b
  namespace: models
  annotations:
    serving.kserve.io/enable-prometheus-scraping: "true"
spec:
  predictor:
    containers:
    - name: vllm-container
      image: vllm/vllm-openai:latest
      args:
      - "--model"
      - "meta-llama/Llama-3.1-8B-Instruct"
      - "--tensor-parallel-size"
      - "1"
      - "--gpu-memory-utilization"
      - "0.90"
      ports:
      - containerPort: 8080
        protocol: TCP
      resources:
        requests:
          nvidia.com/gpu: "1"
          memory: "20Gi"
          cpu: "4"
        limits:
          nvidia.com/gpu: "1"
          memory: "24Gi"
          cpu: "8"
      readinessProbe:
        httpGet:
          path: /health
          port: 8080
        initialDelaySeconds: 60
        periodSeconds: 10
      env:
      - name: HUGGING_FACE_HUB_TOKEN
        valueFrom:
          secretKeyRef:
            name: hf-token
            key: token
    nodeSelector:
      nvidia.com/gpu.present: "true"
  transformer:
    containers:
    - name: kserve-container
      image: kserve/kserve-transformer:latest

カナリアデプロイ(トラフィック分割)

apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
  name: llama-3-8b
  namespace: models
spec:
  predictor:
    canaryTrafficPercent: 20    # 20% to new version, 80% to stable
    containers:
    - name: vllm-container
      image: vllm/vllm-openai:latest
      args:
      - "--model"
      - "meta-llama/Llama-3.1-8B-Instruct-v2"  # new model version
      resources:
        limits:
          nvidia.com/gpu: "1"
# Gradually increase canary traffic
kubectl patch inferenceservice llama-3-8b -n models \
  --type='json' \
  -p='[{"op":"replace","path":"/spec/predictor/canaryTrafficPercent","value":50}]'

# Promote canary to stable
kubectl patch inferenceservice llama-3-8b -n models \
  --type='json' \
  -p='[{"op":"remove","path":"/spec/predictor/canaryTrafficPercent"}]'

KEDA による自動スケーリング

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: llama-scaler
  namespace: models
spec:
  scaleTargetRef:
    apiVersion: serving.kserve.io/v1beta1
    kind: InferenceService
    name: llama-3-8b
  minReplicaCount: 1
  maxReplicaCount: 5
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus-server.monitoring:9090
      metricName: kserve_request_count
      threshold: "10"
      query: |
        sum(rate(kserve_request_count_total{namespace="models",
            service="llama-3-8b"}[1m]))

NVIDIA Triton Inference Server

apiVersion: apps/v1
kind: Deployment
metadata:
  name: triton-server
  namespace: models
spec:
  replicas: 2
  selector:
    matchLabels:
      app: triton
  template:
    metadata:
      labels:
        app: triton
    spec:
      containers:
      - name: triton
        image: nvcr.io/nvidia/tritonserver:24.05-py3
        args:
        - "tritonserver"
        - "--model-store=s3://my-model-store/models"
        - "--model-control-mode=poll"        # auto-load new model versions
        - "--repository-poll-secs=30"
        - "--metrics-port=8002"
        ports:
        - containerPort: 8000   # HTTP
        - containerPort: 8001   # gRPC
        - containerPort: 8002   # Metrics
        resources:
          limits:
            nvidia.com/gpu: "1"
        readinessProbe:
          httpGet:
            path: /v2/health/ready
            port: 8000
          initialDelaySeconds: 30

Triton モデルリポジトリの構造

s3://my-model-store/models/
├── text-classifier/
│   ├── config.pbtxt
│   ├── 1/
│   │   └── model.onnx
│   └── 2/
│       └── model.onnx          # new version; auto-loaded
├── embedding-model/
│   ├── config.pbtxt
│   └── 1/
│       └── model.onnx
# config.pbtxt for ONNX model
name: "text-classifier"
backend: "onnxruntime"
max_batch_size: 64
dynamic_batching {
  preferred_batch_size: [16, 32]
  max_queue_delay_microseconds: 1000
}
input [
  { name: "input_ids" data_type: TYPE_INT64 dims: [-1] }
  { name: "attention_mask" data_type: TYPE_INT64 dims: [-1] }
]
output [
  { name: "logits" data_type: TYPE_FP32 dims: [-1] }
]
instance_group [
  { kind: KIND_GPU count: 2 }   # 2 model instances on GPU
]

モデル管理コマンド

# List loaded models (Triton)
curl http://triton:8000/v2/models

# Load a new model version
curl -X POST http://triton:8000/v2/repository/models/text-classifier/load

# Unload a model
curl -X POST http://triton:8000/v2/repository/models/text-classifier/unload

# KServe — watch rollout status
kubectl rollout status deployment/llama-3-8b-predictor -n models
kubectl get inferenceservice llama-3-8b -n models -w

よくある問題

問題原因対処方法
InferenceService not readyモデルの読み込みまたは OOMPredictor ポッドのログを確認し、メモリ制限を増やします
カナリアが 0% のままKNative のルーティングの問題kubectl get ksvc -n models を確認します
Triton でモデルが見つからないS3 の権限またはパスIAM ロールを確認し、--model-store のパスを確認します
GPU 使用率が低い動的バッチ処理が無効Triton の設定で dynamic_batching を有効にします
オートスケーラーが動作しないPrometheus クエリが誤っているPrometheus UI でクエリをテストします

ベストプラクティス

  • すべてのモデル更新でカナリアデプロイを使用します — メトリクスが悪化した場合、数秒でロールバックできます。
  • Triton の動的バッチ処理を有効にします — 小規模モデルでは GPU スループットを 5~10 倍に向上できます。
  • モデルはバージョン付きパス(s3://bucket/model/v1/、v2/)を使用して S3/GCS に保存します。
  • GPU ノードセレクターを指定し、モデルポッドが CPU のみのノードに配置されないようにします。
  • カナリアロールアウト中は、モデルバージョンごとに p99 レイテンシーとエラー率を監視します。

関連スキル

コメント