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

Container Service for Kubernetes:NGINX Ingress コントローラーに基づく推論サービスのカナリアリリースの実装

最終更新日:May 08, 2025

Raw Deployment モードでは、ゲートウェイに基づいてアプリケーションのカナリアリリースを実装できます。このトピックでは、推論サービスのカナリアリリースを実装し、推論サービスをバージョン v1 から v2 に更新する方法について説明します。この例では、NGINX Ingress コントローラーをゲートウェイとして使用します。

前提条件

手順

このトピックでは、canary という名前のモデルから、異なるバージョンの v1 と v2 の 2 つの推論サービスをデプロイします。このトピックでは、推論サービスを v1 から v2 にアップグレードするための 2 つのカナリアリリース ポリシーについて説明します。

  • リクエストに基づくトラフィック分割

    foo ヘッダーが bar に設定されている リクエストを model-v2-svc サービスに転送します。他のリクエストは、デフォルトで model-svc サービスに転送されます。

  • サービスの重み付けに基づくトラフィック分割

    リクエストの 20% を model-v2-svc サービスに転送し、残りのリクエストを model-svc サービスに転送します。

NGINX Ingress コントローラーを使用してカナリアリリースを実装する方法の詳細については、「NGINX Ingress コントローラーを使用してカナリアリリースとブルーグリーンリリースを実装する」をご参照ください。

ステップ 1:推論サービスのデプロイと検証

v1

  1. canary モデルから v1 の推論サービスをデプロイします。

    arena serve kserve \
        --name=model-v1 \
        --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/ai-sample/kserve-canary:1.0.0 \
        --cpu=1 \
        --memory=2Gi \
        "python app.py --model_name=canary"
  2. v1 の推論サービスのサービスを作成します。

    1. model-svc.yaml という名前のファイルを作成します。

      apiVersion: v1
      kind: Service
      metadata:
        name: model-svc
      spec:
        ports:
        - port: 80
          protocol: TCP
          targetPort: 8080
        selector:
          serving.kserve.io/inferenceservice: model-v1
        type: ClusterIP
    2. サービスを作成します。

      kubectl apply -f model-svc.yaml
  3. NGINX Ingress を使用して model-v1 という名前の推論サービスにアクセスし、model-v1 が正しくデプロイされているかどうかを確認します。

    curl -H "Host: $(kubectl get inferenceservice model-v1 -o jsonpath='{.status.url}' | cut -d "/" -f 3)" \
         -H "Content-Type: application/json" \
         http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \
         -d '{"data": "test"}'

v2

  1. canary モデルから v2 の推論サービスをデプロイします。

    arena serve kserve \
        --name=model-v2 \
        --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/ai-sample/kserve-canary:1.0.0 \
        --cpu=1 \
        --memory=2Gi \
        "python app-v2.py --model_name=canary"
  2. v2 の推論サービスのサービスを作成します。

    1. model-v2-svc.yaml という名前のファイルを作成します。

      apiVersion: v1
      kind: Service
      metadata:
        name: model-v2-svc
      spec:
        ports:
        - port: 80
          protocol: TCP
          targetPort: 8080
        selector:
          serving.kserve.io/inferenceservice: model-v2
        type: ClusterIP
    2. サービスを作成します。

      kubectl apply -f model-v2-svc.yaml
  3. NGINX Ingress を使用して model-v2 という名前の推論サービスにアクセスし、model-v2 が正しくデプロイされているかどうかを確認します。

    curl -H "Host: $(kubectl get inferenceservice model-v2 -o jsonpath='{.status.url}' | cut -d "/" -f 3)" \
         -H "Content-Type: application/json" \
         http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \
         -d '{"data": "test"}'

ステップ 2:Ingress の作成

  1. model-ingress.yaml という名前のファイルを作成します。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: model-ingress
    spec:
      rules:
      - host: model.example.com # ホスト名で値を置き換えます。
        http:
          paths:
          # v1 の推論サービス用に作成されたサービスの情報。
          - path: /
            backend:
              service: 
                name: model-svc
                port:
                  number: 80
            pathType: ImplementationSpecific
  2. Ingress を作成します。

    kubectl apply -f model-ingress.yaml

ステップ 3:カナリアリリース ポリシーの作成と検証

シナリオ 1:クライアント リクエストに基づくトラフィック分割

  1. gray-release-canary.yaml という名前のファイルを作成します。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gray-release-canary
      annotations:
        # カナリアリリース機能を有効にします。
        nginx.ingress.kubernetes.io/canary: "true"
        # リクエスト ヘッダーを foo に設定します。
        nginx.ingress.kubernetes.io/canary-by-header: "foo"
        # foo ヘッダーを bar に設定します。この場合、foo ヘッダーが bar に設定されているリクエストは、新しいサービス バージョン (model-v2) にルーティングされます。
        nginx.ingress.kubernetes.io/canary-by-header-value: "bar"
    spec:
      rules:
      - host: model.example.com
        http:
          paths:
          # model-v2 用に作成されたサービスの情報。
          - path: /
            backend:
              service: 
                name: model-v2-svc
                port:
                  number: 80
            pathType: ImplementationSpecific
  2. カナリアリリース ポリシーをデプロイします。

    kubectl apply -f gray-release-canary.yaml
  3. 特定のヘッダーのないリクエストに対して、デフォルト バージョンのサービスが応答を返すかどうかを確認します。

    # 次のサンプル コードのホスト名を、Ingress で指定されたホスト名に置き換えます。
    curl -H "Host: model.example.com" -H "Content-Type: application/json" \
         http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \
         -d '{"data": "test"}'

    期待される出力:

    {"id":"4d8c110d-c291-4670-ad0a-1a30bf8e314c","model_name":"canary","model_version":null,"outputs":[{"name":"output-0","shape":[1,1],"datatype":"STR","data":["model-v1"]}]}%  

    出力は、model-v1 が応答を返していることを示しています。これは、デフォルトで想定どおりに model-v1 に送信されたリクエストに対して、サービスが推論結果を返すことができることを示しています。この場合、トラフィックは model-v1 に転送されます。

  4. 次のコマンドを実行して、foo ヘッダーが bar に設定されている クライアント リクエストが model-v2 に転送されるかどうかを確認します。

    curl -H "Host: model.example.com" -H "Content-Type: application/json" \
         -H "foo: bar" \
         http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \
         -d '{"data": "test"}'

    期待される出力:

    {"id":"4d3efc12-c8bd-40f8-898f-7983377db7bd","model_name":"canary","model_version":null,"outputs":[{"name":"output-0","shape":[1,1],"datatype":"STR","data":["model-v2"]}]}%   

    出力は、model-v2 が応答を返していることを示しています。これは、想定どおりに model-v2 に送信された特定のヘッダーを持つリクエストに対して、サービスが推論結果を返すことができることを示しています。カナリアリリース ポリシーが有効になっています。

シナリオ 2:サービスの重み付けに基づくトラフィック分割

  1. gray-release-canary.yaml という名前のファイルを作成します。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: gray-release-canary
      annotations:
        # カナリアリリース機能を有効にします。
        nginx.ingress.kubernetes.io/canary: "true"
        # リクエストの 20% のみ model-v2 に転送します。
        # デフォルトの合計重みは 100 です。
        nginx.ingress.kubernetes.io/canary-weight: "20"
    spec:
      rules:
      - host: model.example.com
        http:
          paths:
          # v2 の推論サービス用に作成されたサービスの情報。
          - path: /
            backend:
              service: 
                name: model-v2-svc
                port:
                  number: 80
            pathType: ImplementationSpecific
  2. カナリアリリース ポリシーをデプロイします。

    kubectl apply -f gray-release-canary.yaml
  3. トラフィック分散を確認します。

    curl -H "Host: model.example.com" -H "Content-Type: application/json" \
         http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \
         -d '{"data": "test"}'

    上記のコマンドを複数回実行します。結果は、リクエストの約 20% が model-v2 に転送され、残りは以前のサービス バージョン (model-v1) に転送されることを示しています。これは、カナリアリリース ポリシーが有効になっていることを示しています。

ステップ 4:トラフィックを新しいサービス バージョンに切り替える

model-v2 が一定期間想定どおりに実行された場合は、model-v2 をオフラインにして、新しいサービス バージョンのみをアクセスできるようにする必要があります。

  1. model-svc.yaml ファイルを更新して、model-v2 を model-svc サービスのバックエンド アプリケーションとして指定します。

    apiVersion: v1
    kind: Service
    metadata:
      name: model-svc
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        serving.kserve.io/inferenceservice: model-v2 # model-v1 を model-v2 に置き換えます。
      type: ClusterIP
  2. 次のコマンドを実行して、サービスを再デプロイします。

    kubectl apply -f model-svc.yaml 
  3. Ingress へのアクセスをテストします。

    curl -H "Host: model.example.com" -H "Content-Type: application/json" \
         http://$(kubectl -n kube-system get svc nginx-ingress-lb -ojsonpath='{.status.loadBalancer.ingress[0].ip}'):80/v1/models/canary:predict -X POST \
         -d '{"data": "test"}'

    期待される出力:

    {"id":"a13f2089-73ce-41e3-989e-e58457d14fed","model_name":"canary","model_version":null,"outputs":[{"name":"output-0","shape":[1,1],"datatype":"STR","data":["model-v2"]}]}%  

    上記のコマンドを複数回実行します。結果は、リクエストの約 100% が model-v2 に転送されることを示しています。

  4. 次のコマンドを実行して、model-v1 と関連リソースを削除します。

    kubectl delete ingress gray-release-canary
    arena serve delete model-v1
    kubectl delete svc model-v2-svc