電通総研 テックブログ

電通総研が運営する技術ブログ

ECS on Fargateを使って負荷テストを便利にした話

はじめに

こんにちは!フレックスタイム制度制度を存分に活用して、普段色々な時間に業務をしているXイノベーション本部・クラウドイノベーションセンターの石井大樹です。
今回、社内プロジェクトにて、負荷テストをテスト環境の構築からテストの実施までを担当しました。
このプロジェクトで開発した負荷テストの実行環境の評判がよかったことから、私の経験が皆さんの負荷テストに関する課題を解決する手助けになるのではないかと考え、この記事を書くことにしました。

前提

目的

読者に、クラウド上のコンテナオーケストレーションサービスで負荷テストを実行するメリットと重要性を理解してもらう

この記事の対象とする読者の方

  • 負荷テストのテスト実行計画中の方
  • 現状の負荷テスト実行環境を改善したい方
  • クラウドサービスでの負荷テストに関心がある方

前提知識

  • クラウドに関する基礎知識
  • コンテナ化の概念
  • 負荷テストの概念

注意

シナリオの作成の仕方・ウォームアップなど、負荷テスト自体の内容に関する知識を求める方は、期待した情報を得られない可能性があります。
この記事は、テストの実行環境に焦点をおいており、負荷テストの内容自体には焦点をおいていません。

テスト実行環境とは

本稿における負荷テスト実行環境とは以下の要素で構成されているものとします。

  • テストを実行するインフラストラクチャ
  • 負荷テストツール
  • テスト実施者がテストの実行から結果取得までに扱う必要のある全てのツール

従来の課題

このプロジェクトではいままで、EC2インスタンスを1台立て、そのインスタンスから手動でテストの実行からテスト結果の取得までを実施していました。
そのため、以下のような課題がありました。

  • 負荷の大きさがそのEC2インスタンスの1台の性能に依存し、一定以上の負荷をかけることができない。
  • テストの前処理・後処理など、一部の処理を直列で行う必要があり、その処理に時間がかかってしまう。
  • テスト実行からテスト結果の取得までの一連の流れが手動であり、時間がかかり、手順ミスが生じる恐れがある。
  • 起動時間でEC2インスタンスは課金されるので、手動で起動・停止の課金管理を行う必要がある。

上記のような課題を、これから紹介するテスト実行環境でテストを実施することで解決することができました。

負荷テスト環境の概要

テスト実行インフラ

実際にどのようなインフラでテストを実行したのかを紹介いたします。
以下がこの環境のアーキテクチャ図です。非常に単純な作りとなっています。
テストはECS on Fargate上のコンテナで実行され、それが終了するとコンテナはS3バケットへテスト結果を出力するようになっています。

ECS on Fargateを利用することで以下のようなメリットを得ることができました。

  • コンテナ数(タスク数)とコンテナごとのメモリ、CPUなどのリソースを定義することで、負荷が柔軟に指定可能に。
  • コンテナ数を増やして並列度を上げることで、前処理・後処理などの並列化可能な処理の完了時間を短縮
    • 例えば、テスト前のセットアップでは、実際にSeleniumをheadless modeで利用してブラウザ上でログインを行い、セッションの情報を取得するという処理を負荷に応じたユーザー数分実行していました。
      そのため、非常に多くの時間がセットアップでかかっていました。しかし、コンテナを複数台用意し並列化することで、多くの時間を節約することに成功しています。
  • コンテナ数を増やし並列度を上げることによる、掛けられる負荷の上限の大幅な引き上げ
  • テストの実行が完了したら自動的にコンテナ(タスク)が終了するため、手動での課金管理が不要に

以上で挙げたメリットは主な物であり、それ以外にも様々なメリットがあるかと思います。

負荷テストツール

負荷テストツールはGatlingを利用しています。Gatlingとは、OSS負荷試験フレームワークです。テストシナリオをJava, Scala, Kotlinで記述でき、結果レポートを自動生成してくれます。
この結果レポートはテスト時に収集したメトリクスをもとにして生成されています。用途によっては収集したメトリクスの記録されたファイルのみを出力し、レポートを生成しないこともできます。
この特性を利用し、複数のコンテナでテストを実行する際は、メトリクスファイルのみを各コンテナが出力するようにします。それを1つのディレクトリに収集し、Gatlingのレポートを生成するコマンドを利用することで、メトリクスを結合して1つのテストのレポートを生成してくれます。

参考

負荷テストの実行手順

この章では、ECS on Fargateを使用してテスト実施者がどのようにテストを実行し、結果を取得するかについて紹介します。
ECS on Fargateでのテスト実行と複数コンテナを用いた並列実施はメリットが多くある一方、コンテナ管理と結果処理の必要性が生じました。これに対応するためには、テスト実施者が環境に関する深い知識を持ち、多くの複雑なコマンドを含む手順に従う必要がありました。しかし、全てのテスト実施者が、深い知識にキャッチアップし、手順書に沿って多くの複雑なコマンドを実行するために労力を使うことはあるべき姿ではないと考えていました。テスト実施者はテスト結果に集中し、システム改善にリソースを注ぐべきだと考えているためです。
そこで、makeを利用し、コマンドをテスト実施者の関心の単位(テスト実行・テスト結果取得など)にまとめ上げることにしました。これにより、テスト実施者はテストの結果に集中できたことに加えて、従来の方法に比べて時間を節約し、手順ミスを大幅に減らすことができました。

1. 環境構築

テストを実行するために必要なmakeコマンドでは、様々なツールを利用しています。そのため、makeコマンドを含め、各ツールを利用するために環境構築が必要です。
どのようなツールを利用したかは、この記事の目的から逸れてしまうため扱いません。

2. テストの実行

テスト種別・負荷を指定してテストを実行します。
このプロジェクトではテストケースごとに、どのようにテストを実行するか(テストタイプ)を指定する必要がありました。
実際に利用したコマンドは以下です。
以下のコマンド例では、XXXというテストケースを、loadというテストタイプで2つのコンテナでそれぞれ50ユーザー分の負荷を掛けるよう指定して実行しています。

make run-task TEST_NAME=XXX CONTAINER_COUNT=2 USER_COUNT=50 TEST_TYPE=load

この例では、2 * 50で、100ユーザー分の負荷を掛けるように指示していることになります。

詳細は省略しますが、このコマンドでは主に以下のような処理を実行しています。

  1. コンテナの起動によるテストの実行
  2. テスト完了まで待機&テスト完了の検知
  3. コンテナから出力されたテスト結果の後処理

参考としてこのプロジェクトを例にすると、以下の3つのテストタイプを指定して実行する必要がありました。

  • load:通常の負荷テスト。10分間程、指定した負荷をかけ続ける
  • limit:限界テスト。非常に大きな負荷を短時間で掛ける
  • stress:ストレステスト。指定した負荷を長時間かけ続ける。

3. テスト履歴の取得

指定されたテストケース・テストタイプを指定することで、過去の履歴を取得できます。
このステップで出力された日時の情報を利用して、次のステップのテスト結果の取得を行います。
この例では、XXXというテストケースの、loadというテストタイプの、テスト結果の履歴を取得しています。

make list-logs TEST_NAME=XXX NUM=10 TEST_TYPE=load

実際の出力例

Here are the latest 4 of 4 entries:
1. 2023-11-21-17-52/
2. 2023-11-21-17-26/
3. 2023-11-13-23-23/
4. 2023-11-13-20-54/

4. テスト結果の取得

テストケース・テストタイプ・時間を指定することで、テスト結果を取得できます。
この例では、XXXというテストケースの、loadというテストタイプの、2023年10/08 12:44に実行されたテスト結果を取得しようとしています。

make generate-report TEST_NAME=XXX TEST_TIME=2023-10-08-12-44 TEST_TYPE=load

詳細は省略しますが、このコマンドでは主に以下のような処理を実行しています。

  1. 全コンテナの出力したテスト結果の結合
  2. 結合したテスト結果をレポート化し、ローカルへダウンロード

改善できる点

この環境は従来の実行環境と比較して、コスト・性能・安定性・利便性の向上を達成しました。
しかし、この実行環境を利用してテストを実施していった際に、こうしておけば良かった、改善すればもっと良いものになると考えた点もあります。
以下で、それらのうちの大きな2点を紹介したいと思います。

テスト実行元環境のコンテナ化

現在の環境では、テスト実施者はmakeコマンドを実行するために、make自体や様々な依存関係のインストールなどの環境構築が必要であり、一定の時間・労力を要しています。
実際、環境構築手順のドキュメントを用意し、他メンバーに環境構築を行っていただきましたが、ある程度の時間を要してしまっていました。
このような状態を解決するためには、テスト実行元環境(テスト実施者がテストを実行・結果の取得などを行う環境)のコンテナ化をすることで解決できます。
テスト実施者にはDocker Desktopを用意していただき、あとは必要に応じて、ローカルでイメージをビルドすればテストを実行可能な環境を作成できます。
これにより、現在と比較して環境構築のステップの労力を大幅に削減できると考えています。

テスト結果の静的webホスティング

現在の環境では実行したテストの実行結果を確認するには、ローカルにテスト結果を取り込み、テスト結果レポートの生成が必要です。また、この結果を他者と共有するには結果をzip化してフォルダを共有するか、レポートをGit管理して共有する必要がありました。
これは、あまり労力がかからないように感じますが、1日に何度も結果を共有する必要がある場合は非常に手間になります。
テスト結果の静的webホスティングを実現することで、結果の共有にはURLを共有するのみで良くなり、結果の確認・共有の手間が大きく削減できます。

まとめ

従来のテスト実行環境と比較しながら、今回のプロジェクトで作成した環境を紹介いたしました。
実施者の手順が複雑にならないようにする対応は必要ですが、ECS on Fargateを用いて負荷テストを行うことは、コスト・効率・柔軟性・正確性のどれをとっても非常に従来の環境に比べて強力です。
今回は、実際にプロジェクトで利用したサービスであるAWSのECS on Fargateを例にして紹介いたしました。しかし、これは、どのクラウドベンダーのコンテナオーケストレーションサービスを利用しても、同様のメリットを享受できます。
例えば、Google CloudのCloud Runがあります。また、Kubernetes上でテストを実行するためにAWSAmazon EKSや、Google CloudのGKEを使ってもよいでしょう。
これから負荷テストの実施を計画している方、現状の負荷テストを改善したい方々など、悩んでいる方々の参考に少しでもなったら幸いです。

おわりに

X(クロス)イノベーション本部 クラウドイノベーションセンターでは、新卒・キャリア採用問わず共に働いてくれる仲間を探しています。
本記事で紹介した私の働き方や、クラウドを中心とした業務にご興味をお持ちの方は、ぜひ採用ページよりご応募ください。

執筆:@taiki_ishii、レビュー:@kano.nanami
Shodoで執筆されました