モデルをトレーニングした後、通常はそれを推論サービスとしてデプロイします。推論ワークロードには可変のトラフィックパターンがあり、固定された Elastic Compute Service (ECS) ノードのプールでは、過剰なプロビジョニングなしに急なバーストを効率的に処理できません。Elastic Container Instance (ECI) に推論 Pod をスケジューリングすることで、Container Service for Kubernetes (ACK) はノードを管理することなく、オンデマンドでキャパシティをスケーリングします。
このトピックでは、BERT モデルを TensorFlow Serving 推論サービスとして ECI にデプロイし、Horizontal Pod Autoscaler (HPA) を設定して秒間クエリ数 (QPS) に基づいてスケーリングし、インターネット経由でサービスを公開する方法について説明します。
仕組み
以下のコンポーネントが連携して弾力的推論を実現します。
Client → Ingress (Internet-facing) → TF Serving pods (on ECI)
↑
HPA (scale-out/in)
↑
Metrics Adapter ← SLS (nginx-ingress QPS)
-
トレーニング済みモデルを Object Storage Service (OSS) バケットにアップロードします。
-
永続ボリューム (PV) と永続ボリューム要求 (PVC) を使用して、OSS バケットをクラスターにマウントします。
-
arenaを使用して推論サービスをデプロイします。この際、新しい Pod を ECI に誘導するアノテーションを使用します。 -
Simple Log Service (SLS) から取得した外部メトリックで HPA を設定し、QPS がしきい値を超過したときにスケールアウトをトリガーします。
-
外部クライアントがサービスに到達できるように、インターネットに面した Ingress を作成します。
-
ストレステストを実行して、HPA が QPS に基づいて Pod をスケールアウトおよびスケールインすることを検証します。
前提条件
開始する前に、以下があることを確認してください。
-
デプロイする準備ができたトレーニング済みモデル。このトピックでは、TensorFlow 1.15 でトレーニングされた BERT モデルを使用します。
-
以下のコンポーネントが ACK クラスターにインストールされている必要があります。ack-virtual-node、ack-alibaba-cloud-metrics-adapter、およびarenaです。インストール手順については、「コンポーネントの管理」をご参照ください。ack-virtual-node について詳しくは、「接続の概要」をご参照ください。
ステップ 1: モデルを OSS にアップロード
トレーニング済みモデルファイルを OSS バケットにアップロードします。手順については、「オブジェクトのアップロード」をご参照ください。
ステップ 2: PV と PVC を使用してモデルをマウント
ご利用の OSS バケットにマッピングされる PV と、推論 Pod がマウントする PVC を作成します。
-
pvc.yamlという名前のファイルを次の内容で作成します。apiVersion: v1 kind: PersistentVolume metadata: name: model-csi-pv spec: capacity: storage: 5Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain csi: driver: ossplugin.csi.alibabacloud.com volumeHandle: model-csi-pv # Must match the PV name above volumeAttributes: bucket: "<your-bucket-name>" url: "<your-oss-url>" akId: "<your-access-key-id>" akSecret: "<your-access-key-secret>" otherOpts: "-o max_stat_cache_size=0 -o allow_other" --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: model-pvc spec: accessModes: - ReadWriteMany volumeName: model-csi-pv storageClassName: "" resources: requests: storage: 5Giプレースホルダーを置き換えます。
プレースホルダー 説明 <your-bucket-name>OSS バケットの名前です。バケット名はグローバルに一意です。詳細については、「バケットの命名規則」をご参照ください。 <your-oss-url>バケット内のオブジェクトにアクセスする際に使用する URL です。詳細については、「単一オブジェクトまたは複数オブジェクトの URL を取得する」をご参照ください。 <your-access-key-id>OSS へのアクセスに使用する AccessKey ID です。最小権限の原則に基づき、Resource Access Management (RAM) ユーザーの AccessKey ペアを使用してください。詳細については、「AccessKey ペアを作成する」をご参照ください。 <your-access-key-secret>上記の AccessKey ID に対応する AccessKey Secret です。 otherOptsフィールドは、ossfs のカスタムマウントオプションを受け入れます。-
-o max_stat_cache_size=0— メタデータキャッシュを無効にし、Pod が常に OSS から最新のオブジェクトメタデータを読み取るようにします。 -
-o allow_other— Pod 内で他のユーザーとして実行されているプロセスがマウントされたバケットにアクセスできるようにします。
追加のマウントオプションについては、「ossfs でサポートされているカスタムパラメーター」をご参照ください。
-
-
マニフェストを適用します。
kubectl apply -f pvc.yaml
ステップ 3: 推論サービスをデプロイ
arena を使用して TensorFlow Serving 推論サービスをデプロイします。--annotation フラグは、Pod が ECS ノードまたは ECI のどちらに配置されるかを制御します。
-
次のコマンドを実行します。
arena serve tensorflow \ --namespace=default \ --name=bert-tfserving \ --model-name=chnsenticorp \ --gpus=1 \ --image=tensorflow/serving:1.15.0-gpu \ --data=model-pvc:/data \ --model-path=/data/models/tensorflow/chnsenticorp \ --version-policy=specific:1623831335 \ --annotation=alibabacloud.com/burst-resource=eci_only \ --annotation=k8s.aliyun.com/eci-use-specs=ecs.gn6i-c4g1.xlarge2 つのアノテーションが ECI スケジューリングを制御します。
アノテーション 説明 alibabacloud.com/burst-resourcePod がどこにスケジューリングされるかを制御します。空白のままにすると ECS のみを使用します (デフォルト)。 eciに設定すると、ECS キャパシティが不足している場合に ECI を使用します。eci_onlyに設定すると、ECI のみを使用します。k8s.aliyun.com/eci-use-specsGPU アクセラレーションされた ECI インスタンスタイプを指定します。ECI GPU リソースを使用する場合に必須です。 -
サービスが実行中であることを確認します。
arena serve list期待される出力:
NAME TYPE VERSION DESIRED AVAILABLE ADDRESS PORTS GPU bert-tfserving Tensorflow 202207181536 1 1 172.16.52.170 GRPC:8500,RESTFUL:8501 1 -
Pod が ECI で実行中であることを確認します。
kubectl get pods -o wide期待される出力:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES bert-tfserving-202207181536-tensorflow-serving-547797c546-djh58 1/1 Running 0 114s 192.168.0.246 virtual-kubelet-cn-beijing-h <none> <none>NODE値virtual-kubelet-cn-beijing-hは、Pod が ECS ノードではなく ECI インスタンス上で実行中であることを確認します。
ステップ 4: QPS ベースのスケーリングのために HPA を設定
HPA は、SLS からの sls_ingress_qps メトリックに基づいて推論 Pod の数を自動的に調整します。QPS が averageValue を超過するとスケールアウトがトリガーされ、QPS がそれを下回るとスケールインがトリガーされます。
-
arenaによって作成された Deployment と Service の名前を確認します。kubectl get deployment期待される出力:
NAME READY UP-TO-DATE AVAILABLE AGE bert-tfserving-202207181536-tensorflow-serving 1/1 1 1 2m18skubectl get service期待される出力:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE bert-tfserving-202207181536-tensorflow-serving ClusterIP 172.16.52.170 <none> 8500/TCP,8501/TCP 2m45s -
bert-tfserving-eci-hpa.yamlという名前のファイルを次の内容で作成します。パラメーター 説明 scaleTargetRefスケーリングする Deployment — ステップ 3 で作成された推論サービス Deployment です。 minReplicasPod の最小数。 maxReplicasPod の最大数。 sls.projectご利用のクラスターの SLS プロジェクト名。形式は k8s-log-{cluster id}です。{cluster id}を実際のクラスター ID に置き換えます。sls.logstoreSLS Logstore 名。デフォルトは nginx-ingressです。sls.ingress.route監視する Ingress ルートを識別します。形式は {namespace}-{service name}-{service port}です。averageValueスケールアウトをトリガーする Pod あたりの QPS しきい値。この例では 10に設定します。apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: bert-tfserving-eci-hpa namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: bert-tfserving-202207181536-tensorflow-serving minReplicas: 1 maxReplicas: 10 metrics: - type: External external: metric: name: sls_ingress_qps selector: matchLabels: sls.project: "k8s-log-{cluster id}" sls.logstore: "nginx-ingress" sls.ingress.route: "default-bert-tfserving-202207181536-tensorflow-serving-8501" target: type: AverageValue averageValue: "10"主要なパラメーター:
-
HPA マニフェストを適用します。
kubectl apply -f bert-tfserving-eci-hpa.yaml -
HPA がアクティブであることを確認します。
kubectl get hpa期待される出力:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE bert-tfserving-eci-hpa Deployment/bert-tfserving-202207181536-tensorflow-serving 0/10 (avg) 1 10 1 116s
ステップ 5: インターネット経由でサービスを公開
デフォルトでは、arena serve tensorflow はサービスにクラスター IP アドレスのみを割り当てます。外部トラフィックを受け入れるには、インターネットに面した Ingress を作成します。
-
「ACK コンソール」にログインし、左側のナビゲーションウィンドウで[クラスター]をクリックします。
-
対象のクラスター名をクリックします。左側のナビゲーションウィンドウで、ネットワーク > Ingress を選択します。
-
[名前空間] ドロップダウンリストから、推論サービスが存在する名前空間を選択し、[Ingress の作成] をクリックします。 次のパラメーターを設定します。 詳細については、「NGINX Ingress を作成する」をご参照ください。
パラメーター 例 名前 bert-tfservingドメイン名 test.example.com(独自のドメインを使用)パス /ルール ImplementationSpecific(デフォルト)サービス名 bert-tfserving-202207181536-tensorflow-servingポート 8501 -
[Ingresses]ページで、作成した Ingress を見つけ、[Rules]列のアドレスを確認します。
ステップ 6: ストレステストで弾力的スケーリングを検証
ステップ 5 の Ingress アドレスを使用して、推論サービスに負荷を送信します。
-
QPS が
averageValue(この例では 10)を超えると、HPA がスケールアウトをトリガーし、新しい Pod が ECI 上にスケジュールされます。Pod の合計数はmaxReplicas(10)以内に保たれます。 -
QPS が
averageValueを下回ると、HPA がスケールインをトリガーします。