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

Container Service for Kubernetes:KnativeでAI推論サービスをデプロイするためのベストプラクティス

最終更新日:Oct 21, 2024

KnativeをAIとともに使用すると、モデル推論シナリオなど、AIアプリケーション用にコンピューティングリソースを頻繁に調整する必要があるシナリオで、迅速なデプロイ、高い柔軟性、およびコスト効率を活用できます。 AIモデルを推論サービスとしてKnativeポッドにデプロイし、自動スケーリングを設定し、GPUリソースを柔軟に割り当てて、GPUリソースの利用率を向上させ、AI推論のパフォーマンスを向上させることができます。

加速されたモデル展開

Knative ServingにデプロイされたAI推論サービスをオンデマンドで迅速にスケーリングできるようにするには、AIモデルをコンテナイメージにパッケージ化しないようにする必要があります。 AIモデルをコンテナイメージにパッケージ化すると、コンテナイメージが非常に大きくなり、コンテナの展開が遅くなります。 さらに、AIモデルのバージョンはコンテナイメージバージョンにバインドされているため、バージョン管理がより複雑になります。

上記の問題を回避するには、AIモデルに関連するすべてのデータをObject storage Service (OSS) やApsara File Storage NAS (NAS) などの外部ストレージシステムにアップロードし、永続ボリュームクレーム (PVC) を作成してストレージシステムをKnative Serviceのポッドにマウントすることをお勧めします。 また、分散データセットオーケストレーションおよびアクセラレーションエンジンであるFluidを使用して、AIモデルのプルとロードを高速化することもできます。 これにより、数秒以内に大きな言語モデルをロードできます。 詳細については、「Use JindoFS to accelerate access to OSS」および「EFCを使用したNASファイルシステムへのアクセスの高速化」をご参照ください。

前提条件

手順1: データセットの定義

AIモデルがOSSに保存されている場合は、Dataset CustomResource (CR) を作成してOSSでモデルのデータセットを宣言し、JindoRuntimeを使用してキャッシュタスクを実行できます。

サンプルYAMLコンテンツの表示

apiVersion: v1
kind: Secret
metadata:
  name: access-key
stringData:
  fs.oss.accessKeyId: your_ak_id   # Replace with the AccessKey ID used to access OSS. 
  fs.oss.accessKeySecret: your_ak_skrt   # Replace with the AccessKey secret used to access OSS. 
---
apiVersion: data.fluid.io/v1alpha1
kind: Dataset
metadata:
  name: oss-data
spec:
  mounts:
  - mountPoint: "oss://{Bucket}/{path-to-model}" # Replace with the OSS bucket and OSS path where the model is stored. 
    name: xxx
    path: "{path-to-model}" # Replace with the path of the model to be loaded. 
    options:
      fs.oss.endpoint: "oss-cn-beijing.aliyuncs.com"  # Replace with the endpoint of the OSS bucket. 
    encryptOptions:
      - name: fs.oss.accessKeyId
        valueFrom:
          secretKeyRef:
            name: access-key
            key: fs.oss.accessKeyId
      - name: fs.oss.accessKeySecret
        valueFrom:
          secretKeyRef:
            name: access-key
            key: fs.oss.accessKeySecret
  accessModes:
    - ReadOnlyMany
---
apiVersion: data.fluid.io/v1alpha1
kind: JindoRuntime
metadata:
  name: oss-data
spec:
  replicas: 2
  tieredstore:
    levels:
      - mediumtype: SSD
        volumeType: emptyDir
        path: /mnt/ssd0/cache
        quota: 100Gi
        high: "0.95"
        low: "0.7"
  fuse:
    properties:
      fs.jindofsx.data.cache.enable: "true"
    args:
      - -okernel_cache
      - -oro
      - -oattr_timeout=7200
      - -oentry_timeout=7200
      - -ometrics_port=9089
    cleanPolicy: OnDemand

手順2: PVCをマウントしてOSSへのアクセスを高速化

Dataset CRとJindoRuntime CRを宣言すると、Datasetという名前のPVCが自動的に作成され、そのPVCがKnative Serviceにマウントされ、OSSへのアクセスが高速化されます。

サンプルYAMLコンテンツの表示

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: sd-backend
spec:
  template:
    spec:
      containers:
        - image: <YOUR-IMAGE>   # Replace <YOUR-IMAGE> with the name of the image. 
          name: image-name
          ports:
            - containerPort: xxx
              protocol: TCP
          volumeMounts:
            - mountPath: /data/models  # The path of the model to be loaded. Replace with the value of moutPath. 
              name: data-volume
      volumes:
        - name: data-volume
          persistentVolumeClaim:
            claimName: oss-data   # Mount a PVC with the same name as the Dataset.

ステップ3: イメージキャッシュを使用して数秒以内にモデルをデプロイする

AIモデルのサイズに加えて、Knativeサービスに対するコンテナーイメージのサイズの影響を考慮する必要があります。 AIモデルの実行に使用されるコンテナイメージは、通常、CUDAやpytorch-gpuなどの依存関係でパッケージ化されます。 これらの依存関係により、コンテナイメージのサイズが大きくなります。 エラスティックコンテナインスタンスのポッドにKnative AI推論サービスをデプロイする場合は、イメージキャッシュを使用してイメージプルを高速化することを推奨します。 エラスティックコンテナインスタンスにポッドをデプロイするために使用されるイメージのキャッシュは、システムが数秒以内にイメージをプルできるように事前に作成されています。 詳細については、「ImageCacheを使用したエラスティックコンテナインスタンスの作成の高速化」をご参照ください。

apiVersion: eci.alibabacloud.com/v1
kind: ImageCache
metadata:
  name: imagecache-ai-model
  annotations:
    k8s.aliyun.com/eci-image-cache: "true" # Enable the reuse of image caches. 
spec:
  images:
  - <YOUR-IMAGE>
  imageCacheSize:
    25 # The size of each image cache. Unit: GiB. 
  retentionDays:
    7 # The retention period of image caches.

優雅なポッドのシャットダウン

進行中の要求が中断されないようにするには、SIGTERM信号を受信した後、ポッドを特定の方法でシャットダウンする必要があります。

  • アプリケーションがHTTPプロービングを使用する場合、アプリケーションポッドがSIGTERM信号を受信した後、新しい要求がこれらのポッドに転送された場合、ポッドはNot Ready状態になります。

  • ポッドのシャットダウン処理中、Knative queue-proxyは引き続きポッドにリクエストを転送できます。 ポッドがシャットダウンする前にすべてのリクエストを処理できるように、timeoutSecondsパラメーターを最大タイムアウト期間の1.2倍に設定することを推奨します。 たとえば、リクエストの最大タイムアウト時間が10秒の場合、timeoutSecondsパラメーターを12秒に設定します。

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: helloworld-go
      namespace: default
    spec:
      template:
        spec:
          timeoutSeconds: 12

同時実行パラメーターの設定

同時実行パラメーターを設定して、Knative Servicesのパフォーマンスと応答速度を大幅に向上させることができます。 適切な同時実行設定により、アプリケーションは多数の同時リクエストをより効率的に処理できるようになり、サービス品質とユーザーエクスペリエンスがさらに向上します。

  • ハード同時実行制限: ハード同時実行制限は、強制された上限です。 同時実行レベルがハード制限に達すると、過剰なリクエストがキャッシュされます。 これらの要求は、十分なリソースがあるまで保留のままでなければなりません。

  • ソフト同時実行制限: ソフト同時実行制限は厳密な制約ではありません。 リクエストの数が急増すると、同時実行レベルがソフトリミットを超える可能性があります。

  • 利用ターゲット: targetと比較して、autoscaling.knative.de v/target-Utilization-percentageアノテーションは、同時実行レベルを指定するためのより直接的な方法です。 アノテーションを100% に近い値に設定して、同時リクエストを効率的に処理できます。

詳細については、「ソフト同時実行制限の設定」をご参照ください。

自動スケーリング

自動スケーリングを設定する前に、レイテンシの削減、コストの最小化、トラフィックの急増への対処などの目標を設定する必要があります。 次に、目的のシナリオでポッドを起動するのに必要な時間を見積もる必要があります。 例えば、単一のポッドを起動することと複数のポッドを同時に起動することとの間に時間差がある。 これらのメトリックは、オートスケーリングの基礎として使用できます。

パラメーターの詳細については、「トラフィック変動に耐える自動スケーリングの有効化」をご参照ください。

スケーリングモード

自動スケーリングは、安定モードとパニックモードの2つのモードで機能します。 各モードは、時間ベースのウィンドウ内で実行される。 安定したモードは、通常の操作に適しています。 デフォルトでは、パニックウィンドウは短くなります。 したがって、パニックモードは、トラフィックスパイクを処理するためのポッドをすばやく作成するのに適しています。

安定したウィンドウ

ポッドを期待どおりにスケーリングできるようにするには、安定ウィンドウを平均ポッド起動時間より長くする必要があります。 安定ウィンドウを平均時間の2倍に設定することを推奨します。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/window: "40s"

パニックウィンドウ

パニックウィンドウは、安定ウィンドウのパーセンテージとして定義されます。 パニックウィンドウは通常、予期しないトラフィックスパイクを処理します。

重要

不適切なパニックウィンドウは、ポッドの起動時間が長い場合、ポッドの数が過剰になる可能性があります。 作業は慎重に行ってください。

  • 安定ウィンドウが30秒であり、パニックウィンドウが10% である場合、システムは、3秒以内に収集された統計に基づいてパニックモードを開始するかどうかを決定する。 ポッドの起動に30秒かかる場合、システムは、新しく作成されたポッドがまだ起動しているときにポッドを展開し続けることができます。 その結果、過剰なポッドが生成される。

  • 他のパラメーターを変更する前にパニックウィンドウを変更せず、特にパニックウィンドウがポッドの起動時間以下の場合は、スケーリングアクティビティが期待どおりに実行されることを確認してください。 安定ウィンドウが平均ポッド起動時間の2倍の場合、パニックウィンドウを安定モードとパニックモードの境界として50% に設定します。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/panic-window-percentage: "20.0"

パニックモードしきい値は、サービス容量に対するインバウンドトラフィックの比率を定義します。 トラフィックのピーク値と許容できるレイテンシに基づいてしきい値を変更します。 安定モードが開始されるまでの初期値は200% 以上である。 アプリケーションが一定期間実行された後、しきい値を変更できます。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/panic-threshold-percentage: "150.0"

スケールレート

スケールアップ率とスケールダウン率を調整して、ポッドのスケーリングをより適切に制御できます。 デフォルトのスケールレートは、ほとんどのシナリオで要件を満たすことができます。 スケールレートを変更する前に、現在のステータスを確認し、ステージング環境で新しいスケールレートを変更してテストし、影響を評価します。 スケーリングの問題が発生した場合は、安定ウィンドウやパニックウィンドウなどの関連パラメーターを確認してください。

スケールアップ率

特定の問題を解決する必要がない限り、スケールアップ率を変更しないでください。 たとえば、新しく作成されたポッドがリソースを待つ必要があるため、ポッドの起動時間が長い場合は、スケールアップ率を変更できます。 スケーリングアクティビティが頻繁にトリガーされる場合は、安定ウィンドウやパニックウィンドウなどの他のパラメーターも変更する必要があります。

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-autoscaler
  namespace: knative-serving
data:
  max-scale-up-rate: "500.0"

スケールダウン率

スケールダウン率をポッドの平均起動時間以上に設定します。 デフォルトのスケールダウン率は、ほとんどのシナリオで要件を満たすことができます。 ただし、コストを削減したい場合は、スケールダウン率を上げて、トラフィック量が減少したときにポッドをすばやく削除できます。

スケールダウン率は比率です。 たとえば、N/2は、現在のスケーリングサイクルが終了すると、ポッドが現在の数の半分にスケーリングされることを意味します。 少数のポッドのみを実行するサービスの場合、特定の数のポッドを維持するためにスケールダウン率を下げることができます。 これによりシステムの安定性が向上し、頻繁なスケーリングが回避されます。

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-autoscaler
  namespace: knative-serving
data:
  max-scale-down-rate: "4.0"

スケールダウン遅延

スケールダウン遅延を設定して、新しいリクエストを受信したときにオートスケーラーがポッドを頻繁に作成しないようにすることができます。 これにより、ポッドがリクエストに遅れて応答する問題を解決できます。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/scale-down-delay: "2m" // Scale-down activities are performed with a delay of two minutes.

スケール境界

スケールの境界は、ビジネススケールとリソースの可用性に関連しています。

下限

autoscaling.knative.de v/min-scaleは、各リビジョンのレプリカの最小数を制御します。 Knativeは、レプリカの数を下限以上に保ちます。 アクセス頻度が低いが、常に使用できるようにする必要があるサービスの場合は、下限を1に設定して、少なくとも1つのレプリカを確保します。 トラフィックが急増する可能性のあるサービスの場合、下限を1より大きい値に設定します。 リクエストを受信していないときにレプリカをゼロにスケールする場合は、下限を0に設定します。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/min-scale: "0"

上限

autoscaling.knative.de v/max-scaleの値は、使用可能なリソースの量を超えてはなりません。 上限は、最大リソースコストを制限する。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/max-scale: "3"

初期スケール

トラフィックを新しいバージョンに分散できるように、初期スケールを現在のポッド数の1.2倍に設定します。

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/initial-scale: "3"

GPU共有

Knative Servicesは、Container Service for Kubernetes (ACK) のGPU共有機能を活用して、cGPUのGPUメモリ分離機能を最大限に活用し、GPUリソースの使用率を向上させることができます。

KnativeでGPUを共有するには、Knativeサービスのaliyun.com/gpu-mem制限を設定するだけで済みます。 例:

サンプルYAMLコンテンツの表示

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: helloworld-go
  namespace: default
spec:
  template:
    spec:
      containerConcurrency: 1
      containers:
      - image: registry-vpc.cn-hangzhou.aliyuncs.com/demo-test/test:helloworld-go
        name: user-container
        ports:
        - containerPort: 6666
          name: http1
          protocol: TCP
        resources:
          limits:
            aliyun.com/gpu-mem: "3"

プローブ

livenessプローブとreadinessプローブを設定して、Knative Servicesのヘルスステータスと可用性を監視できます。 Kubernetesプロービングポリシーと比較して、Knativeサービスはポッドのコールドスタート時間を最小限に抑えるために頻繁にプローブします。

  • Livenessプローブ: コンテナのヘルスステータスを監視するために使用されます。 コンテナーがFailed状態の場合、またはコンテナー内のサービスの起動に失敗した場合、livenessプローブはコンテナーを再起動します。

  • Readiness probes: アプリケーションの自動スケーリングを効率的に管理し、Ready状態のポッドのみがトラフィックを受信できるようにします。 これにより、サービスの安定性と応答速度が向上します。

    • すべてのコンポーネントがロードされ、コンテナの準備が整うまで、TCPプローブはリスニングポートを開きません。

    • HTTPプローブは、サービスのエンドポイントが要求を処理する準備ができるまで、サービスを準備完了としてマークしません。

    • periodSeconds (プロービング間隔) を小さな値に設定します。 ほとんどの場合、プローブ間隔はデフォルト値よりも短い10秒を指定します。

ポートプロービングとベストプラクティスの詳細については、「Configure port probing in Knative」をご参照ください。

スケールをゼロ

Knativeは、サービスがアイドル状態の場合、サービスのポッドをゼロにスケーリングできます。

複数のモデルを管理する必要がある場合は、各サービスのビジネスロジックを簡素化するために、モデルごとにKnativeサービスを作成することをお勧めします。

  • Knativeのスケールゼロ機能は、アイドルモデルがリソース料金を負担するのを防ぐことができます。

  • クライアントが初めてモデルにアクセスすると、Knativeはゼロからスケールアップを開始します。

ゼロスケールとベストプラクティスの詳細については、「Configure a reserved instance」をご参照ください。

カナリアリリース

Knativeは、新しいバージョンのリリース中にビジネスの継続性を確保できます。 コードを更新したり、サービスを変更したりすると、Knativeは新しいバージョンの準備ができるまで古いバージョンを実行し続けます。

新しいバージョンに配信されるトラフィックの割合を指定できます。 トラフィックの割合は重要なパラメータです。 Knativeが古いバージョンから新しいバージョンにトラフィックを切り替える時刻を決定します。 トラフィックの割合は、10% から100% の範囲で設定できます。 古いバージョンが不要になったら、パーセンテージを100% に設定します。 古いバージョンは、新しいバージョンの準備ができた直後に段階的に廃止されます。

限られた数のポッドでバッチ操作を実行する場合は、旧バージョンのスケールダウン速度を制限する必要があります。 たとえば、サービスは500のポッドを実行し、追加の300のポッドのみを使用できます。 トラフィックの割合を大きな値に設定すると、一部のサービス機能が利用できなくなることがあります。

カナリアリリースとベストプラクティスの詳細については、「Knative Serviceのトラフィック分割に基づくカナリアリリースの実行」をご参照ください。

ECSインスタンスとelasticコンテナインスタンスのコロケート

オフピーク時にはElastic Compute Service (ECS) インスタンスを使用し、ピーク時にはelasticコンテナインスタンスを使用するようにResourcePoliciesを設定できます。

  • スケールアッププロセス中、KnativeポッドはECSインスタンスにスケジュールされることが望ましいです。 ポッドの数が事前定義された上限を超えた場合、またはECSインスタンスが在庫切れの場合、新しいポッドはエラスティックコンテナインスタンスにスケジュールされます。

  • スケールダウンプロセス中に、弾性コンテナインスタンス上のポッドは削除されることが好ましい。

image

コロケーションとベストプラクティスの詳細については、「KnativeでのECSインスタンスとelastic containerインスタンスのColocate」をご参照ください。