【Docker】EC2インスタンスにJMeterを導入する【負荷試験】



## 概要

### やりたいこと
  - AWSのEC2インスタンス(Linux)にJMeterをdocker-composeで導入
  - jmxファイルを読み込んで負荷試験(実行できればとりあえずOK)

### やることリスト
- [EC2インスタンスを立ち上げる](#ec2インスタンスを立ち上げる)
- [Docker,dokcer-composeをインストール](#dockerdokcer-composeをインストール)
- [Jmeterを導入](#jmeterを導入)
- [jmxファイルを読み込めるようにする](#jmxファイルを読み込めるようにする)
- [実行してみる](#実行方法)
  - コンテナ経由で実行
  - ~~ローカルでの実行~~
- [スケールについて](#スケール)
- [4445ポートについて](#4445ポートについて)
- [終了方法](#終了方法)
- [おまけ](#コンテナ監視)(コンテナ監視ツール)

#EC2インスタンスを立ち上げる

AWSマネジメントコンソールよりEC2インスタンスを構築。手順は調べれば出てきますので割愛します。
スペックは**t2.micro**で立ち上げました(導入試験的に低スペで)


#Docker,dokcer-composeをインストール

立ち上げたEC2インスタンスにSSHログインし、以下のコマンドでDocker, docker-composeを導入していく。

```bash

## yum の更新 & dockerをインストール(セキュリティアップデート等はよしなに)
sudo yum update -y
sudo yum install -y docker

## docker サービスの起動 & グループ割り当て
sudo service docker start
sudo usermod -a -G docker ec2-user

## sudoする
sudo -i

## docker-composeをダウンロード
curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# docker-compose コマンドに実行権限付与
chmod +x /usr/local/bin/docker-compose

# sudo抜ける
exit

# docker-compose コマンドの実行確認
docker-compose --version
```


#Jmeterを導入

EC2インスタンス内に**jmeter**フォルダを作成。(フォルダ名は自由です)
フォルダ内にdocker-compose.ymlを作成。

今回はDockerHubで公開されてた[vinsdocker/jmmaster](https://hub.docker.com/r/vinsdocker/jmmaster/)を使わせてもらいます。

```yml
version: '3.5'
services:
  master:
    image: vinsdocker/jmmaster
    container_name: master
    tty: true
    hostname: master
    networks:
      - jmeter_net
  slave:
    image: vinsdocker/jmserver
    tty: true
    networks:
      - jmeter_net
networks:
  jmeter_net:
    name: jmeter_net
```

起動させてみましょう。

```bash
docker-compose up -d
```

起動の確認

```bash
$ docker-compose ps
     Name                   Command               State          Ports       
-----------------------------------------------------------------------------
jmeter_slave_1   /bin/sh -c $JMETER_HOME/bi ...   Up      1099/tcp, 50000/tcp
master           bash                             Up      60000/tcp
```

#jmxファイルを読み込めるようにする

ローカルのjmxファイルをリモートサーバーへ転送(同期)する場合

```bash
rsync -e "ssh" ~/転送したいパス/ファイル名.jmx  [ユーザー名@ホスト or ホストalias]:~/転送先パス/ファイル名.jmx
```

#実行方法

「[jmxファイルを読み込めるようにする](#jmxファイルを読み込めるようにする)」の項目でローカルからリモートへjmxファイルを転送しましたね。
今度はリモートサーバーの中のjmxファイルをリモートのコンテナ内へとコピーしなくてはなりません。
(本当はしなくてもいいのかも。。。何かいい方法あれば教えてください。。。)

```bash
## コンテナへファイルをコピー(コンテナ名は「master」になっているかと)
docker cp パス/ファイル名.jmx コンテナ名:/コンテナ内のパス/ファイル名.jmx

## 実行
docker exec -ti master /bin/bash /jmeter/apache-jmeter-3.3/bin/jmeter -n -t /コンテナ内のパス/ファイル名.jmx
```

~~実はローカル(Mac)でも実行が可能です。~~ 

```bash
## ローカルでの実行(GUIモードで起動する)
jmeter

## コマンドラインでの実行
jmeter -n -t パス/ファイル名.jmx
```

※ローカルのJmeter(Dockerではない方)が起動してたっぽい。。。

試しにローカル環境でdocker-composeで立ち上げたコンテナのJMeterを実行してみると、怒られました。

```bash

$ docker exec -ti master /bin/bash   /jmeter/apache-jmeter-3.3//bin/jmeter
================================================================================
Don't use GUI mode for load testing, only for Test creation and Test debugging !
For load testing, use NON GUI Mode:
   jmeter -n -t [jmx file] -l [results file] -e -o [Path to output folder]
& adapt Java Heap to your test requirements:
   Modify HEAP="-Xms512m -Xmx512m" in the JMeter batch file
================================================================================
```

#スケール

JMeterではMaster/Slave構成での負荷試験が実施できます。
さらに、DockerであればSlave用コンテナの拡張(Scale)も容易なので楽できそう！！


スケールするには、`docker-compose up -d`を実行する際にオプション指定をします。

```bash
## slaveのスケール
docker-compose up -d --scale slave=コンテナ数
```

試してみましょう

```bash
$ docker-compose up -d
Creating network "jmeter_net" with the default driver
Creating master         ... done
Creating jmeter_slave_1 ... done

$ docker-compose ps
     Name                   Command               State          Ports       
-----------------------------------------------------------------------------
jmeter_slave_1   /bin/sh -c $JMETER_HOME/bi ...   Up      1099/tcp, 50000/tcp
master           bash                             Up      60000/tcp          

$ docker-compose up -d --scale slave=2
master is up-to-date
Starting jmeter_slave_1 ... done
Creating jmeter_slave_2 ... done

$ docker-compose ps
     Name                   Command               State          Ports       
-----------------------------------------------------------------------------
jmeter_slave_1   /bin/sh -c $JMETER_HOME/bi ...   Up      1099/tcp, 50000/tcp
jmeter_slave_2   /bin/sh -c $JMETER_HOME/bi ...   Up      1099/tcp, 50000/tcp
master           bash                             Up      60000/tcp 
```

コンテナが指定したスケールのサイズに増えましたね。
これで、masterコンテナでJMeterを実行すると、各slaveコンテナで並列実行するようにできます。

ただ注意点として、各slaveコンテナはデフォルトで1GBのメモリ上限が設けられているようです。
そのため、スケールサイズに5を設定してslaveコンテナが5つに増えたとしても、
t2.microなどのメモリを1GB程度しか積んでいないサーバーで実行するとメモリ不足になり、まともな検証ができないようです。


#4445ポートについて

```
Waiting for possible Shutdown/StopTestNow/Heapdump message on port 4445
```

jmeter実行時にこのようなエラーが出て以降、何も出力されない状態が続いた場合、
リクエスト先サーバーの4445ポートの受け入れを許可してみてください。

#終了方法

```bash
docker-compose down
```

#コンテナ監視

dockerコンテナのリソース監視は[ctop](https://ctop.sh/)がおすすめです