ECSでEFSを使いこなすための一歩としてEC2ベースでのCPUとメモリ設定にトライしてみた

初めてECSでEC2ベースの操作を行う際、壁の一つになると思われるCPUとメモリの扱いについてまとめてみました。
2019.05.30

はじめに

FargateではEFSが使えないけど、EC2だとリソース管理が面倒。どうしよう

と、Fargateの手軽さに魅力を感じた上で悩まれる方は少なからず居られるものだと思います。

ECSからマウント経由で外部ファイルにアクセスしたい場合は自ずとEC2が手段として上がってきます。Fargateにてイメージファイル内にgitやboto3等で外部から取り込む術を作り込む手もありますが、動作検証が茨の道であることは間違いありません。

EC2になくてFargateにある大きな特徴は、リソース管理がフルマネージドという点です。言い換えればリソース管理さえ覚えれば手立てはあるはずです。

今回は最初の壁になると個人的に思っている CPUメモリ の扱いについて、調べながら只管繰り返した記録を元にまとめてみました。

当記事をオススメしたい方

以下のような悩みを抱えておられる方向けです。「ワタシECSチョトデキル」的な人には物足りないと思います。

  • タスク定義でのメモリCPU指定がよくわからない
  • コンテナでのメモリ制限CPUユニット数がよくわからない

ECS(EC2)のタスク定義におけるメモリとCPU

管理コンソールでタスク定義を行う際に、恐らく壁となるのは以下の4点でしょう。

  • タスクサイズ → タスクメモリ (MiB)
  • タスクサイズ → タスク CPU (単位)
  • タスクサイズ → コンテナの定義 → メモリ制限 → ハード制限
  • タスクサイズ → コンテナの定義 → メモリ制限 → ソフト制限
  • タスクサイズ → コンテナの定義 → CPU ユニット数

タスクメモリ、タスクCPU

公式ドキュメントには以下の通りに記載されており、EC2を利用する場合は空白で特に問題ありません

タスク定義の登録時に、タスクに使用される CPU とメモリの合計量を指定できます。これは、コンテナ定義レベルの cpu および memory の値とは異なります。EC2 起動タイプを使用する場合、これらのフィールドはオプションです。

ハード制限(memory)

コンテナ毎に適用されるハードウェアでのメモリ制約です。このメモリを越えると強制終了となります。

管理コンソールでの初回フォーム入力時に迷う場合は

ECS ではウェブアプリケーション用に 300 〜 500 MB から始めることをお勧めします。

とあるように、余裕を持って500MBあるいはそれ以上の指定が無難のようです。

ソフト制限(memoryReservation)

システムメモリ競合時に維持されるメモリ上限です。ただし、状況に応じてハード制限(設定されている場合)かインスタンス自体の利用可能上限まで消費します。

つまり、以下のような構図となります。

memory ( <= memoryReservation ) <= instance memory

memory 及び memoryReservation については公式ドキュメントに詳細があります。

EC2タイプを使う前提で上記ドキュメントを読む場合に気をつけるべき点は、両方とも

必須: いいえ

となってはいるものの

EC2 起動タイプを使用するタスクにコンテナが含まれる場合、コンテナの定義で memory と memoryReservation の一方または両方にゼロ以外の整数を指定する必要があります。

となっているところです。

CPU ユニット数

特に前提知識がない場合は当てるべき数値の基準がつかみにくい代物です。決めかねる場合は、以下ページに掲載されているFargateでの動作ベースが恐らく無難でしょう。

CPU value Memory value (MiB)
256 (.25 vCPU) 512 (0.5GB), 1024 (1GB), 2048 (2GB)
512 (.5 vCPU) 1024 (1GB), 2048 (2GB), 3072 (3GB), 4096 (4GB)
1024 (1 vCPU) 2048 (2GB), 3072 (3GB), 4096 (4GB), 5120 (5GB), 6144 (6GB), 7168 (7GB), 8192 (8GB)
2048 (2 vCPU) Between 4096 (4GB) and 16384 (16GB) in increments of 1024 (1GB)
4096 (4 vCPU) Between 8192 (8GB) and 30720 (30GB) in increments of 1024 (1GB)

クラスターでのEC2インスタンスタイプがm4.largeの場合、メモリは 8GB となり、CPUユニットは最低でも 1024 以上となっています。

あとはCloudWatchでのモニタリング結果アプリケーションの動作状況に応じてチューニングしていきましょう。

なお、公式ドキュメントによると、インスタンス毎のCPUユニット上限値については以下の計算で求められます。

Amazon EC2 Instances 詳細ページのインスタンスタイプに一覧表示されている vCPU 数に 1,024 を乗算して、Amazon EC2 インスタンスタイプごとに使用可能な CPU ユニットの数を判断できます。

クラスターで初期指定となっている m4.large の場合 vCPUは 2 であり、ユニット数上限は 2048 となります。

コンテナ定義に複数追加するとインスタンスのリソースが足りない場合

アプリケーションの構成にもよりますが、以下の3つの手段が検討できると思います。

  • コンテナ毎の定義値を減らす
  • インスタンスを高性能なものに変える
  • タスクを分けてコンテナ定義を分散させる

コンテナへのメモリ割当によるインスタンス上でのメモリ変動を知りたい

ナレッジセンターでの以下の記事が参考になります。掲載されている手順に沿って操作してみてください。

まとめ

「設定はFargateのフルマネージドな前提で進めたいけど、外部ファイルをどぎゃんかせんといかん」

という状態になり、弊社SAに相談した末にEC2ベースが無難であると結論付きましたが、

「そういやリソース指定を手動でしたことがなかった

と気がついて四苦八苦した結果です。

最終的にはインスタンスタイプをt3.xlargeにして、必要なコンテナを全部のせた形で動作させてみました。(明らかに余剰スペックすぎるとは思いますが…)

EC2ベースでのECSにおけるメモリとCPUについて迷う人の参考になれば幸いです。