モデルのトレーニング後、通常は推論サービスとしてデプロイします。推論ワークロードのトラフィックパターンは変動しやすく、固定の ECS ノードプールでは、オーバープロビジョニングなしでは突発的なバーストを効率よく処理できません。推論 Pod を Elastic Container Instance (ECI) にスケジューリングすると、Container Service for Kubernetes (ACK) はノードを管理することなく、需要に応じてキャパシティをスケールできます。
このトピックでは、BERT モデルを TensorFlow Serving の推論サービスとして ECI にデプロイし、1 秒あたりのクエリ数 (QPS) に基づいてスケールするように Horizontal Pod Autoscaler (HPA) を設定し、サービスをインターネットに公開する手順を説明します。
仕組み
次のコンポーネントが連携して Elastic Inference を実現します:
Client → Ingress (Internet-facing) → TF Serving pods (on ECI)
↑
HPA (scale-out/in)
↑
メトリクスアダプター ← SLS (nginx-ingress QPS)
-
トレーニング済みモデルを Object Storage Service (OSS) バケットにアップロードします。
-
PersistentVolume (PV) と PersistentVolumeClaim (PVC) を使用して、OSS バケットをクラスターにマウントします。
-
arenaを使用して推論サービスをデプロイし、新しい Pod を ECI に割り当てるためのアノテーションを設定します。 -
Simple Log Service (SLS) からの外部メトリクスを使用して HPA を設定し、QPS がしきい値を超えたときにスケールアウトをトリガーします。
-
外部クライアントがサービスにアクセスできるように、インターネット向け Ingress を作成します。
-
ストレステストを実行し、QPS に基づいて HPA が Pod をスケールアウトし、その後スケールインすることを確認します。
前提条件
開始する前に、次を満たしていることを確認してください:
-
デプロイ可能なトレーニング済みモデル。このトピックでは TensorFlow 1.15 でトレーニングした BERT モデルを使用します。
-
ACK クラスターに次のコンポーネントがインストールされていること: ack-virtual-node、ack-alibaba-cloud-metrics-adapter、arena。インストール手順については、「Manage components」をご参照ください。ack-virtual-node の詳細については、「Connection overview」をご参照ください。
手順 1:モデルの OSS へのアップロード
トレーニング済みモデルファイルを OSS バケットにアップロードします。手順については、「Upload objects」をご参照ください。
手順 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 # 上記の PV 名と一致する必要があります 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 バケット名。バケット名はグローバルに一意である必要があります。詳細については、「Bucket naming conventions」をご参照ください。 <your-oss-url>バケット内のオブジェクトにアクセスするための URL。詳細については、「Obtain the URL of a single object or the URLs of multiple objects」をご参照ください。 <your-access-key-id>OSS にアクセスするための AccessKey ID。最小権限の Resource Access Management (RAM) ユーザーを使用してください。詳細については、「Create an AccessKey pair」をご参照ください。 <your-access-key-secret>上記の AccessKey ID に対応する AccessKey Secret。 otherOptsフィールドでは、ossfs のカスタムマウントオプションを指定できます:-
-o max_stat_cache_size=0:メタデータキャッシュを無効化し、Pod が OSS から常に最新のオブジェクトメタデータを読み取るようにします。 -
-o allow_other:Pod 内で別のユーザーとして実行されるプロセスが、マウントされたバケットにアクセスできるようにします。
追加のマウントオプションについては、「Custom parameters supported by 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.xlarge次の 2 つのアノテーションで、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 を超えるとスケールアウトし、下回るとスケールインします。
-
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 は Service にクラスター IP アドレスのみを割り当てます。外部トラフィックを受け付けるには、インターネット向け Ingress を作成します。
-
ACK コンソールにログインし、左側のナビゲーションペインで[クラスター]をクリックします。
-
対象のクラスター名をクリックします。左側のナビゲーションペインで、[ネットワーク] > [イングレス] を選択します。
-
[Namespace] ドロップダウンリストから、推論サービスが存在する名前空間を選択し、[Ingress の作成] をクリックします。 次のパラメーターを設定します。 詳細については、「NGINX Ingress を作成する」をご参照ください。
パラメーター 値の例 [Name] bert-tfserving[Domain name] test.example.com(独自ドメインを使用)[Path] /[Rule] ImplementationSpecific(デフォルト)[Service name] bert-tfserving-202207181536-tensorflow-serving[Port] 8501 -
[Ingresses] ページで、作成した Ingress を見つけ、[ルール] 列でそのアドレスを控えます。
手順 6:ストレステストによる弾性スケーリングの検証
手順 5 で確認した Ingress アドレスを使用して、推論サービスに負荷をかけます。
-
QPS が
averageValue(この例では 10) を超えると、HPA がスケールアウトをトリガーし、新しい Pod が ECI にスケジューリングされます。Pod の総数はmaxReplicas(10) の範囲内に維持されます。 -
QPS が
averageValueを下回ると、HPA がスケールインをトリガーします。