mcpField
M
model-serving-kubernetes

model-serving-kubernetes

github.com/bagelhole云与 DevOps1.2k329 次安装23 周前更新
代码仓库

关于 model-serving-kubernetes

面向在 Kubernetes 上部署机器学习模型的工程师,提供基于 KServe 和 Triton 的模型服务操作指南,涵盖流量切分、自动扩缩和 GPU 调度。

主要功能

  1. 01部署 KServe InferenceService
  2. 02配置模型金丝雀发布与流量切分
  3. 03按请求或 GPU 指标自动扩缩
  4. 04使用 Triton 管理模型版本
  5. 05配置动态批处理与 GPU 调度

适用场景

  1. 01在 Kubernetes 上部署机器学习模型
  2. 02逐步验证新模型版本并调整流量
  3. 03扩缩 LLM 推理服务
  4. 04管理 Triton 模型加载与卸载

安装

复制下面的命令,在终端中运行。

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

安装后在 Claude Code 中输入/model-serving-kubernetes确认已加载。

详细介绍

Kubernetes 上的模型服务

使用 KServe 和 Triton 提供生产级机器学习模型服务 — 金丝雀部署、自动扩缩容和 GPU 感知调度。

何时使用此技能

在以下情况下使用此技能:

  • 大规模提供 scikit-learn、PyTorch、TensorFlow 或 ONNX 模型服务
  • 为机器学习模型实现金丝雀部署和 A/B 测试
  • 根据请求速率或 GPU 指标对推理 Pod 进行自动扩缩容
  • 在 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 推理服务器

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模型加载或内存不足(OOM)检查预测器 Pod 日志;提高内存限制
金丝雀版本停留在 0%KNative 路由问题检查 kubectl get ksvc -n models
Triton 找不到模型S3 权限或路径问题验证 IAM 角色;检查 --model-store 路径
GPU 利用率低未启用动态批处理在 Triton 配置中启用 dynamic_batching
自动扩缩容未触发Prometheus 查询错误在 Prometheus UI 中测试查询

最佳实践

  • 对所有模型更新使用金丝雀部署 — 如果指标恶化,可在数秒内回滚。
  • 启用 Triton 动态批处理 — 对于小型模型,它可将 GPU 吞吐量提高 5–10 倍。
  • 将模型存储在 S3/GCS 中,并使用带版本号的路径(s3://bucket/model/v1/、v2/)。
  • 固定 GPU 节点选择器,防止模型 Pod 被调度到仅配备 CPU 的节点上。
  • 在金丝雀发布期间,按模型版本监控 p99 延迟和错误率。

相关技能

评论

支持 Markdown