Amazon Web Services ブログ

詳解: Amazon Elastic Container Service と AWS Fargate のタスク起動レートの向上

この記事は Under the hood: Amazon Elastic Container Service and AWS Fargate increase task launch rates を翻訳したものです。

2015 年以降、数十万人の開発者がクラスター管理のオーケストレーションサービスとして Amazon Elastic Container Service (Amazon ECS) を選択しています。開発者はミッションクリティカルなアプリケーションのライフサイクルを、最初のデプロイから新バージョンのコードのロールアウト、トラフィックレベルの変化に対応した自動スケーリングまで Amazon ECS に託しています。

これらの長期間実行を前提とするアプリケーションのタスクと並んで、Amazon ECS はスタンドアロンのタスクの起動にも使用されます。スタンドアロンのタスクは、スケジュール実行やイベントトリガーで実行されるコンピューティングジョブです。また、キューに格納された作業に応じて実行される AWS Batch のジョブである場合もあります。Amazon EC2、AWS Fargate、および Amazon ECS Anywhere で管理されるオンプレミスハードウェア全体で、Amazon ECS は毎秒数千ものアプリケーションのタスクとバッチのタスクを起動します。過去 1 年間で、AWS は Amazon ECS を利用されるお客様のタスクの起動レートを引き上げてきました。タスクの起動レートの引き上げにより、デプロイ、スケール、バッチワークロードの高速化が可能になります。

この記事では、Amazon ECS の仕組みや、タスク起動レートとは何か、タスク起動レートの向上がなぜ重要なのかについて、その裏側を紹介します。

Amazon ECS の機能

開発者が Amazon ECS を選択する理由として、インフラストラクチャよりもアプリケーションの構築に集中して迅速に行動できるという点があります。Amazon ECS は、管理されたコントロールプレーンとシンプルさを重視したエクスペリエンスを提供します。開発チームはインフラストラクチャの管理やアップグレード、インフラストラクチャ自体への理解に時間を費やすことから解放されます。Amazon ECS はセキュアなマルチテナントコントロールプレーンとしてゼロから設計されています。傍から見ると Amazon ECS の使用はフルマネージドのサーバーレス API を呼び出すのと同じくらい簡単です。この API は、いくつかのコアコンポーネントで構成されるコントロールプレーンのフロントエンドとなっています。

  • ECS エージェントとの通信: Amazon ECS エージェントは、Fargate の実行基盤、Amazon EC2 インスタンス、またはお客様のオンプレミスサーバー上で実行されます。エージェントはタスクの実行を可能にするために必要な CPU、メモリ、GPU のキャパシティを Amazon ECS のコントロールプレーンに報告します。また、コントロールプレーンはこれらのエージェントと対話して、アプリケーションのタスクを起動するように指示します。さらに、予期しないエージェントからの切断や、Amazon EC2 インスタンスからホストがシャットダウンされたことを示す終了通知がないかなど、これらのエージェントを監視します。
  • タスク監視: タスクのライフサイクルとヘルスチェックを監視し、アプリケーションのタスクのクラッシュ、フリーズ、OS の OOM reaper による強制終了など、予期しない状態の変化がないかを確認します。
  • API: 開発者や運用エンジニアが Amazon ECS に対して、彼らが意図する設定を反映する方法です。この API は様々なシナリオで宣言的な構成を受け入れます。例えば「このコンテナをスタンドアロンのタスクとして完了まで実行する」「このアプリケーションコンテナのコピーをサービスとして 10 個実行し、実行を持続する」「このサービスにはすでにアプリケーションのコピーが 10 個あるが、ダウンタイム無しのローリングデプロイで、トラフィックを落とさずにアプリケーションコンテナを新しいバージョンに更新する」などのシナリオです。開発者は自分のデプロイスクリプトから直接、または AWS マネジメントコンソール、AWS CLI、AWS CloudFormation、または AWS Copilot などの高レイヤーの Amazon ECS ツールを使用して、間接的に Amazon ECS の API を操作します。
  • タスクスケジューリング: お客様の宣言的な構成を実現するための、プランを作成して実行するエンジンです。開発者が宣言型の構成を提供すると、スケジューラはその設定を取得し、アプリケーションコンテナを実行するキャパシティを見つける責任を負います。さらに、タスクが予期せずクラッシュした場合など、Amazon ECS に管理されたサービスの実際の状態が、タスクモニタリングによってお客様のプランと異なるということが示された場合、スケジューラはこれを修正するプランを立てます。お客様の意図が変わり、お客様が新しいバージョンのアプリケーションのロールアウトを要求したり、アプリケーションのスケールインまたはスケールアウトを要求した場合は、スケジューラはお客様の新しい意図を実現するためのプランを立てます。

タスクのスケジューリングは Amazon ECS の機能の中核をなすものです。このスケジューリングの機能は非常に複雑で、多数のインスタンスとタスクを追跡する必要があり、リソースを大量に消費する可能性があります。EC2 インスタンスにはさまざまなサイズがあり、複数のサイズのタスクが実行される場合があります。スケジューラは複数サービスの起動のために、同じインスタンス上で並行してタスクを起動することが多々あります。そのため、負荷の高いホスト上で 2 つのタスクがリソースを奪い合うような競合を避けながら、タスクをスケジューリングしなければなりません。このような複雑さを Amazon ECS は全て内部で処理しています。開発者は、タスクスケジューラに達成させたい目標をいくつか指定するだけで、残りは Amazon ECS のコントロールプレーンが行ってくれます。

タスクスケジューリングが興味深い要因の1つは、タスクのスケジューリングの複雑さがワークロードに大きく依存する点です。ある開発者は、1 つのタスクで 1 つのコンテナを実行する小さなアプリケーションをデプロイしています。ある開発者は、数百台のマシンで構成されるオンプレミスのサーバーファームを所有していたり、クラウド上で EC2 インスタンスや AWS Fargate 上でタスクが実行される数万のアプリケーションコンテナを持つ巨大なデプロイメントを所有しています。ある開発者は、デプロイ頻度が低くサービスのサイズがそれほど変わりません。ある開発者は、1 日に何回もデプロイし、オートスケーリングを使用して 1 日を通してサービスのサイズを調整します。

Amazon ECS を使用する場合、ユースケースの規模や複雑さにかかわらず、ワークロードのスケジューリングに料金はかかりません。開発者は、アプリケーションのタスクを実行するコンピューティングキャパシティに対してのみ料金を支払うだけです。そのキャパシティへアプリケーションのタスクをスケジューリングする機能自体には料金は発生しません。ワークロードのスケジューリングを無料で提供できるのは、Amazon ECS が最初からマルチテナントアーキテクチャとして設計されているためです。シングルテナント前提の設計では、お客様のクラスターごとにそのクラスターのスケジューリングを行うための専用のコントロールプレーンが必要になります。クラスターごとの専用のコントロールプレーンは使用量に関わらずコストが発生するため、コントロールプレーンを十分に活用していない小規模なワークロードでは無駄が発生します。一方、Amazon ECS のコントロールプレーンは共有テナントモデルを採用しており、共有の巨大なスケジューリングキャパシティを分割し、すべてのユーザーに一度にサービスを提供します。小規模なクラスターや小規模なサービスのデプロイは、スケジューラの時間のごく一部のみを占めるため無駄がありません。大規模なクラスターはより多くのリソースを使用しますが、コントロールプレーンの共有キャパシティは非常に大きく、必要なときに利用することができます。

Amazon ECS がレート制限で顧客体験を保護する方法

Amazon ECS は現在、オーケストレーターとして Amazon ECS を使用しているすべての AWS のお客様を対象に、1 秒間に数千のタスクをスケジューリングしています。タスクの起動にレート制限を設けることで、Amazon ECS を使用しているお客様の間でスケジューリングワークロード全体が公平に分散されます。レート制限により、あるお客様のタスクの起動によって Amazon ECS のコントロールプレーンや AWS Fargate のキャパシティプールを圧迫することを防ぎ、他のお客様の体験に影響を与えないようにします。

Amazon ECS のレート制限はトークンバケットアルゴリズムを使用して実装されています。AWS がトークンバケットをどのように使用しているかについての詳細は Amazon Builders’ Library に書かれていますが、ここでの要点は、トークンバケットに対して設定可能な最大トークン数まで、設定されたレートでトークンが追加されていくことです。RunTask API を呼び出すなどして Amazon ECS を使用する場合、コントロールプレーンはトークンバケットからトークンを消費します。トークンバケットが空になると RunTask API の呼び出しなどのアクションは、トークンバケットにトークンが追加される新しいバッチを待つ必要があります。このアプローチでは、必要に応じてアクティビティのバーストが可能になりますが、持続的なアクティビティレートも制限されます。

Amazon ECS を使用する際には、3 種類のレート制限を意識する必要があります。

  • サービスデプロイのレート制限: ECS のサービスを作成または更新するときに、サービスが新しいタスクをロールアウトしたり、既存のタスクを新しいバージョンに置き換える速度を制限します。
  • RunTask API のレート制限: これにより、スタンドアロンのタスクを起動できるレートが制限されます。
  • AWS Fargate のキャパシティレート制限: これらは AWS Fargate タスクの起動に特化した個別のレート制限です。

これらのレート制限は、サポートチケットを起票することでケースバイケースで調整できます。これらのデフォルトのレート制限がどのように影響するかを説明するために、それぞれについて少し掘り下げてみましょう。

キャパシティタイプとタスク起動レート

タスク起動レートは Amazon ECS で選択するキャパシティのタイプによって変わります。次の表は、キャパシティタイプ別の現在のレート制限を示したものです。

キャパシティタイプ タスクのバースト 持続可能なタスク起動 調整可能かどうか
AWS Fargate オンデマンドキャパシティ 100 タスク 1 秒あたり 20 タスク 調整可能
AWS Fargate スポットキャパシティ 100 タスク 1 秒あたり 20 タスク 調整可能
EC2 インスタンス 制限なし 制限なし
ECS Anywhere 制限なし 制限なし

AWS Fargate のレート制限はアカウント全体に適用されます。これは、同じ AWS アカウントにあるすべてのクラスターのすべてのサービスが、同じ AWS Fargate タスク起動レート制限を共有していることを意味します。ただし、AWS Fargate のオンデマンドキャパシティと AWS Fargate スポットキャパシティのトークンバケットは別々に分割されています。つまり、スポットキャパシティがある限り、1 秒あたり最大 20 回の継続的なオンデマンドキャパシティでのタスク起動と同時に、1 秒あたり最大 20 個のスポットのタスクの起動を実現できます。

AWS Fargate のレート制限を検討する際には、タスクのサイズで調整できることを覚えておくことが重要です。最小タスクサイズの 0.25 vCPU では、1 秒あたり最大 5 個の vCPU のオンデマンドキャパシティと 5 個の vCPU のスポットキャパシティを起動できます。最大タスクサイズの 4 vCPU では、1 秒あたり最大 80 個の vCPU のオンデマンドキャパシティと 80 個の vCPU のスポットキャパシティを起動できます。したがって、より多くのキャパシティをより早く起動する必要がある場合は、タスクサイズを増やすことで、同じ時間枠内により多くのコンピューティングリソースを確保できます。それでも十分でない場合は AWS サポートチケットを起票し、レート制限の引き上げをリクエストして 1 秒あたりのタスク数を増やすこともできます。

EC2 キャパシティを使用する場合、実行中の EC2 インスタンス上で起動するタスクにレート制限はありません。サービスのデプロイや RunTask などの高レベル API には、EC2 キャパシティでタスクを起動できる速度を制御する独自のレート制限がありますが、多くのサービスが同じ EC2 キャパシティで同時にタスクを起動させることができます。ただし EC2 のクォータとしてクラスターに登録できる EC2 キャパシティの量と登録できる速度に制限があるため、場合によってはそちらを検討する必要があるかもしれません。ECS Anywhere ではタスクの起動にレート制限はありませんが、SSM マネージドインスタンスのクォータを考慮する必要があります。

サービスデプロイのレート制限 – サービスのデプロイと更新の高速化

2021 年から 2022 年にかけて Amazon ECS のスケジューリングがより進化しました。AWS Fargate キャパシティを使用する場合は毎分最大 500 タスク、EC2 キャパシティを使用する場合は毎分最大 250 タスクのレートで各サービスをデプロイできるようになりました。AWS Fargate のデプロイレートは昨年の 16 倍速く、EC2 キャパシティではデプロイレートが 2 倍になりました。

この進化が Amazon ECS を使用するお客様の体験にどのような影響を与えるかを説明するために、大量のトラフィックを受信する、大規模なウェブ API 用の Amazon ECS サービスを作成する場合を考えてみましょう。この API へのウェブトラフィックは非常に多いため、すべてのトラフィックを処理するには 1,000 個のタスクが必要になります。タスクを起動するため、サービスの希望数を 1,000 に設定します。Amazon ECS のコントロールプレーンはこのリクエストに対して、1,000 個の新しいタスクを起動する必要がありますが、1,000 個のタスクすべてを一度に起動するわけではありません。代わりに、ワークフローサイクルの実行を開始して、現在の状態 (タスクが 0 の状態) を目的の状態 (1,000 タスクの状態) に近づけます。ワークフローサイクルごとに新しいタスク起動のバッチが開始されます。タスクのスケジューリング速度が向上したことで、これら 1,000 個のタスクがより速く起動し、ワークフローサイクルが減ります。AWS Fargate をキャパシティとして使用すると、これらの 1,000 個のタスクを約 2 分でスケジュールできます。

しかし、実際のシナリオでは、タスクのスケジューリング以外にも多くのことが行われています。コンテナイメージをダウンロードして解凍する必要があったり、アプリケーションに正常に起動していることを検証するヘルスチェックが含まれている可能性もあります。また、タスクをロードバランサーに自動的に登録するなどの、Amazon ECS との統合を有効にしている場合もあります。Amazon ECS サービスで有効にする機能と、使用されているキャパシティのタイプ (Amazon EC2 または Fargate) によっては、タスクの起動速度にばらつきが生じる場合があります。Amazon ECS のサービスが、サービス内のタスクをどれだけ早くロールアウトできるかを把握するために、現実世界のさまざまなサービス設定に対していくつかのベンチマークを実行しました。これらのベンチマークでは、コンテナ実行基盤へのタスクのスケジューリング、コンテナイメージのダウンロード、実行、および正常性の評価にかかるエンドツーエンドの時間がカウントされるため、1,000 個のタスクに対して合計デプロイ時間が 2 分より少し長くなることがわかります。

ベンチマーク タスクの量 時間 レート
AWS Fargate オンデマンドキャパシティ、ロードバランサー無し 1,000 タスク 208 秒 4.8 タスク/ 秒
AWS Fargate スポットキャパシティ、ロードバランサー無し 1,000 タスク 353 秒 2.8 タスク/ 秒
AWS Fargate 50/50 のオンデマンド/スポットキャパシティ 1,000 タスク 213 秒 4.7 タスク/ 秒
AWS Fargate オンデマンドキャパシティ、パブリック IP アドレス無し 1,000 タスク 199 秒 5 タスク/ 秒
AWS Fargate オンデマンドキャパシティ、ロードバランサー有り 1,000 タスク 252 秒 4 タスク/ 秒
EC2 キャパシティ、キャパシティプロバイダ使用、初期の EC2 インスタンス起動無し 1,000 タスク 1,118 秒 0.8 タスク/ 秒
EC2 キャパシティ、EC2 インスタンス起動済み 1,000 タスク 270 秒 3.7 タスク/ 秒
EC2 キャパシティ、host ネットワークモード使用 1,000 タスク 270 秒 3.7 タスク/ 秒

これらのタスク起動シナリオのいくつかを自分でテストしたい場合は、これらのテストで使用された CloudFormation テンプレートを GitHub からダウンロードし試すことができます。

上記の表から特に注意すべき事項をいくつか挙げます。

  • 1 つのサービスの場合、Amazon EC2 のキャパシティを使用するよりも、AWS Fargate の方がサービスによるタスクの起動速度が速くなります。AWS Fargate では標準化されたタスクサイズを、そのサイズのタスクを実行したい人のために事前ウォーミングされた状態で保持しておくためです。Amazon ECS のスケジューラはタスクの起動が必要なときに、この AWS Fargate タスクプールからタスクをリクエストするだけです。EC2 キャパシティの場合、スケジューラは事前に準備されたタスクを利用できません。任意のサイズのタスク用のスペースを持つ EC2 インスタンスを検索し、そのスペースを予約して、そのインスタンスでタスクを都度起動する必要があります。
  • 1 秒あたり 20 回の AWS Fargate タスク起動のデフォルトレート制限は、3 つ以上のサービスを並行してデプロイすると、AWS Fargate キャパシティよりも EC2 キャパシティでのサービスのデプロイの方が速くなることを意味します。
  • EC2 インスタンスがまだ準備されていない状態で、キャパシティプロバイダを使用してサービスを起動する場合、Amazon ECS は EC2 インスタンスを都度起動します。起動が完了するまで待機してからコンテナを起動する必要があるため、タスクの起動速度が大幅に低下します。Amazon EC2 のキャパシティがすでに起動されタスクを実行する準備ができていると、タスク起動レートが向上します。
  • Amazon VPC ネットワーキングモードを使用する AWS Fargate タスクを起動するときに、タスクごとに割り当てるパブリック IP アドレスをオフにすると、タスクの起動速度がわずかに向上することがあります。
  • AWS Fargate スポットキャパシティのタスクの起動は、リージョンで利用可能なスポットキャパシティの量に依存するため、AWS Fargate のオンデマンドキャパシティでのタスクよりも時間がかかる場合があります。一般的に、オンデマンドキャパシティでのタスクの起動の方が高速です。ただし、レート制限に直面している場合でも、スポットキャパシティでのタスクとオンデマンドキャパシティでのタスクを 50/50 の組み合わせを使用することで、全体的なタスク起動レートを高めることができます。
  • ロードバランサーをサービスに追加すると、タスクの起動速度がわずかに低下します。非公開のワークロードで迅速にタスクを起動したい場合には、ロードバランサーよりも DNS ベースのサービスディスカバリ、またはサービスメッシュを使用することをお勧めします。

また、Amazon ECS のタスクのスケジューリングに適用される、組み込み済みのレート制限もいくつかあります。注意すべき重要なレート制限の 1 つは、安定稼働するコンテナをサービスが正常に起動できない場合のエクスポネンシャルバックオフです。アプリケーションコンテナが起動しない、起動直後にクラッシュする、またはヘルスチェックに合格しなかった場合、Amazon ECS はサービスのタスクが安定していないことを検出し、エクスポネンシャルバックオフを使用してこのサービスのスケジューリングを自動的に遅くします。これにより、同じクラスター内で実行されている隣接のワークロードが、タスクの起動とクラッシュの無限ループの影響を受けるのを防ぎます。タスク起動時のエクスポネンシャルバックオフをリセットするには、サービスを新しいタスク定義リビジョンに更新するか、force-new-deploy フラグを true に設定して UpdateService API を呼び出します。

上記のような基礎となるキャパシティレート制限は、引き続き適用されることを意識することが重要です。具体的には、AWS Fargate のオンデマンドキャパシティを使用する複数の ECS サービスをデプロイする場合、それらはすべて 1 秒あたり 20 タスクという、基礎となる AWS Fargate タスク起動レート制限を共有します。そのため、すべてのサービスを並行してデプロイする場合に、サービスデプロイのタスクの起動レートが最大になるよう、AWS Fargate タスク起動レートを上げるようにサポートチケットを起票する必要があります。

RunTask API のレート制限 – 多くのスタンドアロンジョブをより速く実行する

Amazon ECS のサービスに加えて、RunTask API を使用してクラスター内でスタンドアロンのタスクを起動するお客様もいます。この API は通常、ジョブごとに新しい Amazon ECS のタスクを実行するバッチワークロードに使用されます。たとえば、機械学習、ビデオレンダリング、科学技術アプリケーションなどがあります。RunTask API は、スケジュール起動の cron ジョブ、Amazon EventBridge イベントへの応答としてのタスク実行、AWS Step Functions ワークフローの一部としてのタスク実行などのユースケースにも使用されます。

RunTask API にはいくつかの制限があります。まず、API コールごとに最大 10 個のタスクを起動できます。さらに、RunTask API を呼び出す速度を制御するトークンバケットのレート制限があります。このレート制限により、API へのコールを最大 100 回までバーストできます。トークンバケットが更新されると、1 秒あたり 40 回の持続的な RunTask API 呼び出しのレートが許可されます。この API では、API コールごとに最大 10 個のタスクを起動できるため、RunTask API を使用して最大 1,000 個までタスク起動をバーストでき、EC2 または ECS Anywhere のキャパシティでは 1 秒あたり最大 400 個の持続的なタスク起動レートを実行できます。EC2 でのタスク起動には基礎となるレート制限がないため、RunTask API の制限の最大値まで複数のサービスを同時に EC2 にデプロイできます。

ただし、AWS Fargate のキャパシティでタスクを実行する場合、RunTask API のレート制限やサービスデプロイのレート制限よりも、基礎となる 1 秒あたり 20 回のタスク起動レートが優先されます。RunTask API のレート制限により、1 秒間に最大 400 個のタスクを起動できますが、それらのタスクが Fargate タスクの場合、1 秒あたり 20 個を超えるオンデマンドキャパシティでのタスクを起動しようとするとレート制限エラーが返されます。しかし、オンデマンドの Fargate タスクのレート制限に達した場合でも、RunTask API の全体的なレート制限にまだ達していない限り、AWS Fargate スポットキャパシティでのタスクまたは EC2 キャパシティでのタスクを起動できます。さらに、基礎となる AWS Fargate のレート制限は、サービスデプロイのタスクの起動と RunTask のタスクの起動間で共有されます。そのため、RunTask でタスクを起動しながら Fargate への同時サービスデプロイを行う場合は、Fargate のキャパシティレート制限に達するのが早くなる可能性があります。問題が生じた場合、この Fargate のキャパシティレート制限は、サポートチケットを介して引き上げることができます。

多くのお客様は、レート制限や API スロットリングを気にすること無く大規模なバッチワークロードを実行するために AWS Batch を選択します。AWS Batch では、SubmitJob API を使用して、一度に最大 10,000 個のジョブのバッチを送信できます。この SubmitJob API は 1 秒間に最大 50 回呼び出すことができ、1 秒間に最大 500,000 個のジョブを送信できます。ジョブは、AWS Fargate または EC2 キャパシティで ECS タスクとして起動できるようになるまで、ジョブを保持するキューに保存されます。AWS Batch は、すべてのジョブが実行されるまでお客様に代わって Amazon ECS の RunTask API を呼び出して、キューに入れられたジョブを最大レートで処理します。これにより、Amazon ECS の RunTask API の制限を処理する独自のコードを実装しなくても、大規模なバッチワークロードを簡単に処理できます。

RunTask API を直接呼び出したり、Amazon ECS クラスターでジョブを実行するための仲介として AWS Batch を使用したり、タスクの実行をトリガーする Amazon EventBridge ルールを実装したりするかどうかに関わらず、RunTask API のレート制限により、より多くの Amazon ECS タスクを 1 秒間に起動できるようになりました。繰り返しになりますが、これらのレート制限が低すぎる場合は、サポートチケットを起用することでケースバイケースで引き上げることができます。

まとめ

開発者はますます大規模にサービスを構築しており、そのサービスはかつてない規模で運用されています。開発者は Amazon ECS を使用してこれらのサービスをオーケストレーションしています。Amazon ECS タスクの起動レートが向上し続けるにつれて、これらの開発者はより大規模なウェブサービスをより迅速にロールアウトし、Amazon ECS を使用して大量のバッチジョブをオーケストレーションできるようになります。AWS は Amazon ECS をさらに強力にする努力を続けます。そして、新規および既存のビルダーが Amazon ECS をコントロールプレーンとして使用し、どのようなものを構築するかを楽しみにしています。

コンテナの起動レートについてさらに深く掘り下げた記事を読みたい場合、AWS コンテナヒーローである Vlad Ionescu が Amazon ECS でのコンテナのスケーリングレートについて研究した幅広い記事を執筆しています。彼の記事では、2020 年、2021 年、2022 年のタスク起動レートの履歴が示されているため、時間の経過に伴う傾向を確認できます。また、Amazon Elastic Container Service と Amazon Elastic Kubernetes Service のコンテナ起動レートを、EC2 と AWS Fargate の両方のキャパシティで比較しています。

タスク起動レートに影響するクォータの詳細については、以下もご覧ください。

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