Amazon Web Services ブログ

カスタムメトリクスに基づいた Application Auto Scaling による Amazon ECS サービスのオートスケール

この記事は Autoscaling Amazon ECS services based on custom metrics with Application Auto Scaling (記事公開日: 2023 年 3 月 14 日) の翻訳記事です。

Introduction

Application Auto Scaling は、Amazon Elastic Container Service (Amazon ECS) サービス、Amazon DynamoDB テーブル、AWS Lambda のプロビジョニングされた同時実行などのスケーラブルな AWS サービスに向けた、リソースを自動的にスケーリングするソリューションを必要とする開発者やシステム管理者向けのウェブサービスです。Application Auto Scaling では、Amazon CloudWatch のカスタムメトリクスに基づくスケーリングポリシーを使用して、このようなリソースをスケーリングできるようになりました。これらのメトリクスは、メトリクスの数学式に照らして評価されます。この記事では、この機能がどのように機能するかを、サンプルシナリオを使ってデモします。このシナリオでは、サービスが処理する HTTP リクエストの平均レートに基づいて、Amazon ECS サービスをスケーリングします。

背景

水平スケーラビリティは、クラウドネイティブアプリケーションの重要な側面です。Application Auto Scaling は複数の AWS サービスと統合されているため、アプリケーションの需要に合わせてスケーリング機能を追加できます。Amazon CloudWatch で利用できる事前定義済みの関連するメトリクスを 1 つ以上と、ターゲット追跡スケーリングポリシーまたはステップスケーリングポリシーと組み合わせて使用することで、特定のサービスのリソースに比例してスケーリングできます。このような事前定義されたメトリクスだけでは、スケーリングアクションをいつどの程度実行すべきかを示す信頼できる指標にならないユースケースがいくつかあります。特定のシナリオでは、受信した HTTP リクエストの数、キュー/トピックから取得されたメッセージの数、実行されたデータベーストランザクションの数など、アプリケーションの他の側面を追跡するカスタムメトリクスの方が、スケーリングアクションのトリガーに適している場合があります。

Application Auto Scaling でターゲット追跡スケーリングポリシーを使用する際の重要な考慮事項として、指定されたメトリクスが、スケールするターゲットがどの程度ビジーであるかを示す平均使用率で表現される必要があるということです。アプリケーションが受信した HTTP リクエストの数、メッセージブローカーのキュー / トピックから取得されたメッセージの数などのメトリクスは本質的に累積的であり、単調に増加するためこの要件を満たしません。それらは、スケーラブルなターゲットの容量に比例して増減する使用率指標に変換する必要があります。以前は、お客様はこの変換を実行する独自のコードを作成する必要がありました。この記事では、このようなユースケースの代表的な例を紹介し、Amazon Managed Streaming for Apache Kafka (Amazon MSK) のトピックに公開されるメッセージのレートに基づいて Amazon ECS サービスのタスク数をスケーリングする方法について詳しく説明しています。Amazon CloudWatch から定期的にカスタムメトリクスデータを取得し、平均使用率のメトリクスを計算し、後者を Amazon CloudWatch に新しいカスタムメトリクスとして公開する AWS Lambda 関数を採用しています。その後、事前に計算されたこの新しい使用率メトリクスを参照する CustomizedMetricSpecification を使用してターゲット追跡ポリシーが定義されます。

この新機能により、お客様は CustomizedMetricSpecification 内で Metrics Math をインラインで使用して、1 つ以上の Amazon CloudWatch メトリクスを使用してそのような平均使用率メトリクスを計算する方法を定義できます。それ以外はすべてApplication Auto Scaling によって処理されます。これにより、お客様がこのタスクを実行するコードを作成したり、このコードを実行するためのコンピューティングインフラストラクチャをデプロイしたりする必要がなくなります。これらの追加タスクは、単に運用上のオーバーヘッドとメンテナンスコストを増大させるだけで、アプリケーションの差別化にはつながりませんでした。では、この新機能の仕組みを詳しく見ていきましょう。

ソリューションの概要

Amazon ECS クラスターにデプロイされたサンプルワークロードを使用して、新機能がどのように機能するかを示します。以下の図 (Figure 1) は、このデモに使用した構成を示しています。これは、Amazon Aurora PostgreSQL データベースのインスタンスと直接通信するバックエンドデータストアサービスが、他のマイクロサービスがデータベースの作成、読み取り、更新、削除 (CRUD) 操作を実行できるようにする一連の REST API を公開するマイクロサービスアーキテクチャの代表的なものです。

このアプリケーションには Prometheus クライアントライブラリが組み込まれており、http_requests_total という名前の Prometheus カウンタを使用して、サービスに送信された HTTP リクエストの数を追跡します。Amazon ECS クラスターから Prometheus メトリクスを収集するには、Prometheus メトリクスコレクションを持つ CloudWatch エージェントを使用するか、AWS Distro for OpenTelemetry コレクターを使用できます。このデモでは CloudWatch エージェントを使用します。カスタムメトリクスはエージェントによって CloudWatch 名前空間  ECS/ContainerInsights/Prometheus に公開されます。目標は、実行中のタスクによって処理される HTTP リクエストの平均レートに比例してデータストアサービスを自動スケーリングすることです。バックエンドサービスはロードバランサーに登録されていないため、Elastic Load Balancing が CloudWatch に公開したメトリクスは、サービスの負荷を示す信頼できる指標としては使用できないことに注意してください。

ウォークスルー

セットアップの最初のステップは、ターゲットリソースのスケーラブルディメンションを登録することです。これに基づいてスケーリングアクションが実行されます。この場合は、サービス内のタスクの DesiredCount です。

CLUSTER_NAME=ecs-ec2-cluster
SERVICE_NAME=BackendService
aws application-autoscaling register-scalable-target \
--service-namespace ecs \
--scalable-dimension ecs:service:DesiredCount \
--resource-id service/$CLUSTER_NAME/$SERVICE_NAME \
--min-capacity 2 \
--max-capacity 10

次に、Application Auto Scaling API を使用してターゲット追跡スケーリングポリシーを設定します。ターゲット追跡スケーリングポリシーで使用されるカスタムメトリクスは、次のコードに示すように、ポリシー設定 JSON ファイルの CustomizedMetricSpecification フィールドを使用して定義されます。

{
    "TargetValue":5.0,
    "ScaleOutCooldown":120,
    "ScaleInCooldown":120,
    "CustomizedMetricSpecification":{
        "MetricName":"http_request_rate_average_1m",
        "Namespace":"ECS/CloudWatch/Custom",
        "Dimensions":[
           {
              "Name":"ClusterName",
              "Value":"ecs-ec2-cluster"
           },
           {
              "Name":"TaskGroup",
              "Value":"service:BackendService"
             }
        ],
        "Statistic":"Average"
     }
 }

以前は、JSON ファイルの MetricName フィールドで指定するカスタムメトリクスは事前に計算され、CloudWatch ですぐに利用できる使用率のメトリクスである必要がありました。この新機能により、CustomizedMetricSpecification フィールドのスキーマが拡張され、Metrics フィールドを使用するメトリクス数式を含めることができるようになりました。Metric Mathを使用すると、複数の CloudWatch メトリクスをクエリし、複数の関数と演算子を使用して、これらのメトリクスに基づいて新しい時系列を作成できます。これにより、お客様はポリシー設定 JSON ファイルに以下の例に示すような数式を指定するだけで、カスタムの使用率指標を動的に作成できます。なお、このスキーマは、ピリオドフィールドという 1 つの例外を除いて、CloudWatch API の GetMetricDataMetricDataQuery パラメータで使用されるものとまったく同じであることに注意してください。Application Auto Scaling は内部でこれを 60 秒という定義済みの値に設定していますが、カスタムメトリクスの仕様で明示的に定義することはできません。次の例では、数学式は他の 2 つの CloudWatch メトリクスに基づいて http_request_rate_average_1m という名前のメトリクスを計算します。1 つ目の http_requests_total は、上で説明した Prometheus のカスタムメトリクスです。2 つ目のメトリクス RunningTaskCount は Amazon ECS Container Insights によって自動的に収集され、ECS/ContainerInsights という名前空間に公開されます。ここに記載されているように、Amazon ECS クラスターの Container Insights が有効になっていることを確認する必要があります。計算されたメトリクスは、過去 1 分間に実行中のタスクによって処理された HTTP リクエストの 1 秒あたりの平均レートです。現在、この使用率指標を使用して、TargetValue フィールドを使用して 1 秒あたり 5 リクエストという目標しきい値を設定することで、サービスの自動スケーリングを行っています。

{
   "TargetValue":5.0,
   "ScaleOutCooldown":120,
   "ScaleInCooldown":120,
   "CustomizedMetricSpecification":{
      "Metrics":[
         {
            "Id":"m1",
            "Label":"sum_http_requests_total_1m",
            "ReturnData":false,
            "MetricStat":{
               "Metric":{
                  "Namespace":"ECS/ContainerInsights/Prometheus",
                  "MetricName":"http_requests_total",
                  "Dimensions":[
                     {
                        "Name":"ClusterName",
                        "Value":"ecs-ec2-cluster"
                     },
                     {
                        "Name":"TaskGroup",
                        "Value":"service:BackendService"
                     }
                  ]
               },
               "Stat":"Sum"
            }
         },
         {
            "Id":"m2",
            "Label":"running_task_count_average_1m",
            "ReturnData":false,
            "MetricStat":{
               "Metric":{
                  "Namespace":"ECS/ContainerInsights",
                  "MetricName":"RunningTaskCount",
                  "Dimensions":[
                     {
                        "Name":"ClusterName",
                        "Value":"ecs-ec2-cluster"
                     },
                     {
                        "Name":"ServiceName",
                        "Value":"BackendService"
                     }
                  ]
               },
               "Stat":"Average"
            }
         },
         {
            "Id":"m3",
            "Expression":"m1/(m2*60)",
            "Label":"http_request_rate_average_1m",
            "ReturnData":true
         }
      ]
   }
}

ターゲット追跡スケーリングポリシーは、上記のポリシー設定 JSON ファイルと以下の CLI コマンドを使用して作成されます。ターゲットの追跡スケーリングポリシーを作成すると、Application Auto Scaling は 2 つのメトリクスアラーム (Figure 2) を作成します。1 つはスケールアウトアクション (ハイアラーム) をトリガーし、もう 1 つはスケールインアクション (ロウアラーム) をトリガーします。

CLUSTER_NAME=ecs-ec2-cluster
SERVICE_NAME=BackendService
POLICY_NAME=HTTP-Request-Rate-Policy
aws application-autoscaling put-scaling-policy \
--policy-name $POLICY_NAME \
--service-namespace ecs \
--resource-id service/$CLUSTER_NAME/$SERVICE_NAME \
--scalable-dimension ecs:service:DesiredCount \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration file://policy.json

Amazon ECS によるオートスケーリングの実行

Locust をロードジェネレーターとして使用し、このワークロードには絶え間なくリクエストが送信されます。このバックエンドサービスはロードバランサーに登録されていないため、テストを容易にするために、サービスは AWS Cloud Map のサービスレジストリに登録されます。これにより、ロードジェネレータはサービスの DNS ホスト名を使用してトラフィックを基盤となるタスクに転送できます。テスト期間中の負荷プロファイルを以下に示します (Figure 3)。まず、1 秒あたり約 9 リクエストの初期ロードから始めます。スケールアウトアクションをトリガーする期間が経過すると、負荷は 2 倍になり、最終的にスケールインアクションがトリガーされるまで約 4 リクエスト/秒に減少します。

図 4 (Figure 4) は、自動スケーリングアクションの実行基準となるターゲット使用率指標 http_request_rate_average_1m のプロファイルを示しています。図 5 (Figure 5) は、スケールアウト前、スケールアウト後、およびスケールイン後のサービスで実行中のタスクの数を示しています。2 つの実行中のタスクから始めて、サービスの初期負荷では、目標メトリクスは 1 タスクあたり約 4 リクエスト / 秒に維持されます。これは、設定されている上限しきい値である 5 をはるかに下回っています。負荷が 2 倍になると、メトリクスはこの上限しきい値を超え、約 3 分(ハイアラームの評価期間)後に、ハイアラームによってトリガーされるスケールアウトアクションが発生します。ターゲットを追跡すると、それに比例してタスク数が 4 に増え、ターゲットメトリクスが上限値を下回ります。その後、4 つのタスクを実行した状態で負荷が 4 リクエスト/秒に減少すると、目標メトリクスはタスクあたり約 1 リクエスト/秒/タスクに低下し、下限のしきい値を超えます。約 15 分が経過すると (つまり、ロウアラームの評価期間)、スケールインアクションが発生します。スケールインアクションは、ロウアラームがトリガーされ、タスクの数が 2 に戻ります。

まとめ

この記事では、Application Auto Scaling のターゲット追跡に Metrics Math のサポートを使用して Amazon ECS サービスを自動スケーリングする方法を説明しました。この機能は現在一般公開されており、AWS CLI または AWS SDK で使用できます。以前は、お客様が Application Auto Scaling を使用して特定の AWS サービスのリソースを自動スケーリングする必要がある場合、CloudWatch で利用できる定義済みのメトリクスのセットを使用することに限定されていました。他のカスタムアプリケーションメトリクスを使用するには、使用率メトリクスを事前に計算して Amazon CloudWatch で利用できるようにするタスクを実行する独自のコードを作成する必要がありました。この新機能により、このようなコードを管理する必要がなくなり、ターゲットアプリケーションに差異が生じることはありません。これにより、Amazon ECS サービスや AWS Lambda などの AWS サービスのスケーラブルリソースをカスタムメトリクスに基づいて自動スケーリングするタスクが大幅に簡略化されます。Amazonではお客様からのフィードバックを大変大切にしていますので、この新機能がどのように役立っているかをお知らせください。

翻訳はソリューションアーキテクトの加治が担当しました。原文はこちらです。