Carpe Diem

備忘録。https://github.com/jun06t

ECSのオートスケール戦略

概要

ECSはコンテナのスケールアウトとインスタンスのスケールアウトのタイミングが重要です。
よく起きる問題としては

  • インスタンスのスケールアウトが遅くてコンテナのスケールアウトも遅くなってしまう
  • しきい値が不適切でインスタンスがスケールアウトせず、コンテナがスケールアウトしたくてもできない

で、こういった事が起きないようにしないといけません。

スケールアウトの方針

対象 方針
インスタンス インスタンスの空きリソースがコンテナ1台分だけの状態がn分間続いたら
コンテナ コンテナの使用率がn%を超えたら

インスタンスもう1台もコンテナを追加するリソースがない状況になったら早めにスケールアウトします。
コンテナは一般的なやり方で使用率が高くなったらスケールアウトすればOKです。

スケールインの方針

対象 方針
インスタンス コンテナがn分間ずっと1台を下回ったら
コンテナ コンテナの使用率がn%以下の状態がm分続いたら

インスタンス1台もコンテナが載っていなければスケールインします。不要ですからね。 コンテナは一般的なやり方で使用率が低くなったらスケールインすればOKです。

具体的な設定

コンテナはCPUやメモリの使用率を使えばいいのであまり難しくありませんが、インスタンスはちょっと複雑です。
ここで利用するメトリクスがCPUReservationMemoryReservationです。

ECSではtask definitionでcpu, memory, memoryReservationといったパラメータであらかじめ使用するリソースを確保できます。
これらの数値はUtilizationと異なり確保した量なので、確保したリソース量を超えた使用量でなければ一定です。なのでコンテナ数の計算に向いています。

CPUUtilizationとCPUReservationの比較

f:id:quoll00:20171019193856p:plain

MemoryUtilizationとMemoryReservationの比較

f:id:quoll00:20171019193909p:plain

どちらのReservationも基本的に一定ですね。

スケールアウト

コンテナが増えた時のリソースの遷移

CPU Unitが2048で、そこで実行するコンテナのタスクのcpu割当が768だとします。この場合

コンテナ数 残りリソース CPU Reservation
1 1280 768 / 2048 = 37.5%
2 512 1536 / 2048 = 75%
3 -256 2304 / 2048 = 112.5%

と、3台目で枯渇してしまいます。つまり75%のときにはすでにインスタンスを増やさなければいけません。

算出式

ただこのような数値は環境によって異なるため、統一して算出できる数式が欲しいです。それが以下です。

Threshold=(1  Container ReservationTotal Capacity of a Single Container Instance)×100

※英語なのは日本語だとtexの表示が変になるためです。

先程の例で算出

今回のケースだと、

Threshold=(1  7652048)×100=62.5

62.5%インスタンススケールアウトのしきい値となります。
この設定にすれば先程の例でも

コンテナ数 残りリソース CPU Reservation スケールアウトするか
1 1280 768 / 2048 = 37.5% しない
2 512 1536 / 2048 = 75% する

と、コンテナが2台になったらスケールアウトしてくれるので3台めのコンテナも生成することができるようになります。

複数のサービスが混在する場合

先程の例は1サービスのみ考えればいい例ですが、複数のサービスが混在してcpu割当もそれぞれ異なるケースも当然あります。その場合は以下の方針で考えればいいです。

算出式

最もReservationの高いタスクを元に算出する、という方針です。

Threshold=(1  max(Container Reservation)Total Capacity of a Single Container Instance)×100

具体例

例えばcpu割当が

  • web-server: 256
  • batch-server: 512
  • proxy-server: 128

みたいなケースでは、最大であるbatch-server512を使います。

Threshold=(1  5122048)×100=75

75%になりました。これをしきい値として設定しておけば、どのコンテナであってもスケールできます。

web数 batch数 proxy数 残りリソース CPU Reservation スケールアウトするか
1 1 1 1152 896 / 2048 = 43.75% しない
1 2 1 640 1408 / 2048 = 68.75% しない
2 2 2 256 1792 / 2048 = 87.5% する

NG例

これがもしproxy-server128に合わせてしきい値を設定すると

Threshold=(1  1282048)×100=93.75

93.75%となり、

web数 batch数 proxy数 残りリソース CPU Reservation スケールアウトするか
1 1 1 1152 896 / 2048 = 43.75% しない
2 2 2 256 1792 / 2048 = 87.5% しない

と、残りリソースが256になってもインスタンスがスケールしないため、batchコンテナが次にスケールアウトしたくてもこれ以上増えることはできません
なので最もReservationの高いタスクを元に算出することが重要です。

スケールイン

インスタンスをスケールインしたいのはタスクによるコンテナが1つもない状態です。
ただecs-agentや監視用エージェントが動いているため、単純に0とか固定値にすることはできません。

算出式

なので最もReservationの低いタスクを元に算出する方針が良いです。

Threshold=min(Container Reservation)Total Capacity of a Single Container Instance×100

先程の例で算出

先程のweb, batch, proxyがある環境であれば、

Threshold=1282048×100=6.25

6.25%になります。

web数 batch数 proxy数 残りリソース CPU Reservation スケールインするか
2 2 2 256 1792 / 2048 = 87.5% しない
1 1 1 1152 896 / 2048 = 43.75% しない
0 0 1 1920 128 / 2048 = 6.25% しない
0 0 0 2048 0 / 2048 = 0%
(実際は他プロセスで0にはならないはず)
する

となります。問題なくスケールインできますね。

NG例

もしこれがwebを元に算出すると、

Threshold=2562048×100=12.5

12.5%しきい値になります。この場合

web数 batch数 proxy数 残りリソース CPU Reservation スケールインするか
2 2 2 256 1792 / 2048 = 87.5% しない
1 1 1 1152 896 / 2048 = 43.75% しない
0 0 1 1920 128 / 2048 = 6.25% する

となり、proxyが残っているのにサーバがシャットダウンしてしまうという事になります。

まとめ

ECSのインスタンスをスケールアウトする時は

Threshold=(1  max(Container Reservation)Total Capacity of a Single Container Instance)×100

スケールインする時は

Threshold=min(Container Reservation)Total Capacity of a Single Container Instance×100

で算出したしきい値で設定すると問題なくスケールできます。

ソース