Dockerで構築したBotを、AWS ECSを使って数百体起動させる【WebRTC負荷テスト用】

前回は、Selenium+Dockerを使って、WebRTCの負荷テスト用のBotを構築しました。今回は、AWSのECSというサービスを使って、このBotを数百体起動させてみます

Amazon Elastic Container Service(Amazon ECS)とは

Amazon Elastic Container Service (Amazon ECS) は、フルマネージド型のコンテナオーケストレーションサービスです。Duolingo、Samsung、GE、Cookpad などのお客様が ECS を使用して、セキュリティ、信頼性、スケーラビリティを実現するために最も機密性が高くミッションクリティカルなアプリケーションを実行しています。

https://aws.amazon.com/jp/ecs/

つまりECSを使うと、Dockerを使って構築したコンテナを、スケーラブルなAWSのリソース上で複数実行・管理できます

一般的にはWebサーバーやBatch処理などを実行することに用いられますが、下記四つの理由からBotを複数起動する用途にも適していると思います。

  • Bot一体あたりのリソースを柔軟に設定できる
  • Bot(コンテナ)数の変更が容易
  • Fargate Spotを使用することで、コストが節約できる
  • コストの計算がリソース(CPU+メモリ量)xコンテナ数x時間でわかりやすい

今回、私は200体のbotコンテナをECS上で稼働させることができました。
起動・停止も容易です。

手順

手順は大きく分けて4つ存在します。

  1. Docker ImageをECR(Elastic Container Registry)にPushする
  2. タスクを定義する
  3. クラスターを作成する
  4. サービスを作成する

システム全体の概要は下図のような感じです。

システム概要図

ローカルで作ったimageをAmazonのECRにPushし、それをECSのそれぞれのタスクがPullして使います。

Docker ImageをESRにpushする

AWS CLIを使用して、前回作成したBotのImageをECR(Elastic Container Registry)にPushします。
ECRはAWS上に用意できるプライベートなコンテナイメージレジストリです。
ECRを使用しなくてもDockerHubのプライベートリポジトリや、パブリックなリポジトリも使えます。(ただし認証がめんどくさそうです)

ECRを利用する場合は、アクセスキーが必要なので、このへんを参考に発行しておいてください。
また、AWS CLIをPCにインストールしていない方は、こちらからインストールしてください。

最初に、ECRのリポジトリを用意します。ECRのコンソールを開き、「リポジトリの作成」を選択し、案内に従ってリポジトリを作成してください。
この時、リポジトリを作成するリージョンが想定通りになっているか注意してください。

リポジトリを作成したら、AWS CLIを使ってBotのImageをECRにPushします。
ECRのコンソールから作成したリポジトリを選択すると、「プッシュコマンドの表示」ボタンから、Pushコマンドを表示させることができます。

基本的にはコマンドをそのまま実行すれば、ECRにImageをPushできます。

Unable to locate credentials. You can configure credentials by running "aws configure".と表示される場合は、アクセスキーによる認証ができていません。aws configureを実行して、アクセスキーを設定してください。

また、リポジトリのURLをメモしておいてください。タスク定義で使用します。
筆者の場合は<user_id>.dkr.ecr.<リージョン>.amazonaws.com/<リポジトリ名>になっていました。

タスクを定義する

実際に実行されるタスクを定義します。
タスク定義では主に、

  • タスクの起動タイプ(Fargate or EC2)
  • コンテナの定義(使用するimageや環境変数など)
  • タスクサイズ(CPUとメモリのサイズ)
  • IAMロール

などを設定します。
また、IAMロールには

  • タスクが使用するロール
    • タスクが他のサービス(Lambdaとか)にアクセスする場合必要
  • ECSがタスクを実行するためのロール
    • ECRからimageをpullし、実行するためのロール

の二つがあります。このうちECSがタスクを実行するためのロールであるecsTaskExecutionRoleは必須のため、事前に作成しておいてください。(アカウントが持っている権限によっては、タスク定義と同時に作成することも可能です)
作成方法はこちらを参照。

筆者は、下記のような構成でタスクを定義しました。

項目設定値
タスクの起動タイプFargate
タスクロール(タスクが使用するロール)なし
タスクメモリ0.5GB
タスクCPU0.25vCPU
コンテナの定義image(リポジトリのURL)と環境変数を設定

タスクの起動タイプにはメモリとCPUの組み合わせを細かく設定できる Fargateを選択しました。
インスタンスタイプによって決まるEC2とは違って、Fargateの場合は起動するコンテナに合わせて細かくメモリとCPUのスペックを設定できます。最小構成はメモリ0.5GB、0.25vCPUです。

筆者の場合は最小構成で十分でした。この辺は実際に動かしてみないと必要なリソース量がわからないため、EC2のインスタンスなどで試しに実行するなどして決めると良いと思います。

コンテナを定義するときのimageとして、メモしておいたECRのリポジトリURLを設定してください。
また、コンテナを定義するときに、コンテナ実行時の環境変数を設定することもできます。コンテナにパラメータを渡す場合はここで設定しましょう。
環境変数のタイプをValueFromに設定すれば、AWS Systems Manager経由で値を設定することも可能です。

クラスターを作成する

ECSのコンソールを開き、「クラスターの作成」を選択します。
「クラスターテンプレートの選択」画面が表示されるのでタスク定義でFargateを選択した場合は、ネットワーキングのみを選択してください。

その後クラスター名とVPC(仮想的なプライベートネットワーク)を作成するかを選択すれば、クラスターを作成できます。

サービスを作成する

ECSのコンソールを開き、作成したクラスターを選択します。
クラスター画面のサービスタブにて、「作成」ボタンを選択すると、サービスの作成ができます。

ここで、起動タイプにFargate Spotを使用する場合は、起動タイプを選択するのではなく必ず「キャパシティープロパイダー戦略への切り替え」を選択し、プロパイダーに「FARGATE_SPOT」を追加してください。

キャパシティープロパイダー戦略への切り替え

キャパシティープロパイダー戦略とは、複数のタスクを実行したときに、起動タイプの割合をどうするか定義する設定であり、例えばFARGATEとFARGATE_SPOTの割合を1:1にすることなどが可能です。
今回の場合、起動タイプはすべてFARGATE_SPOTにしたかったため、プロパイダーをFARGATE_SPOTだけにしてあります。

サービスではなくクラスターの設定で、デフォルトのキャパシティープロパイダーを設定することもできます。
この場合、クラスター詳細画面の「クラスターの更新」を選択して表示される画面で設定してください。

起動タイプをFARGATE_SPOTにした場合、コストは大幅に下がりますが、AWSによって強制的にタスクが中断される危険性があります。
実行するタスクにおいて問題がないか、十分に検討してください。

サービスの作成では、起動タイプのほかに

  • 使用するタスク定義
  • タスクの数
  • VPC
  • ロードバランサ
  • オートスケーリング

などが主に設定できます。

タスク(コンテナ)の数を設定できるので、ここで起動するBotの数を設定します。
(筆者の場合は200)

筆者の設定は下記の通り。

項目設定値
使用するタスク定義先ほど設定したタスク定義
タスクの数200
VPC事前に作成したVPC
ロードバランサなし
オートスケーリングしない

サービスを作成すると、自動的に指定した数のタスクが実行されます。
200も起動するコンテナがあると、すべて起動(RUNNING状態)になるまでに10分程度かかりました
停止する場合はサービスを削除してください。(スマートではないので何とかしたい)

費用について

今回データ転送はほとんど行わないものとして計算します。(つまりは純粋なコンピューティングにかかる料金)

ECSは純粋に使用した計算リソース量によって料金が決まるため、今回の場合はFargate Spotの料金計算になります。

Amazon ECS 向け Fargate Spot の料金

リージョン : アジアパシフィック(東京)

1 時間あたりの vCPU 単位 0.01567483USD
1 時間あたりの GB 単位 0.00171443USD

https://aws.amazon.com/jp/fargate/pricing/

よって、0.25vCPU 0.5GBのFargate Spotを200個起動させたときの一時間当たりの料金は、
(0.01567483 x 0.25 + 0.00171443 x 0.5) x 200 = 2.38796125USD/h = 101.05円/h
となります。

ちなみに、Fargate Spotではなく、Fargate を使った場合は325.96円/hになるので、Spotを使うことによってだいぶ節約できることがわかりますね。

まとめ

  • ECSを使って数百体のBotを起動させることができる
  • Fargate Spotを使えば安価

ただ、負荷テストをするのに、一々AWSのコンソールを操作するのは手間だし、ヒューマンエラーも起きそうなので、AWS CLIなどを用いて自動化したいところです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です