アイリッジ開発者ブログ

アイリッジに所属するエンジニアが技術情報を発信していきます。

負荷試験用JMeterクラスタをAWS上にさっと上げる

TL;DR

負荷試験時に活用できる、AWS上にJMeterクラスタを立てるテンプレートを作りましたので、ご利用下さい!!

はじめに

開発推進グループのbbrfkr(ビビリフクロウ)こと、斎藤です。

WebサイトやAPIの負荷試験をする際、皆様はどのようなツールを利用されていますでしょうか? シンプルにabコマンド? Web上からLoad Impactで行う手もあります…

私が担当しているプロジェクトではApache JMeterを利用しています。「ユーザの行動を想定するとこのAPIを叩いてから次にそのAPIを叩いて…」といったシナリオテス卜をXMLフォーマットでコード化しておくこともでき、またHTTPステータスコードやレスポンスタイム、スループットといった情報がまとめられたレポートも吐き出してくれるので、大変重宝しています。

JMeterではクライアント-サーバ構成でクラスタを組むことで、大規模な負荷試験を巨大なCPU・メモリリソースを一つ用意するのではなく、容易に調達可能なCPU・メモリリソースをたくさん用意することで実現することができます。しかし、複数のサーバを人が逐一用意していくのは効率的ではありません…

そこでJMeter ClusterをAWSに自動構築するコードを作成することにしました。折角なので他のプロジェクトや同様の悩みを抱えている方々の助けになればと思い、使い回しが可能なテンプレートの形にしてあります。

使い方

事前準備

以下のURLでコードを公開しておりますので、まずはコードをgit cloneしてください。

git cloneしたら、pipおよびpipenvコマンドで依存パッケージをインストールします。なお、pythonバージョンは3.8でのみ動作確認しております。

$ pip install pipenv
$ pipenv install
$ pipenv shell

次にリポジトリ直下で設定ファイルのサンプルをコピーします。

$ cp variables.yaml.sample variables.yaml

コピーした設定ファイルvariables.yaml内の変数に値を入力していきます。各変数の意味は以下の通りです。

変数名 説明
jmeter_region JMeterクラスタをデプロイするAWSリージョン
jmeter_vpc JMeterクラスタをデプロイするVPC
jmeter_subnet JMeterクラスタが所属するサブネットID
jmeter_allowed_ip JMeterクラスタに属するインスタンスにSSHする際の接続許可ソースIP(CIDRで記載。なおパブリックIPが付与されるかはVPCの設定に依存しますので、プライベートサブネットでご利用の場合は、生成されたインスタンスにアクセス可能な踏み台サーバのIPを指定して下さい)
jmeter_ami_id JMeterクラスタのインスタンスに利用するAMI ID (Amazon Linux 2で動作確認済み。RedHat系OSのみ利用可能)
jmeter_client_instance_type JMeterクライアント(サーバに負荷試験指示を出すインスタンス)のインスタンスタイプ
jmeter_server_instance_type JMeterサーバ(実際に負荷試験対象に負荷をかけるインスタンス群)のインスタンスタイプ
jmeter_key_pair JMeterクラスタのキーペア
jmeter_servers_count JMeterサーバの数
jmeter_install_version インストールするJMeterのバージョン(例: 5.2.1)
jmeter_heap_initial_size JMeterサーバの初期ヒープメモリサイズ (パラメータXmsに与えられます)
jmeter_heap_max_size JMeterサーバの最大ヒープメモリサイズ (パラメータXmxに与えられます)
jmeter_max_meta_space_size JMeterサーバのMetaspace領域の最大値 (パラメータXX:MaxMetaspaceSizeに与えられます)
jmeter_max_open_file オープン可能なファイル数の上限 (ulimit -nコマンドの引数に与えられます)

また、本コードは内部的にboto3を使用しますので、対象AWSアカウントに対するクレデンシャルを環境変数やAWS CLIのaws configureコマンドで予め与えておいてください。環境変数で与える場合はリポジトリ直下のファイル.env.sampleを以下のコマンドでコピーし、値を入力します。

$ cp .env.sample .env

その後、sourceコマンドで環境変数を読み込ませます。

$ source .env

以上で、JMeterクラスタをデプロイする準備は完了です。

JMeterクラスタの起動

依存パッケージと変数の準備が完了していれば、JMeterクラスタのデプロイは以下のコマンドを実行するだけです!

本コードではsceptretroposphereというツールを利用して、CloudFormationスタックを作成することでデプロイを実現しています。

$ sceptre --var-file ./variables.yaml launch cluster

デプロイし終わったJMeterサーバ群をデプロイするスタックを見ると、出力の欄にJMeter実行時に与えるremote_hostsプロパティが生成されているので、こちらをJMeter実行前にクライアントに設定すればサーバ群に接続して負荷試験を実施できます。

f:id:bbrfkr:20200116100740p:plain

負荷試験が終わったら…

負荷試験が完了しレポート等を取得して、JMeterクラスタが不要になった際は以下のコマンドでクリーンアップすることができます。

$ sceptre --var-file ./variables.yaml delete cluster

構成

構成というほど大した内容ではありませんが、本コードの実行と負荷試験実施をイメージした図を以下のとおり示しておきます。

f:id:bbrfkr:20200116121358p:plain

  1. sceptreコマンドを実行してJMeterクライアント用のStackとJMeterサーバ群用のStackを作ります
  2. JMeterサーバ群用のStackの出力からremote_hostsプロパティを読取り、JMeterクライアントに設定します
  3. 負荷試験シナリオを作成するか、既存シナリオをダウンロードし、JMeterクライアントに配置します
  4. jmeterコマンドにて負荷試験を実施し、負荷試験対象システムに負荷を掛けます

まとめ

負荷試験実施用のクライアントは、JMeterでそれなりの負荷をかけようとすると意外とスペックを要求されます。AWSなどのパブリッククラウドを利用することで一時的に多くのコンピュートリソースを手軽に用意することができ、試験が終わって不要になればそれらを迅速かつ簡単に破棄することができます。今回のようにリソースの用意と破棄を自動化すれば、さらに効率的に負荷試験を実施できますので是非お試しいただければ幸いです。