Amazon Web Services ブログ

Amazon ECS クラスターの Auto Scaling を深く探る

 

概要

つい最近まで、ECS クラスター内での EC2 インスタンスの数を、タスクとサービスに合わせてスケーリングさせようとすると、難しい問題の発生することがありました。  ECS クラスターは必ずしも必要なときにスケールアウトするわけではなく、スケールインは注意深く扱わないと可用性に影響を及ぼします。ときには、顧客はこの課題に対応するため、Lambda 関数などのカスタムの手法、カスタムのメトリクス、そして重量挙げにも例えられるような他の手段に訴えましたが、あらゆる状況でうまくいく単一のアプローチはありませんでした。もちろん、タスクを EC2 インスタンスの代わりに Fargate で実行すれば、クラスターのスケーリングの必要性は全くなくなりのですが、すべての顧客がすべてのワークロードで Fargate を採用する用意ができている、または用意ができるわけではありません。

ECS クラスター Auto Scaling (CAS) は、EC2 Auto Scaling グループ (ASG) のスケーリングを管理する、ECS のための新しい機能です。CAS を使えば、ECS が ASG を自動的にスケーリングするように構成できるので、自分のタスクにのみ注意を集中できます。ECS は必要に応じて ASG がスケールインおよびスケールアウトできるようにします。それ以上の介入は必要ありません。CAS は、ECS クラスターとユーザーが使用する ASG の間をリンクする、ECS のキャパシティプロバイダに依存します。それぞれの ASG は 1 つのキャパシティプロバイダと関連付けられ、キャパシティプロバイダはただ 1 つの ASG を持ちますが、1 つの ECS クラスターには多数のキャパシティプロバイダを関連付けることができます。クラスター全体を自動的にスケーリングするために、それぞれのキャパシティプロバイダが、関連している ASG のスケーリングを管理します。

CAS をローンチする際の私たちの目標の 1 つは、ECS クラスターのスケーリングが「ただ機能する」ようにすること、ユーザーがそれについて考えなくてもうよいようにすることでした。それでもやはり、舞台裏で何が生じているか知りたいと思われるかもしれません。この記事では、CAS が働く仕組みについて、深く探ってみることにします。

設計目標

顧客からのフィードバックに基づき、私たちは CAS に対し 3 つの設計目標を定めました。

設計目標 #1: 顧客が実行しようとしているタスクを実行するだけのキャパシティがなかったら、CAS は ASG をスケールアウトする (インスタンスを追加する) こと。

設計目標 #2: CAS は、(デーモンタスク以外の) タスクを中断しないで行える場合にのみ、スケールインする (インスタンスを除去する) こと。

設計目標 #3: 顧客が ASG を完全に制御できるようにすること。これには最小サイズと最大サイズの設定、他のスケーリングポリシーの使用、インスタンスタイプの設定などが含まれます。

この記事の後の部分で説明しますが、CAS の設計はこれら 3 つの目標すべてを満たしています。

中心となるスケーリングロジック

CAS の中心的な責任は、ASG に割り当てられたタスクの必要を満たす上で「適切な」数のインスタンスが ASG で実行されるようにすることです。これには、既に実行されているタスクと、既存のインスタンスには収まらない、顧客が実行しようとしているタスクの両方が含まれます。その数を M としましょう。また、既に実行されている ASG 内の現在のインスタンス数を N とします。この記事の残りの部分では M と N が繰り返し出てくるので、これらをどう考えたらよいかを十分明確に理解しておくことが重要です。  今のところ、M をいくらにしたらよいかを知る方法は説明していませんが、議論の目的上、M は必要数であるとだけ仮定します。この仮定の下で、もし N = M であるとするなら、スケールアウトは必要ではなく、スケールインは不可能です。一方、N < M なら、十分なインスタンスがないことになるので、スケールアウトが必要です。  最後に N > M なら、スケールインが可能です (ただし必要だとは限りません)。自分の ECS タスクすべてを実行するのに必要な数よりも多くのインスタンスが存在しているからです。また、後ほど見るように、N と M に基づく新しい CloudWatch メトリクスを定義し、それをCapacityProviderReservation と呼ぶことにします。N と M が与えられたときのこのメトリクスの定義は非常にシンプルです。

簡単に説明するなら、このメトリクスは、ASG の実際の大きさと必要な大きさとの比を、パーセント単位で表したものです。  この記事の後の方で説明しますが、このメトリクスは CAS が ASG のスケーリングをコントロールするために用いているものです。  上の式で、数値 M は CAS がコントロールする部分ですが、この M は顧客のタスクによって決まります (既に実行されているタスクと実行を待機しているものの両方)。M の計算方法が、CAS が実際にスケーリングを行う際の鍵となっています。

M を決定するためには、顧客が実行しようとしているものの、既存のインスタンスには収まらないタスクという概念が必要です。その目的で、既存の ECS タスクのライフサイクルを採用しました。  以前のタスクは、利用可能なキャパシティに基づいて、実行されるかされないかのどちらかでした。今後、プロビジョニング状態のタスクには、既存のインスタンス上に十分なリソースを見つけられないでいるタスクが含まれるものとします。これは、例えば、RunTask API を呼び出したものの、リソース不足のためにそれらのタスクがインスタンス上に配置されなかった場合 (どのアクティブなインスタンスにもタスクを実行するのに十分なメモリ、vCPU、ポート、ENI、GPU がないということです)、直ちに失敗させるのではなく、タスクがプロビジョニング状態に入ることを意味します (ただし、プロビジョニングへの移行は、キャパシティプロバイダでマネージドスケーリングを有効にしている場合にのみ生じるものとします。それ以外の場合、キャパシティを見つけられなかったタスクは、以前のように直ちに失敗します)。より多くのインスタンスが利用可能になれば、プロビジョニング状態のタスクはそれらのインスタンスに配置され、プロビジョニング状態のタスクの数は減っていきます。  ある意味で、プロビジョニング状態のタスクは待ち行列に入っていると見なすことができます。リソースが原因で配置されなかったタスクは待ち行列に入り、リソースが利用可能になると、タスクは待ち行列から取り出されます。

現時点では、どのクラスターでも最大 100 のタスクをプロビジョニング状態にすることができます。そして、インスタンスに配置されなかったプロビジョニングタスクは、15 分経過すると、実行されないまま「停止」されます。

新しいタスクのライフサイクル動作をこのように定めたとして、CAS はどのようにインスタンスの必要数 M を決定するのでしょうか。 最上位では、ロジックは非常にシンプルです。

  1. すべてのインスタンスが、デーモンサービスタスクを除いて少なくとも 1 つのタスクを実行しており、プロビジョニング状態のタスクが存在しなければ、M = N です。(デーモンサービスタスクは除いています。どのインスタンスでも実行されているはずのデーモンサービスタスクのためにスケーリングが発生することは望まないからです。そうでなければ、スケールアウトが限りなく続くことになります)。図 1 は例を図で説明しています。

    <em>図 1. ASG は 3 つのインスタンスがあり (紫色のボックス、N = 3)、それぞれがデーモン以外のタスクを実行しています (緑色のボックス)。プロビジョニングタスクはありません。これ以上インスタンスは必要ない一方、どのインスタンスも既存のタスクを中断せずに終了することはできないので、M = N = 3 です。</em>

    図 1.ASG には 3 つのインスタンスがあり (紫色のボックス、N = 3)、それぞれがデーモン以外のタスクを実行しています (緑色のボックス)。プロビジョニングタスクはありません。これ以上インスタンスは必要ない一方、どのインスタンスも既存のタスクを中断せずに終了することはできないので、M = N = 3 です。

  2. 少なくとも 1 つのプロビジョニング状態のタスクがある場合には M > N です。この場合の M の計算方法については次に説明します。図 2 は例を図で説明しています。

    図 2. 既存のインスタンス (N = 3) には 3 つのプロビジョニングタスクのための余地がありません。この例では、プロビジョニングタスクを実行するためにさらにインスタンスが必要なので M > 3 です。M の実際の値を判断するには、さらに作業が必要です。

    図 2。プロビジョニングタスクを実行するためにさらにインスタンスが必要なので M > 3 です。この例では、プロビジョニングタスクを実行するためにさらにインスタンスが必要なので M > 3 です。M の実際の値を判断するには、さらに作業が必要です。

  3. 少なくとも 1 つのインスタンスはタスクを実行しておらず (デーモンサービスタスクは除く)、プロビジョニング状態のタスクもないので、M < N となります。さらに正確に言うと、M は少なくとも 1 つのタスクを実行しているインスタンスの数です (やはりデーモンサービスタスクは除きます。これらはすべてのインスタンスで実行されているものと想定されるからです。デーモンサービスを含めるとしたら、スケーリングは決して起きません)。図 3 は例を図で説明しています。

    図 3. 緑色のボックスはデーモン以外のタスクを表しており、青色のボックスはデーモンタスクを表しています。既存のインスタンスがすべてデーモン以外のタスクを実行しているわけではありません。3 番目のインスタンスはデーモン以外のタスクを中断せずに終了できるので、M = 2 です。

    図 3.緑色のボックスはデーモン以外のタスクを表しており、青色のボックスはデーモンタスクを表しています。既存のインスタンスがすべてデーモン以外のタスクを実行しているわけではありません。3 番目のインスタンスはデーモン以外のタスクを中断せずに終了できるので、M = 2 です。

 

では、少なくとも 1 つのタスクがプロビジョニング状態にある場合の M の計算方法について考えてみましょう。M が N より大きいことはわかっています。しかしどの程度大きいのでしょうか。 理想的には、CAS には最適な M の値を計算してほしいものです – つまり、プロビジョニング状態のすべてのタスクを実行するのに大きすぎず、小さすぎもしない値です。残念ながら、このことはたいてい非実際的か、不可能です – タスクはそれぞれ、リソースの要件、配置上の制約および配置戦略が異なっています。また ASG が、vCPU、メモリ、および利用可能な他のリソースの点で異なる複数のインスタンスタイプを持っている場合さえあります。このトピックを十分詳しく扱おうとすると、数学的最適化に関する大学院レベルの内容になるでしょう。それでここでは、タスクとインスタンスの可能なあらゆるバリエーションに対して最適な値の M を求めるアルゴリズムを開発することは、計算理論上実行不能であるとだけ言っておきます。

M の最適値を求めることは一般的に無理なので、代わりに CAS はよい見積もりを行おうと努めます。ASG にすでにインスタンスがあり、ASG が単一の AZ と単一のインスタンスタイプを使用するように構成されていると、CAS は追加すべきインスタンス数の最適値の下限を見積もり、その値を M として用います。言い換えると、プロビジョニング状態のタスクをすべて実行するには、少なくとも M だけ多くのインスタンスが必要だということです。この場合、CAS は M を次のように計算します。

  1. すべてのプロビジョニングタスクをグループ化して、それぞれのグループのリソース要件が正確に等しくなるようにします。
  2. ASG に最も新しく追加されたインスタンスのインスタンスタイプと属性を取得します。
  3. リソースの要件が等しいグループごとに、binpack 配置戦略を使用した場合に必要となるインスタンス数を求めます (配置戦略は必要なインスタンス数の下限を変えることはできません。これらのインスタンス上でのタスクの分散を変えられるだけです)。この計算では、タスクおよびインスタンスの vCPU、メモリ、ENI、ポート、および GPU を考慮に入れます。タスクの配置の制約考慮されます。  ただし、distinctInstance 以外の配置の制約は推奨されません。
  4. すべてのタスクグループにわたるステップ 3 の最大値を M として算出します。
  5. 最後に、 M >= N + minimumScalingStepSize および M <= N + maximumScalingStepSize という条件を要求します。(これらの 2 つのパラメータは、キャパシティプロバイダの構成で定義されます)。

 

このアルゴリズムから得られる M は、一般に必要なインスタンス数の下限を与えます。そしてある場合には必要なインスタンス数と正確に一致します。例えば、すべてのプロビジョニングタスクが同一であり、ASG が単一のインスタンスタイプを使用するように構成されていて、タスクに配置の制限が課されていなければ、このアルゴリズムは、必要なインスタンス数と正確に一致します (M がステップ 5 で定義した範囲内に収まるとして)。

M がプロビジョニングタスクのすべてを実行するのに十分なインスタンス数を与えないとしても、すべてが無駄であるというわけではありません。後ほど示すように、ターゲットのキャパシティを 100 として、ASG はインスタンス数 M にスケールアウトします。必ずしもすべてとは限りませんが、プロビジョニングタスクの一部は、新しいインスタンスに配置されます。M が十分なインスタンス数でなかった場合には、いくつかの追加のタスクがやはりプロビジョニング状態に置かれます。これにより別のスケーリングアクションが起動され、M の新しい値が算出されます。これは、プロビジョニング状態のタスクがなくなるまで繰り返されます。このプロセスは 1 ステップで終わることが理想的です。ステップごとに完了するまでの時間がかかるためなので、CAS が 1 ステップで正しいサイズにスケーリングすれば、ASG は正しいサイズに迅速に達することができます。ただし、複数のステップが必要だとしても、いずれは適切なサイズに達します。

ASG が複数のインスタンスタイプを使用している場合、または単一の AZ に制限されていない場合にはどうでしょうか。 この場合、上記のアルゴリズムは必ずしも下限を与えません。それで CAS はずっとシンプルなアプローチである、M = N + minimumScalingStepSize にフォールバックします。効率は劣りますが、これもやがては適切なサイズに達します。

AWS Auto Scaling とスケーリングメトリクス

CAS が M を算出した後に、自分で ASG に望ましいキャパシティ値を設定するのはどうでしょうか (つまり、N = M となるように手動で強制すること)。 そうすべきでないのは、設計目標 #3 を達成することができなくなるからです。望ましいキャパシティ値を直接設定すると、構成されている他のスケーリングポリシーが上書きされてしまい、スケーリング設定をすべて手作業で CAS に渡すことが必要になるからです。それで、3 つすべての設計目標を達成するため、CAS は、インスタンスの終了保護に加えて、 AWS Auto Scaling に依存するようになっています。もう少し詳しく言うと、ASG キャパシティプロバイダでマネージドスケーリングとマネージド終了保護を有効にした場合、ECS はユーザーに代わって次のことを行います。

  1. ASG のスケーリングプランを作成する。
  2. ターゲットトラッキングスケーリングポリシーを作成して、スケーリングプランと関連付ける。スケーリングポリシーは CapacityProviderReservation という新しい CloudWatch メトリクスを使用します。これは ECS が ASG キャパシティプロバイダごとに公開するもので、マネージドスケーリングを有効にします (同じ ASG の別のスケーリングポリシーをスケーリングプランにアタッチして使用すること、さらには EC2 予測スケーリングを使用することさえできます)。
  3. CapacityProviderReservation メトリクスの定期的な公開を開始します (1 分間に 1 度)。
  4. インスタンスの終了保護を管理して、ASG のスケーリングのためにデーモン以外のタスクが終了させられることを防止します。

CapacityProviderReservation メトリクスの目的は、他のスケーリングポリシーが ASG 内で機能する余地を残しながら、ASG 内のインスタンス数をコントロールすることです。  言い換えると、他のスケーリングポリシーを使用しなければ、ASG の希望数は M (CAS が必要であると判断したインスタンス数) になるということです。  N は ASG ですでに開始されて動作しているインスタンス数であることを思いだしてください。  M と N をターゲットトラッキングスケーリングと互換性のあるメトリクスに変換する際には、「メトリクス値は Auto Scaling グループのイスタンス数に比例して増加または減少しなければならない」という要件に従う必要があります。 この要件を念頭に置いた上での、私たちの CapacityProviderReservation の計算方法は、次のようになります (前述したものと同じです)。

この公式を使えない、いくつかの特殊例もあります。M と N が両方ともゼロである場合は、インスタンスはなく、動作中のタスクもなく、プロビジョニングタスクもないので、CapacityProviderReservation = 100 にします。  M > 0、N = 0 の場合は、インスタンスはなく、動作中のタスクもないものの、少なくとも 1 つのプロビジョニングタスクがあるので、CapacityProviderReservation = 200 にします。(ターゲットトラッキングスケーリングには、ゼロキャパシティからのスケーリングを行う際に用いる特殊例があり、スケーリングの目的に基づいて、現在のキャパシティをゼロではなく 1 にします)。

図 1、2、3 のシナリオをもう一度見てみましょう。

  • 図 1 では、CapacityProviderReservation = 3/3 X 100 = 100 になります。
  • 図 2 では、M = 4 にします。3 つのプロビジョニングタスクに加えて、もう 1 つのインスタンスを実行する必要があるからです。  そのため、CapacityProviderReservation = 4/3 X 100 = 133 になります。
  • 図 3 では、CapacityProviderReservation = 2/3 X 100 = 66 になります。

ターゲットトラッキングスケーリングポリシー

ターゲットトラッキングスケーリングポリシーは、ASG のキャパシティを管理します。特定のメトリクスとそのメトリクスの目標値が与えられると、このスケーリングポリシーは ASG のサイズを増加または減少させます。言い換えると、メトリクスが増加または減少したときには、メトリクスを目標値に近いか、それと等しい値に保てるように、N を調整します。スケーリングの動作は「メトリクス値は Auto Scaling グループのイスタンス数に比例して増加または減少しなければならない」という仮定に基づいて定められます。 CapacityProviderReservation は、この仮定に合わせてデザインされています。

CapacityProviderReservation を 100 にするという目標値が与えられた場合、スケーリングポリシーは N = M が成立するまで ASG のサイズ (N) を増減します。これが正しいのは、等式 CapacityProviderReservation = 目標値 (または同等な M / N X 100 = 100) は、N = M の場合にのみ成立するからです。より多くのタスクを実行して、または既存のタスクをシャットダウンして M を変化させると、スケーリングポリシーは N を変化させて M と N が等しい状態を保てるようにします。ゼロにスケーリングする、またはゼロからスケーリングすることさえ可能です。M=0 の場合、つまりデーモンサービスしか実行されていない場合には、N も 0 に調整されます。同様に、 N=0 で M>0 の場合には、タスクはプロビジョニングされているものの、実行されていないことを意味しているので、CapacityProviderReservation = 200 に設定して、N を増加側に調整して、ASG にインスタンスが追加されるようにします。

目標値を 100 未満にすると、ASG にスペアのキャパシティを設けることができます。たとえば、目標値を 50 に設定すると、スケーリングポリシーは N を調整して、M / N X 100 = 50 の等式が成り立つようにします。(M は CAS がすべてのタスクを実行するために必要だと見積もったインスタンス数であり、スケーリングポリシーの目標値に基づいてはいないことに注意するのは重要です)。少し計算してみると、N = 2 X M になることがわかります。言い換えると、目標値を 50 にした場合、スケーリングは N を調整して、CAS がすべてのタスクを実行するために必要だと見積もったインスタンス数のちょうど 2 倍になるようにします。このことは、インスタンスの半分は、タスクを実行しないことを意味します。これらのインスタンスは、タスクの開始前にインスタンスを追加しなくても、即座に追加のタスクを実行できるようにするために利用できます。これらのスペアインスタンスがタスクを実行すると、スケーリングポリシーは N を再び調整して (大きくし)、N = 2 X M の等式が守られるようにします。同様に、タスクを実行していたインスタンスのいくつかが後ほど実行を終えると、N は同様の方法で小さくなるように調整されます。

より一般的にまとめると、目標値が小さいほど、ASG で利用できる臼ペアのキャパシティは多くなります。  たとえば、目標値が 10 の場合、スケーリングポリシーは N を (利用可能な範囲内で) 調整し、ASG のインスタンスの 90% は、どれほど多くのタスクを実行しているかには関わりなく、タスクを実行しないことになります。 目標値を 100 未満にするとしても、ゼロにスケーリングすることは不可能であることに注意してください。スペアのキャパシティを維持するという目標は、ゼロへのスケーリングとは相容れないからです。

ターゲットトラッキングスケーリングポリシーについて注意すべき重要な点は、メトリクスが目標値に正確に等しくなることを常に保証できるわけではないということです。たとえば、目標値を 75、M = 10 に設定した場合、M / N X 100 を正確に 75 にすることは不可能です。N は整数でなければならないからです。その代わり、スケーリングポリシーは N を調整して、目標値に近い値が得られるようにします。メトリクスの基本設定では、可能であれば、目標値よりも小さくするようになっています。

スケールインと終了保護

スケーリングポリシーが N を小さくするとき、インスタンス数は調整されますが、どのインスタンスが実際に終了させられるかをコントロールすることはできません。ASG のデフォルトの動作では、タスクを実行していないインスタンスがある場合でも、タスクを実行しているインスタンスが終了させられます。そこで、マネージド型の終了保護機能の出番となります。

図 4. 3 つのインスタンスがあり、2 つがタスクを実行しています。M = 2 と N = 3 なので、CapacityProviderReservation = 66 です (この特定の例では、実行中の 4 つのタスクを理論的には 1 つのインスタンスで実行することが可能だとしても、M は現在タスクを実行しているインスタンス数に基づいてのみ計算されることに注意しておくのは重要です。最小数のインスタンスを用いるという、仮定上のタスクの最適分配ではありません)。目標値が 100 であれば、ASG は 1 インスタンス分スケールインします。

図 4.3 つのインスタンスがあり、2 つがタスクを実行しています。M = 2 と N = 3 なので、CapacityProviderReservation = 66 になります。(この特定の例では、実行中の 4 つのタスクを理論的には 1 つのインスタンスで実行することが可能だとしても、M は現在タスクを実行しているインスタンス数に基づいてのみ計算されることに注意しておくのは重要です。最小数のインスタンスを用いるという、仮定上のタスクの最適分配ではありません)。目標値が 100 であれば、ASG は 1 インスタンス分スケールインします。

図 4 の例を考えてみてください。メトリクス値は 66 で目標値が 100 なので、ASG は N を 3 から 2 に減らして、スケールインします。スケールイン動作では、図 4 の 3 番目のインスタンスを終了するのがもっともだと思えますが、付加的な入力がないので、タスクを実行していないインスタンスが終了されるように保証する方法はありません。この理由で、ユーザーの代わりにインスタンスの終了保護を ECS に動的に管理させるオプションが実装されました (こうして設計目標 #2 が実現されました)。キャパシティプロバイダでこのオプションを有効にすると、ECS は、デーモン以外のタスクを少なくとも 1 つ実行しているインスタンスをスケールインの際に保護します。これは、スポットインスタンスの回収を妨げる、またはインスタンスを手動で終了できなくなるようにするものではないことに注意してください。ASG がスケーリングの際にインスタンスを終了させることだけを防ぐ機能です。

図 5. マネージド型の終了保護により、ECS は、ASG のスケールインの際、デーモン以外のタスクを実行しているインスタンスが終了させられないようにします。これにより、実行中のタスクが中断される可能性は小さくなります (設計目標 #2)。

図 5.マネージド型の終了保護により、ECS は、ASG のスケールインの際、デーモン以外のタスクを実行しているインスタンスが終了させられないようにします。これにより、実行中のタスクが中断される可能性は小さくなります (設計目標 #2)。

スケーリングの動作

ここまでで、CAS のすべてのピースを定義し終えたので、スケーリングアウトとスケーリングインの詳しい例について見てみることにしましょう。

スケーリングアウト

ステップ 1. クラスターはキャパシティプロバイダと、3 つのインスタンスのある ASG を持っています (上図を参照)。これらはすべてタスクの実行中です。マネージド型のスケーリングが目標値 100 で有効になっており、マネージド型の終了保護も有効です。クラスター内で実行されるタスクの定義はここにのみ出てきます。それですべてのタスクが同じリソースの要件を持っています。この時点では、M = 3、N = 3 であり、CapacityProviderReservation = 100 です。

ステップ 2. RunTask がさらに 9 つのタスクを実行するように呼び出されます。  そのうちの 6 つは既存のインスタンスに配置できますが、3 つはプロビジョニング状態になります。そのため、M = 4、N = 3、CapacityProviderReservation = 133 に変わります。メトリクスは下の図のように動作します。

ステップ 3. メトリクスが目標値の 100 を越えると、スケーリングポリシーが機能して、ASG の希望数を N = 3 から N = 4 に増やします。これらのタスクはまだ (少しの間) プロビジョニング状態です。ECS がそれらをインスタンスに配置していないからです。

ステップ 4. ECS は付加的なキャパシティが利用可能になったことを認識して、プロビジョニングタスクを新しいインスタンスに配置します。

ステップ 5. M = 4 と N = 4 になったので、メトリクスは更新され、CapacityProviderReservation = 100 になります。  これ以上のスケーリングは必要ありません。

スケーリングイン

ステップ 1. これは前のシナリオのステップ 1 と同じです。クラスターはキャパシティプロバイダと、3 つのインスタンスのある ASG を持っています (上図を参照)。これらはすべてタスクの実行中です。マネージド型のスケーリングが目標値 100 で有効になっており、マネージド型の終了保護も有効です。クラスター内で実行されるタスクの定義はここにのみ出てきます。それですべてのタスクが同じリソースの要件を持っています。この時点では、M = 3、N = 3 であり、CapacityProviderReservation = 100 です。

ステップ 2. 1 つのタスクが停止します (例えば、サービススケーリングのため)。ここで、最初の 2 つのインスタンスは終了から保護されていますが、3 番目はそうではありません。スケーリングはまだトリガーされないので、3 つのインスタンスはまだ動作中です。

ステップ 3. ここで、1 つのインスタンスがデーモン以外のタスクから解放され、M=2、 N=3 に更新され、CapacityProviderReservation=66 になります。

ステップ 4. 15 分経過し、メトリクス値が 66 の状態が 15 回続くと、ASG はスケーリングインをトリガーします。3 番目のインスタンスはスケールインから保護されてはいないので、終了させられます。スケールイン動作中に、既存のタスクが中断されることはありませんでした。

ステップ 5. 上記のインスタンスが終了したので、メトリクスは再び更新されて、N=2、M=2 になり、CapacityProviderReservation = 100 になります。これ以上のスケーリングは必要ありません。

まとめ

この記事では、ECS クラスターの Auto Scaling 機能の設計上の目標について高いレベルから考察しました。そして、CAS がこれらの目標を達成する方法の詳細について説明しました。CAS は単に、新しい API であるというわけではありません。これは ECS の動作に関する全く新しいセットを包含しています。皆さんには、スケーリング時のクラスターの動作をよりよく理解できるよう、このブログ記事にすぐにアクセスできるようにしておくことをお勧めします。

最後になりますが、これは CAS とキャパシティプロバイダについてのストーリーの終わりではありません。ECS とキャパシティプロバイダの他の面をカバーするいくつかの記事をこのコンテナブログで計画していますが、それだけではなく、私たちが提供している機能を拡張するためにアクティブに活動する予定です。  新しい機能をリクエストしたい、またはロードマップを見たいという場合には、GitHub の AWS コンテナロードマップを訪れてください。  ありがとうございました。