平常運転

アニソンが好き

過去記事とかは記事一覧で見れます

Amazon ECS Capacity Provider と Fargate Spot と ECS Cluster Auto Scaling を整理する

ラスベガス帰りの id:astj です。

今年も re:Invent ではたくさんのサービスリリース/アップデートがあって目が回るような思いでした。現地にいたからキャッチアップできた中身もあれば、しれっとリリースされていて現地でセッションを聞いてるだけだと気づきそびれた中身もあって物量に圧倒されております。

さて、本稿では2019年の re:Invent で発表された ECS 関連のリリースのうち、以下の3つを中心に整理してみようと思います。

  • Amazon ECS Capacity Provider
  • AWS Fargate Spot
  • AWS ECS Cluster Auto Scaling

遅くなりましたが(ダブルミーニング)、このエントリは はてなエンジニア Advent Calendar 2019 の12/9分のエントリです。ラスベガス時間ではまだ 12/9 ではないでしょうか。そういう話題ではない。

qiita.com

前日は id:kouki_dan さんによる "SlackでクイズができるSlack Appsを作った" でした。

kouki.hatenadiary.com

関係性

今回取り上げる ECS 関連の新機能はそれぞれブログや whats-new で公式からリリースが出ています。

aws.amazon.com
aws.amazon.com
aws.amazon.com

Capacity Provider はブログになってなかったりして非常に地味ですが、おそらくみなさまの関心が高いであろう Fargate Spot や ECS Cluster Auto Scaling を実際の ECS サービス/タスクと関連付けているのは Capacity Provider です。

これまで( = re:Invent 2019 以前)の ECS とコンテナ実行環境

これまで、ある ECS サービス/タスクが EC2 インスタンスで実行されるか Fargate で実行されるかを定めていたのはサービス作成/タスク定義時の起動タイプ(Launch Type) でした。Fargate を選択すればタスクは Fargate で起動し、 EC2 を選択した場合はクラスタに関連付けられた EC2 インスタンス上で動作します。(この指定方法は今も利用可能です!)
また、 EC2 を選択した場合にはクラスタ内で実行されるタスクの増減に応じてインスタンスをスケールする必要がありますが、これらは EC2 Auto Scaling によって CPU なりメモリの利用率を基準にスケールさせるほかありませんでした。特にスケールインの場合は EC2 Auto Scaling によるスケールイン対象選定と ECS 側のインスタンス drain (=> タスク停止)との間に標準の協調処理がないため、タスクが実行されているインスタンスが ACTIVE 状態のまま Auto Scaling で破棄されてしまうことがありました。これによる対処としては、 AWS 公式では EC2 Auto Scaling のライフサイクルフックで Lambda 関数を呼び出して ECS 側でドレインする方法が紹介されているほか、サイバーエージェントさんの Developers Blog では実行中のタスクがある EC2 インスタンスを Auto Scaling において削除保護状態に保つことで回避する方法が紹介されています。いずれにせよ AWS ビルトインの仕組み以外を用いて ECS のインスタンス登録状態と EC2 インスタンスのライフサイクルを橋渡しする必要がありました。

aws.amazon.com
developers.cyberagent.co.jp

Fargate Spot / ECS Cluster Auto Scaling

re:Invent 2019 で、冒頭やタイトルに記載したみっつのサービスが ECS に追加されました。これらはいずれも ECS におけるコンテナ実行環境に関する新サービスです。そのうち、まずは Fargate Spot と ECS Cluster Auto Scaling について確認しましょう。

Fargate Spot

まず Fargate Spot は、これまでの Fargate と比較して安価(現時点の価格比で約3割!)で提供される代わりに、 AWS 側の都合で停止される可能性がある、という Fargate のバリエーションです。

aws.amazon.com

EC2 のスポットインスタンスと近い概念ですが、 EC2 スポットインスタンスを見慣れた我々*1からするとやや驚くべきことに、(現時点では) Fargate Spot のリクエスト時に入札価格などのパラメータをコントロールすることはできません。通常の Fargate の「価格は相対的に高いが実行が保証されている」と、 Fargate Spot の「価格は相対的に安いが停止することがある」の二極を後述の Capacity Provider (そう、 Capacity Provider が登場します!)によってバランス配分することはできますが、 EC2 のように値段や継続実行時間をコントロールすることは現時点ではできない、ということになります。

ECS Cluster Auto Scaling

次いで ECS Cluster Auto Scaling では、今まで EC2 側のリソース状況をトリガーとして EC2 オートスケールグループをスケールするほかなかったのに対し、対象の ECS クラスタが必要としているインスタンスを基準として EC2 クラスタをスケールさせることができます。また、タスクが実行されているインスタンスを Auto Scaling のスケールインから保護することで、 ECS 側に ACTIVE 状態で登録されてコンテナが実行されているインスタンスが停止されることがなくなる、とされています。
(ここでスケールインに関して歯切れが悪いことに関しては後述します。)

この機能のうち前者の Managed Scaling についてもう少し中身を触れてみましょう。
ECS Cluster Auto Scaling は、 AWS のブログエントリ でも触れられていたように、スケール対象の EC2 Auto Scaling Group を作成した後に、 Capacity Provider (そう、また Capacity Provider です!)を設定することで実現できます。設定すると、2サービスのリソースが作られます。

When creating a capacity provider, you can optionally enable managed scaling. When managed scaling is enabled, Amazon ECS manages the scale-in and scale-out actions of the Auto Scaling group. On your behalf, Amazon ECS creates an AWS Auto Scaling scaling plan with a target tracking scaling policy based on the target capacity value you specify. Amazon ECS then associates this scaling plan with your Auto Scaling group. For each of the capacity providers with managed scaling enabled, an Amazon ECS managed CloudWatch metric with the prefix AWS/ECS/ManagedScaling is created along with two CloudWatch alarms. The CloudWatch metrics and alarms are used to monitor the container instance capacity in your Auto Scaling groups and will trigger the Auto Scaling group to scale in and scale out as needed.

Amazon ECS Cluster Auto Scaling - Amazon Elastic Container Service

上記引用内容にもあるように、

  • ECS はその Auto Scaling Group にインスタンスがいくつ必要かを表現する CloudWatch metrics を投稿する
  • metrics がスケールイン/アウトする基準値を超えたとき、(CloudWatch alarm を経由して) AWS Auto Scaling がインスタンスをスケールイン/アウトさせる

という挙動を示します。これによって、たとえばインスタンスが1台も存在しない場合であっても ECS からの要求ベースでインスタンスを起動することができるようになっています。

後者のスケールイン保護に関しては、 EC2 Auto Scale Group に存在する、インスタンスのスケールインからの保護機能を利用する、とされています。タスクの実行されているインスタンスを保護状態にすることでそれらがスケールインから防ぎ、タスクの実行されていない = 保護状態でないインスタンスからスケールインされていくようにする機能であるように、ドキュメントからは読み取れます。

docs.aws.amazon.com

For Managed termination protection, choose your managed termination protection option. When managed termination protection is enabled, Amazon ECS prevents Amazon EC2 instances that contain tasks and that are in an Auto Scaling group from being terminated during a scale-in action. Managed termination protection can only be enabled if the Auto Scaling group also has instance protection from scale in enabled. Managed termination protection is only supported on standalone tasks or tasks in a service using the replica scheduling strategy. For tasks in a service using the daemon scheduling strategy, the instances are not protected.

Amazon ECS Cluster Auto Scaling - Amazon Elastic Container Service

この機能に関して歯切れが悪いのは、筆者が検証した範囲ではスケールインが機能していることを確認できなかったからです。


何か設定を誤っているのかもしれないのでもう少し調査はしていきたいと思っています。

ECS Capacity Provider

さて、ここまで三つのうちふたつを確認しましたが、このどちらも実際の設定は ECS Capacity Provider 経由で行うようになっていました。ここでその ECS Capacity Provider を確認してみましょう。

whats-new における機能の紹介を引用すると、 ECS Capacity Provider はコンテナの実行 capacity を管理する新しい方法である、として定義されています。また、特に「アプリケーションに」 capacity の利用方法を定義させるためのものである、とされていることに注目しておきたいです。 re:Invent での本機能の開発者セッションでは、"application first" であること、この機能によって実際にインスタンスが実行されているインフラストラクチャに関心をもたなくてよくすることがねらいである、という言及がありました。ここだけ re:Invent に行ってきました感が出ます。

Capacity Providers are a new way to manage compute capacity for containers, that allow the application to define its requirements for how it uses the capacity. With Capacity Providers, you can define flexible rules for how containerized workloads run on different types of compute capacity, and manage the scaling of the capacity. Capacity Providers improve the availability, scalability, and cost of running tasks and services on ECS.

Amazon ECS Capacity Providers Now Available

ECS Capacity Provider では、あるクラスタにおける EC2 Auto Scaling Group や Fargate / Fargate Spot のようなコンテナ実行環境を提供する概念を Capacity Provider として抽象化します。また、実際にどの Capacity Provider をどういう配分で利用するのかを表現したものが Capacity Provider Strategy です。 ECS サービスにこの Capacity Provider Strategy を設定することで、 ECS サービス側から Capacity Provider をどう使うのか、ひいてはどのようなコンテナ実行環境で実行するかを指定することができます。

f:id:astj:20191210031452p:plain
ざっくりとしたイメージ図です

上記のイメージ図では Strategy はふたつの Provider の間の比例として表現しましたが、実際は1~6個の Provider に baseweight のふたつのパラメータを指定することで、タスクの起動数を比例配分します。

利用方法1: Fargate / Fargate Spot における利用

Strategy が実際にどうなるかは、 Fargate と Fargate Spot で検証された Developers.IO さんのエントリを見ていただくとイメージしやすいように思います。 たとえば "最低4つは Fargate で起動して、それ以上は Fargate と Fargate Spot を 1:1 で起動する" であれば、Fargate と Fargate Spot の (base, weight) はそれぞれ (4, 1)(0, 1) になります。また、 Fargate でのみ起動したいのであれば Fargate のみを選択した Strategy をつくればよい、ということになります。

dev.classmethod.jp

新しく作成した ECS クラスタには予め FARGATE と FARGATE_SPOT のふたつの Capacity Provider が定義された状態になっているため、これらを希望のバランスで配分する Capacity Provider Strategy を指定することで Fargate Spot の利用範囲をコントロールできます。

f:id:astj:20191210050545p:plain

また、この Capacity Provider Strategy はサービスやタスク実行のほかに、クラスタそのものにもデフォルトの Strategy として定義することができます*2。これにより、そのクラスタ上で新しくサービスを作ったりタスク実行を行ったりする際のデフォルト値として提供することもできます。たとえば Fargate Spot を利用する予定のないクラスタであれば、 Fargate のみを利用する Strategy を予め設定しておくとよいでしょう。

利用方法2: ECS Cluster Auto Scaling における利用

EC2 を使用するクラスタの場合でも Capacity Provider を利用することができます。前述したように、 ECS Cluster Auto Scaling は Capacity Provider によって実現されているため、 ECS Cluster Auto Scaling を利用したい場合は必然的に Capacity Provider を利用することになります。

EC2 の場合、 Auto Scaling グループ単位で Capacity Provider を登録することになります。以下にコンソール上のスクリーンショットを掲載します。ここでは設定方法の詳細には立ち入りませんが、 ECS Cluster Auto Scaling のそれぞれの機能に対応する "Managed scaling" と "Managed termination protection" を使うかどうかを設定できます。

f:id:astj:20191210041300p:plain

また、この設定画面からも推察できるように、ECS Capacity Provider を利用するのに ECS Cluster Auto Scaling の設定は必須ではありません。旧来の EC2 Auto Scaling Group のスケーリングポリシーを利用したまま、 Capacity Provider Strategy による配分機能のみを利用することも可能です。

まとめ

なんだか書き始めた時の予定よりもだいぶごっちゃりしてしまったのだけど、これらを整理すると以下のような感じでしょう:

  • ECS Capacity Provider で ECS クラスタにおけるコンテナ実行環境の調達手法をクラスタごと、あるいはサービスごとに設定することができる
  • Fargate Spot では、実行が停止されるかもしれないが安い価格で Fargate タスクを実行することができる
    • あるタスクにおける Fargate と Fargate Spot の利用配分は、 Capacity Provider 経由で行うことができる
  • ECS Cluster Auto Scaling では、 ECS Capacity Provider に EC2 Auto Scaling Group を登録することで以下のことが実現できる
    • Managed Scaling では、 ECS サービスやタスクの側から EC2 Auto Scaling Group のスケールを要求することができる
    • Termination Protection は、追加の実装なしに ECS インスタンスを安全にスケールインできるようにすることを意図している

どの機能もこれからどんどん機能拡張されていくので細かい仕様や挙動は今後変化していくと思われますが、これらの関係性を踏まえておくとそれぞれの機能がどんなものかわかりやすくなるのではないでしょうか。

その他考慮事項

「整理」という本稿の目的とは外れますが、現時点におけるその他の制約などについて確認したものをいくつか掲載しておきます。

ひとつの Capacity Provider Strategy に EC2 と Fargate を混ぜることはできない

Fargate と Fargate Spot を混ぜたり、 EC2 同士でことなる Auto Scaling Group を混ぜることは勿論できますが、それらの垣根を越えて混ぜることはできない、とのことです。

A cluster may contain a mix of both Auto Scaling group capacity providers and Fargate capacity providers, however when specifying a capacity provider strategy they may only contain one or the other but not both.

Amazon ECS Cluster Capacity Providers - Amazon Elastic Container Service

サービス実行において、 Capacity Provider Strategy の "base" は考慮されない

まあまあ大事なことのような気はしますが、何にせよいまのところはそういうことのようです。

When you specify a capacity provider strategy, the base value is only supported when running tasks. When creating a service, the capacity provider strategy base parameter is not supported.

Amazon ECS Cluster Capacity Providers - Amazon Elastic Container Service

Web コンソールからの操作はハマりやすく、いまのところは aws cli から操作した方がよい

本文中でもちょっと触れたのだけど、 Capacity Provider Strategy の作成や変更周りは Web コンソールから行えない操作がまだ多いようでした。Web コンソールとヘルプと aws ecs help を行き来しながら試すことになります。

アドベンドカレンダー

さて、アドベントカレンダーの翌日 (12/10) 担当は id:koudenpa さんです。ぼくが遅刻した結果、既にエントリが投稿されているのですぐに読むことができて便利ですね!

koudenpa.hatenablog.com

*1:GCE のプリエンプティブルインスタンスを見慣れた人たちからすれば、固定価格であること自体は驚くべきことではないのかもしれませんが…

*2:というか 2019/12/10 時点ではむしろ Web コンソールからはクラスターのデフォルトとしてしか Strategy を作ることができない。 API / aws-cli からはできる