🫠

SageMaker非同期推論エンドポイントのAutoScaling設定で詰まった話

2024/06/02に公開

SageMaker非同期推論エンドポイントは

  • 使用しないときはインスタンス数0にすることができるのでコストを節約できる
  • リクエスト数に応じたAutoScalingができる
  • GPUが使用できる

等の多くのメリットがありますが、これのターゲット追跡スケーリングポリシーを設定した際に

  1. 「0→1」のスケールアウトが実行されない
  2. 「1→N」のスケールアウトが実行されない

の2点で詰まって時間を溶かしてしまったので、解決策について備忘録として残します。

1. 「0→1」のスケールアウトが実行されない

最初は「ApproximateBacklogSizePerInstance」が180になるようなターゲット追跡スケーリングポリシーを設定していたのですが、数件リクエストを送っても「0→1」のスケールアウトが実行されませんでした。
公式ドキュメントによると

散発的なリクエストやリクエスト数が少ない期間があるユースケースがあるかもしれません。この期間中にエンドポイントのインスタンスがゼロインスタンスにスケールダウンされた場合、キュー内のリクエスト数がスケーリングポリシーで指定された目標を超えるまで、エンドポイントは再びスケールアップされません。その結果、キュー内のリクエストの待ち時間が長くなる可能性があります。

とあったため、以下の2つのコードを実行してステップスケーリングポリシーと CloudWatch アラームを設定することで「0→1」のスケーリングが行われるようになりました。

ステップスケーリングポリシーの設定

response = client.put_scaling_policy(
    PolicyName="HasBacklogWithoutCapacity-ScalingPolicy",
    ServiceNamespace="sagemaker",  # The namespace of the service that provides the resource.
    ResourceId=resource_id,  # Endpoint name
    ScalableDimension="sagemaker:variant:DesiredInstanceCount",  # SageMaker supports only Instance Count
    PolicyType="StepScaling",  # 'StepScaling' or 'TargetTrackingScaling'
    StepScalingPolicyConfiguration={
        "AdjustmentType": "ChangeInCapacity", # Specifies whether the ScalingAdjustment value in the StepAdjustment property is an absolute number or a percentage of the current capacity. 
        "MetricAggregationType": "Average", # The aggregation type for the CloudWatch metrics.
        "Cooldown": 300, # The amount of time, in seconds, to wait for a previous scaling activity to take effect. 
        "StepAdjustments": # A set of adjustments that enable you to scale based on the size of the alarm breach.
        [ 
            {
              "MetricIntervalLowerBound": 0,
              "ScalingAdjustment": 1
            }
          ]
    },    
)

CloudWatch アラームの作成

response = cw_client.put_metric_alarm(
    AlarmName=step_scaling_policy_alarm_name,
    MetricName='HasBacklogWithoutCapacity',
    Namespace='AWS/SageMaker',
    Statistic='Average',
    EvaluationPeriods= 2,
    DatapointsToAlarm= 2,
    Threshold= 1,
    ComparisonOperator='GreaterThanOrEqualToThreshold',
    TreatMissingData='missing',
    Dimensions=[
        { 'Name':'EndpointName', 'Value':endpoint_name },
    ],
    Period= 60,
    AlarmActions=[step_scaling_policy_arn]
)

2. 「1→N」のスケールアウトが実行されない

以下のように最小キャパシティ0, 最大キャパシティ20に設定し、「ApproximateBacklogSizePerInstance」を実験用に1に設定して100件ほどリクエストを送ったところ、ステップスケーリングポリシーによって「0→1」にスケールアウトした後、1台のままでそれ以上スケールアウトが実行されませんでした。

response = autoscaling_client.register_scalable_target(
    ServiceNamespace='sagemaker', 
    ResourceId=resource_id,
    ScalableDimension='sagemaker:variant:DesiredInstanceCount',
    MinCapacity=0,
    MaxCapacity=20,
)

boto3のdescribe_scaling_activitiesを使ってログを調べてみると、

Failed to set desired instance count to 20. Reason: The account-level service limit 'ml.g4dn.xlarge for endpoint usage' is 4 Instances, with current utilization of 1 Instances and a request delta of 19 Instances. Please use AWS Service Quotas to request an increase for this quota. If AWS Service Quotas is not available, contact AWS support to request an increase for this quota.

とありました。私が使用していた「ml.g4dn.xlarge」のエンドポイントはデフォルトのクォータが4であり、それを超える最大キャパシティを設定してしまうとスケールアウト時に怒られて全くスケールアウトしないみたいです。

まとめ

  • ターゲット追跡スケーリングポリシーで「0→1」のスケーリングが実行されないときはステップスケーリングポリシーを追加する
  • クォータを超える最大キャパシティを設定してはいけない

特に2についてはCloudWatch アラームのログを見ても詳しい原因が分からなかったため非常に苦戦しました...
この記事が一助になれば幸いです!

Discussion