ECS on EC2におけるCapacity Providerのメリット解説 

# はじめに

　[Ateam Lifestyle Advent Calendar 2020](https://qiita.com/advent-calendar/2020/ateam-lifestyle) の5日目はインフラエンジニアの@dayamaguchi1 が担当します。
　今回の記事はECS on EC2におけるAutoScaling手法の１つであるCapacity Providerについて、そのメリットを解説します。
　ちなみにCapacity Provider自体は１年前にリリースされている機能なので、割と今更感ではあります。

最終的なゴールは以下です。

* 過去のスケーリング戦略との違いを知る

説明しないことは以下です。

* Fargate関連全て
* Capacity Providerの全貌


# ECS on EC2の構成要素を先に解説

　ECS on EC2は既設のAWS機能を複数組み合わせて稼働させるサービスになります。触り始めた当初、理解に悩んだ部分があったので、事前に構成要素を説明します。

## ECS on EC2の構成要素

* ECS Cluster
    * 実行環境を束ねた仮想的な集合体
    * ECS Cluster自体にコストはかからず（Cloudwatchは別です）、ECS配下になったEC2に対して費用が計上される
    * 世間的にクラスタって言葉はcovid19になってしまいましたね。閑話休題
* タスク定義
    * ECSで動かすコンテナの定義
    * どんなイメージで動かすか、どれぐらいCPUとかメモリ使うかなどを決めておく
* EC2 Auto Scaling Group
    * EC2のスケールイン/アウト戦略を担う
    * EC2だけでも使えるけど、ECSにも利用されている
    * 起動するEC2は後述の起動設定or起動テンプレートから選択
* 起動設定（Launch Configuration）
    * EC2をスケールアウトするとき、どのような設定で起動させるかを定義する
        * AMI-IDとか、サブネットとか
* 起動テンプレート（Launch Template）
    * 起動設定の後継
    * 起動設定よりも高機能
        * 設定項目が多いので、EC2構築に慣れた人でないと少し大変
    * Fleetなどを選べたりするが、今回は割愛

# Capacity Provider解説

　Capacity Provider登場以前と以降でどのようにスケーリング戦略が変わったのか、比較して説明します。

## Capacity Provider以前のECSスケーリング戦略

[Capacity Providerは2019/12/3にリリースされたECS機能の１つです。]([リリースニュース](https://aws.amazon.com/jp/blogs/aws/aws-ecs-cluster-auto-scaling-is-now-generally-available/)
)

　Capacity Providerが追加されるまで、ECSのスケーリング戦略はECSのメトリクスやEC2のメトリクスをベースに設定していました。
　具体的には以下のようにルールを定めています。

* ECS ClusterのMemory Reservationを参照し、
    * 80%利用以上でスケールアウト（EC2を1台追加）
    * 30%以下でスケールイン（EC2を1台削除）

　安定稼働という意味では十分な設定なのですが、明確にデメリットを抱えています。
　それは、余剰インスタンスが増えやすいという点です。
　なぜかというと、Memory Reservationが30%~80%の値となるようEC2台数を調整しているためです。

極端な例で現実的ではないのですが、具体例をあげます。

* 前提
    * タスク１つのメモリサイズが600MB
    * EC2のメモリサイズは2000MBの１台
    * スケール戦略は上記例と同じく、80%以上でスケールアウト、30%以下でスケールインとする
* スケールアウトの挙動想定
    * タスクを３つ起動させると、タスクメモリの合計数は1800MB
    * 1800MBだと80%を超えているので、スケールアウトする
        * EC2が１台増えて、ECS Clusterのメモリ量が2000MBから4000MBに増大
        * 4000MBに対して1600MBの利用量であれば、40%の割合なので、EC2台数は安定
* メモリ使用量の実態
    * 1台のEC2が保持する2000MBに対して、実際には1600MBまでしか使えない
    * 台数にかかわらず、常に [(ECS Clusterのメモリ合計数) * 0.8]までしかメモリが扱えず、余分なコストを払い続ける可能性がある

　ECSではなくEC2目線でスケーリング戦略を定めることになるので、正しい配分でEC2を用意できないのが問題でした。


## Capacity Provierで問題解決

> ECSではなくEC2目線でスケーリング戦略を定めることになるので、正しい配分でEC2を用意できないのが問題でした。

　Capacity Providerの登場によって、これが改善されました。
　Capacity Providerを一言で説明すると、「要求したタスク数に応じた最適なインスタンス数を提供する」となります。
　スケーリング戦略は、タスクが要求したCPU、メモリサイズに対して、EC2が許容できるか否かで決まります。

　ここでも極端な具体例で説明します。

* 前提
    * Memory Reservationと同様
* スケールアウトの挙動想定
    * タスク３つ起動させると、タスクメモリの合計数は1800MB
        * EC2のメモリサイズは2000MB。タスク起動できるため、スケールアウトは発生しない
    * タスク4つ起動させると、タスクメモリの合計数は2100MB
        * EC2のメモリサイズは2000MBで100MB余るため、スケールアウトが発生する

Memory Reservationと比較して、とてもシンプルですし、最適なインスタンス台数で稼働できています。
とてもスマート。


## 注意事項

　上の解説は実は極端で、実際には上記の通りに必ずしも動くわけではないです。
　そもそも「最適な台数」と表現しますが、最適という言葉も語弊があって、何目線で見て最適なんだという話です。
　今回の最適は、「Memory Reservationベースのスケーリング戦略と比較し、より余剰台数を抑えている」という意味で最適という感じです。
　他にも、EC2側に余剰を残すため、タスクが利用できるEC2リソースの割合を決定するターゲットキャパシティや、各EC2にタスクをどう分配するかを決定するタスク配置戦略など、Capacity Providerは細かく設定でき、最終的なスケール戦略は設計者が決める必要があります。
　今回の解説はあくまでEC2のスケール戦略にフォーカスあてていますので、他にもタスク配分戦略、タスクが稼働しているEC2のスケールインを防止するマネージドターミネーション保護など、Capacity Providerでしかできない機能が盛りだくさんです。
　私の解説以上の機能については、[Amazon ECS クラスターの Auto Scaling を深く探る](https://aws.amazon.com/jp/blogs/news/deep-dive-on-amazon-ecs-cluster-auto-scaling/)を参照ください。
　ぶっちゃけていうと、このドキュメント読んで理解できれば私のこの記事は無用の長物です。
　さらにぶっちゃけて言うと、EC2の管理したくねぇ！って人はFargate使った方が良いです。

# 最後に

最後までお読みいただきありがとうございます。どなたかの助けになれば幸いです。
明日は@yuki0325のターンです。引き続き弊社アドベントカレンダーをお楽しみください。

以上