すべてのプロダクト
Search
ドキュメントセンター

Alibaba Cloud Service Mesh:動的サブセット負荷分散を使用した Model Service Mesh 推論の高速化

最終更新日:Mar 12, 2026

複数のモデルをデプロイする Model Service Mesh 環境では、Kubernetes サービスは推論リクエストをすべてのモデルサービングランタイムにランダムに分散します。リクエストがターゲットモデルをホストしていないランタイムに到達した場合、Model Service Mesh は正しいランタイムを見つけるまで内部的に再ルーティングします。この再ルーティングにより、レイテンシーが増加します。

動的サブセット負荷分散は、モデルをホストするランタイムをグループ化することで、この問題を解決します。推論リクエストが Service Mesh (ASM) ゲートウェイに到着すると、ゲートウェイはリクエストヘッダーからモデル名を読み取り、そのモデルをホストするランタイムにリクエストを直接ルーティングします。これにより、再ルーティングが不要になり、推論レイテンシーが削減されます。

概念の概要については、「動的サブセット負荷分散」をご参照ください。

仕組み

動的サブセット負荷分散は、2 つの Istio リソースに依存しています。DestinationRule は *どのランタイムをグループ化するか* を定義し、VirtualService は *リクエストをそれらのグループにどのように一致させるか* を定義します。

  • DestinationRule はランタイムをサブセットにグループ化します。ASM は、標準の DestinationRule を dynamicSubset フィールドで拡張し、エンドポイントをラベルキーでグループ化します。Model Service Mesh は、モデルがロードまたはアンロードされるとランタイムラベルを自動的に更新するため、手動介入なしでサブセットは最新の状態に保たれます。

  • VirtualService は受信リクエストをサブセットに一致させます。ASM は、標準のVirtualService を headerToDynamicSubsetKey フィールドで拡張し、リクエストヘッダー (例: model) を動的サブセットラベルキーにマップします。ゲートウェイは、このマッピングを使用して、各リクエストを正しいサブセットにルーティングします。

リクエストに一致するサブセットがない場合、fallbackPolicy が次の動作を決定します。

フォールバックポリシー動作
ANY_ENDPOINTラベルに関係なく、利用可能な任意のランタイムにルーティングします。潜在的な再ルーティングのコストを伴いますが、可用性を維持します。このチュートリアルで使用されます。

前提条件

開始する前に、次のことを確認してください。

ステップ 1: 2 番目のモデルをデプロイする

動的サブセット負荷分散は、複数モデルシナリオを対象としています。このステップでは、既存の sklearn-mnist モデルに加えて、tf-mnist モデル (Triton ランタイムによって提供される TensorFlow ベースの MNIST モデル) を追加します。

説明

このステップでは、「Model Service Mesh を使用した複数モデル推論サービスのロールアウト」で作成された永続ボリューム要求 (PVC) my-models-pvc を使用します。tf-mnist モデルの内容は、mnist ディレクトリ内のすべてです。

モデルを永続ボリュームに保存する

  1. kubectl を使用して ACK クラスターに接続し、mnist モデルディレクトリを永続ボリュームにコピーします。

    kubectl -n modelmesh-serving cp mnist pvc-access:/mnt/models/
  2. モデルが永続ボリュームに存在することを確認します。

    kubectl -n modelmesh-serving exec -it pvc-access -- ls -alr /mnt/models/

    期待される出力:

    -rw-r--r-- 1  502 staff 344817 Apr 23 08:17 mnist-svm.joblib
    drwxr-xr-x 3 root root    4096 Apr 23 08:23 mnist
    drwxr-xr-x 1 root root    4096 Apr 23 08:17 ..
    drwxrwxrwx 3 root root    4096 Apr 23 08:23 .

推論サービスをデプロイする

  1. 次の内容で tf-mnist.yaml という名前のファイルを作成します。

    apiVersion: serving.kserve.io/v1beta1
    kind: InferenceService
    metadata:
      name: tf-mnist
      namespace: modelmesh-serving
      annotations:
        serving.kserve.io/deploymentMode: ModelMesh
    spec:
      predictor:
        model:
          modelFormat:
            name: tensorflow
          storage:
            parameters:
              type: pvc
              name: my-models-pvc
            path: mnist
  2. マニフェストを適用します。

    kubectl apply -f tf-mnist.yaml
  3. イメージのプルが完了するまで待機し、両方のモデルが準備完了であることを確認します。

    kubectl get isvc -n modelmesh-serving

    期待される出力:

    NAME            URL                                               READY
    sklearn-mnist   grpc://modelmesh-serving.modelmesh-serving:8033   True
    tf-mnist        grpc://modelmesh-serving.modelmesh-serving:8033   True

(オプション) ステップ 2: 最適化前の推論レイテンシーをベンチマークする

動的サブセット負荷分散を有効にする前に、fortio を使用してベースラインレイテンシーを測定します。ASM イングレスゲートウェイの IP アドレスを取得するには、「KServe と ASM を統合してクラウドネイティブ AI モデルに基づく推論サービスを実装する」をご参照ください。

  1. ゲートウェイ IP を設定し、tf-mnist モデルに対して 60 秒間の負荷テストを実行します。

    ASM_GW_IP="<your-asm-gateway-ip>"
    fortio load -jitter=False -H 'model: tf-mnist' -c 1 -qps 100 -t 60s -payload '{"inputs": [{ "name": "inputs", "shape": [1, 784], "datatype": "FP32", "contents": { "fp32_contents": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.01176471, 0.07058824, 0.07058824, 0.07058824, 0.49411765, 0.53333336, 0.6862745, 0.10196079, 0.6509804, 1.0, 0.96862745, 0.49803922, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.11764706, 0.14117648, 0.36862746, 0.6039216, 0.6666667, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.88235295, 0.6745098, 0.99215686, 0.9490196, 0.7647059, 0.2509804, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.19215687, 0.93333334, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.9843137, 0.3647059, 0.32156864, 0.32156864, 0.21960784, 0.15294118, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.07058824, 0.85882354, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.7764706, 0.7137255, 0.96862745, 0.94509804, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3137255, 0.6117647, 0.41960785, 0.99215686, 0.99215686, 0.8039216, 0.04313726, 0.0, 0.16862746, 0.6039216, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.05490196, 0.00392157, 0.6039216, 0.99215686, 0.3529412, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.54509807, 0.99215686, 0.74509805, 0.00784314, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.04313726, 0.74509805, 0.99215686, 0.27450982, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.13725491, 0.94509804, 0.88235295, 0.627451, 0.42352942, 0.00392157, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.31764707, 0.9411765, 0.99215686, 0.99215686, 0.46666667, 0.09803922, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1764706, 0.7294118, 0.99215686, 0.99215686, 0.5882353, 0.10588235, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0627451, 0.3647059, 0.9882353, 0.99215686, 0.73333335, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.9764706, 0.99215686, 0.9764706, 0.2509804, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.18039216, 0.50980395, 0.7176471, 0.99215686, 0.99215686, 0.8117647, 0.00784314, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.15294118, 0.5803922, 0.8980392, 0.99215686, 0.99215686, 0.99215686, 0.98039216, 0.7137255, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.09411765, 0.44705883, 0.8666667, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.7882353, 0.30588236, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.09019608, 0.25882354, 0.8352941, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.7764706, 0.31764707, 0.00784314, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.07058824, 0.67058825, 0.85882354, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.7647059, 0.3137255, 0.03529412, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.21568628, 0.6745098, 0.8862745, 0.99215686, 0.99215686, 0.99215686, 0.99215686, 0.95686275, 0.52156866, 0.04313726, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.53333336, 0.99215686, 0.99215686, 0.99215686, 0.83137256, 0.5294118, 0.5176471, 0.0627451, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] }}]}' -a ${ASM_GW_IP}:8008/v2/models/tf-mnist/infer

    期待される出力:

    期待される出力

    16:06:53.107 r1 [INF] scli.go:125> Starting, command="Φορτίο", version="1.63.7 h1:S6e+z36nV6o8RYQSUI9EWYxhCoPJy4VdAB2HQROUqMg= go1.22.2 amd64 linux", go-max-procs=8
    Fortio 1.63.7 running at 100 queries per second, 8->8 procs, for 1m0s: 192.168.0.7:8008/v2/models/tf-mnist/infer
    16:06:53.107 r1 [INF] httprunner.go:121> Starting http test, run=0, url="192.168.0.7:8008/v2/models/tf-mnist/infer", threads=1, qps="100.0", warmup="parallel", conn-reuse=""
    16:06:53.107 r1 [WRN] http_client.go:170> Assuming http:// on missing scheme for '192.168.0.7:8008/v2/models/tf-mnist/infer'
    Starting at 100 qps with 1 thread(s) [gomax 8] for 1m0s : 6000 calls each (total 6000)
    16:07:53.172 r1 [INF] periodic.go:851> T000 ended after 1m0.007662555s : 6000 calls. qps=99.98723070575699
    Ended after 1m0.007716622s : 6000 calls. qps=99.987
    16:07:53.172 r1 [INF] periodic.go:581> Run ended, run=0, elapsed=60007716622, calls=6000, qps=99.98714061718327
    Sleep times : count 5999 avg 0.0021861297 +/- 0.001025 min -0.011550303 max 0.003734337 sum 13.1145918
    Aggregated Function Time : count 6000 avg 0.0072130591 +/- 0.0007502 min 0.006125677 max 0.020551562 sum 43.2783545
    # range, mid point, percentile, count
    >= 0.00612568 <= 0.007 , 0.00656284 , 35.88, 2153
    > 0.007 <= 0.008 , 0.0075 , 90.85, 3298
    > 0.008 <= 0.009 , 0.0085 , 97.77, 415
    > 0.009 <= 0.01 , 0.0095 , 99.42, 99
    > 0.01 <= 0.011 , 0.0105 , 99.68, 16
    > 0.011 <= 0.012 , 0.0115 , 99.77, 5
    > 0.012 <= 0.014 , 0.013 , 99.90, 8
    > 0.014 <= 0.016 , 0.015 , 99.95, 3
    > 0.016 <= 0.018 , 0.017 , 99.97, 1
    > 0.018 <= 0.02 , 0.019 , 99.98, 1
    > 0.02 <= 0.0205516 , 0.0202758 , 100.00, 1
    # target 50% 0.00725682
    # target 75% 0.00771164
    # target 90% 0.00798454
    # target 99% 0.00974747
    # target 99.9% 0.014
    Error cases : no data
    # Socket and IP used for each connection:
    [0]   1 socket used, resolved to 192.168.0.7:8008, connection timing : count 1 avg 0.004218262 +/- 0 min 0.004218262 max 0.004218262 sum 0.004218262
    Connection time histogram (s) : count 1 avg 0.004218262 +/- 0 min 0.004218262 max 0.004218262 sum 0.004218262
    # range, mid point, percentile, count
    >= 0.00421826 <= 0.00421826 , 0.00421826 , 100.00, 1
    # target 50% 0.00421826
    # target 75% 0.00421826
    # target 90% 0.00421826
    # target 99% 0.00421826
    # target 99.9% 0.00421826
    Sockets used: 1 (for perfect keepalive, would be 1)
    Uniform: false, Jitter: false, Catchup allowed: true
    IP addresses distribution:
    192.168.0.7:8008: 1
    Code 200 : 6000 (100.0 %)
    Response Header Sizes : count 6000 avg 233.00067 +/- 0.02581 min 233 max 234 sum 1398004
    Response Body/Total Sizes : count 6000 avg 454.00067 +/- 0.02581 min 454 max 455 sum 2724004
    All done 6000 calls (plus 1 warmup) 7.213 ms avg, 100.0 qps
    Successfully wrote 11561 bytes of Json data to 2024-04-24-160653_192_168_0_7_8008_v2_models_tf_mnist_infer_iZbp1jfq2w26u2kpxa9r3dZ.json
  2. ブラウザで fortio の結果を表示します。

    fortio server

    localhost:8080 を開き、[saved results] をクリックして、JSON ファイルを選択し、レイテンシーディストリビューションを表示します。

    Latency distribution before optimization

    動的サブセット負荷分散が有効になっていない場合、一部の推論リクエストは、正しいランタイムに到達する前に Model Service Mesh を介して再ルーティングされるため、レイテンシーが増加します。

ステップ 3: 動的サブセット負荷分散を有効にする

推論リクエストは、modelmesh-serving 名前空間の modelmesh-serving サービスを介して Model Service Mesh に到達します。このサービスで DestinationRule と VirtualService を構成して、リクエストを正しいモデルサービングランタイムに直接ルーティングします。

DestinationRule を作成する

次の DestinationRule を適用して、モデルサービングランタイムをホストするモデルによって動的にグループ化します。詳細については、「宛先ルールの管理」をご参照ください。

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: modelmesh-serving
  namespace: modelmesh-serving
spec:
  host: modelmesh-serving
  trafficPolicy:
    loadBalancer:
      dynamicSubset:
        subsetSelectors:
          - fallbackPolicy: ANY_ENDPOINT
            keys:
              - modelmesh.asm.alibabacloud.com

主要なフィールド:

フィールド目的
dynamicSubset静的サブセット定義ではなく、ランタイムラベルに基づいてエンドポイントの動的なグループ化を有効にします。
keysランタイムをグループ化するために使用されるラベルキーです。Model Service Mesh は、各ランタイムに modelmesh.asm.alibabacloud.com ラベルを設定して、ホストするモデルを示します。
fallbackPolicy: ANY_ENDPOINTサブセットが一致しない場合、リクエストを拒否する代わりに、利用可能な任意のランタイムにルーティングします。

VirtualService を更新する

次の VirtualService を適用して、model リクエストヘッダーを動的サブセットキーにマップします。詳細については、「仮想サービスの管理」をご参照ください。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: vs-modelmesh-serving-service
  namespace: modelmesh-serving
spec:
  gateways:
    - grpc-gateway
  hosts:
    - '*'
  http:
    - headerToDynamicSubsetKey:
        - header: model
          key: modelmesh.asm.alibabacloud.com
      match:
        - port: 8008
      name: default
      route:
        - destination:
            host: modelmesh-serving
            port:
              number: 8033

headerToDynamicSubsetKey フィールドは、標準 Istio VirtualService の ASM 拡張です。ゲートウェイが model: tf-mnist ヘッダーを持つリクエストを受信すると、modelmesh.asm.alibabacloud.com ラベルに対して値を検索し、一致する動的サブセット内のランタイムにリクエストをルーティングします。

(オプション) ステップ 4: 最適化後の推論レイテンシーをベンチマークする

ステップ 2 と同じ fortio テストを実行して、レイテンシーを比較します。

Latency distribution after optimization

動的サブセット負荷分散を有効にすると、すべての推論リクエストが正しいランタイムに直接ルーティングされます。レイテンシーディストリビューションは大幅に改善され、内部再ルーティングによって引き起こされる外れ値はなくなります。