2017年版 負荷テストツールTsungをAWS EC2 AmazonLinuxでクラスタリング構築

Erlang製 負荷テストツールTsung。
JMeterとかよりパフォーマンスがよいとのことで初めて利用しました。

環境構築するにあたって、こちらが非常に参考になったんだけど、いくつか苦労したので自分なりにまとめました。
postd.cc
george-osd-blog.herokuapp.com

概要

  • Erlang: OTP19.3
  • Tsung: 1.6.1
  • OS: AmazonLinux 2017.03.0 (HVM), SSD Volume Type
  • EC2: c4.2xlarge 3台構成(そのうち1台がマスター兼スレイブ)
  • まず1台単体でTsungが動作するところまで構築し、この1台を複製(AMI)して残り2台を設定していく流れ

AWS VPC作成

VPC

  • ネームタグ: tsung(※任意)
  • CIDR: 10.0.0.0/16

で作成

サブネット

で作成

インターネットゲートウェイ

  • ネームタグ: tsung(※任意) をつけて作成
  • VPCにアタッチ」で上記で作成したVPCと関連づける

ルートテーブル

  • VPCと関連づいているルートテーブルが既に作成されているはず
  • これを選択し、画面下部の「ルート」タブ > 「編集」し、グローバル0.0.0.0/0からのルートを追加



AWS EC2作成

セキュリティグループ

  • セキュリティグループ名: tsung(※任意)
  • VPC: 先程作成したVPCを指定
  • インバウンド: SSH TCP 22 マイIP
  • インバウンド: カスタムTCPルール TCP 0 - 65535 10.0.0.0/24

自分のPCからSSH接続できるようにと、クラスタリングしたときにTsungサーバ同士がVPCローカルエリア内で接続し合えるようにという意図です。

インスタンス

  • Amazonマシンイメージ: Amazon Linux
  • インスタンスタイプ: c4.2xlarge
  • インスタンス数: 1
  • ネットワーク: 先程作成したVPCを指定
  • 自動割り当てパブリック IP: 有効化
  • セキュリティグループの設定: 先程作成したセキュリティグループを指定
  • キーペア名: tsung(※任意)

で作成(他項目はデフォルトで作成しました)

キーペアは新しくても、既存のものでもOKです。
本項では、ダウンロードした鍵tsung.pemとして説明をしていきます。

こちらを参考にさせていただきました。
http://qiita.com/hiroshik1985/items/f078a6a017d092a541cf

Tsungサーバ構築

EC2接続

tsung.pemをローカルPC(Mac想定)の~/.sshに格納

mv tsung.pem ~/.ssh/
chmod 600 ~/.ssh/tsung.pem

EC2説明にあるIPv4パブリックIPを指定して接続

$ ssh -i ~/.ssh/tsung.pem ec2-user@xxx.xxx.xxx.xxx

費用を抑えるためにEC2を停止し翌日とかに起動した場合、IPv4パブリックIPは変わるので気をつけてください。

Tsung用OSカスタマイズ

gccインストール
$ sudo yum update -y
$ sudo yum install gcc
limits.conf変更
sudo vi /etc/security/limits.conf

*  soft  nofile  1024000
*  hard  nofile  1024000

SSHログアウトして、AWS EC2管理画面から再起動して、変更が反映されているか確認

$ ulimit -n

1024000
sysctl.conf追加

以下の設定を末尾に追加

$ sudo vi /etc/sysctl.conf

# General gigabit tuning
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

# This gives the kernel more memory for TCP
# which you need with many (100k+) open socket connections
net.ipv4.tcp_mem = 50576 64768 98152

# Backlog
net.core.netdev_max_backlog = 2048
net.core.somaxconn = 1024
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_syncookies = 1

追加が反映されているか確認

$ sudo sysctl -p

Erlangインストール

yum installだとバージョンが古かったのでダウンロードしてきてインストール

$ sudo yum install ncurses ncurses-devel openssl openssl-devel gcc-c++ unixODBC unixODBC-devel fop *openjdk-devel inotify-tools
$ sudo yum --enablerepo=epel install inotify-tools
$ mkdir ~/work && cd ~/work
$ wget http://erlang.org/download/otp_src_19.3.tar.gz
$ tar zxvf otp_src_19.3.tar.gz
$ cd otp_src_19.3
$ ./configure
 # wxWidgets not found, wx will NOT be usable
 # というメッセージが表示されますが、GUIを使わないなら無視してよいっぽいです。
$ make
$ sudo make install
$ erl -version

Tsungインストール

$ cd ~/work
$ sudo yum groupinstall -y "Development Tools"
$ sudo yum install -y perl perl-devel perl-Template-Toolkit
$ git clone https://github.com/processone/tsung
$ cd tsung
$ ./configure
$ make
$ sudo make install
$ sudo yum install -y gnuplot
$ tsung -v

秘密鍵

EC2へ接続するための秘密鍵を、ローカルPCからEC2へアップロード.

$ cd ~/.ssh
$ scp -i ~/.ssh/tsung.pem ~/.ssh/tsung.pem ec2-user@xxx.xxx.xxx.xxx:/home/user/ec2-user/.ssh/

EC2にSSH接続し

$ mv ~/.ssh/tsung.pem ~/.ssh/id_rsa

ローカルホストにSSH接続できることを確認
$ ssh localhost

EC2には既に公開鍵が設定されてるので秘密鍵も設定すると
複製したEC2でクラスタリングしたとき、お互いに容易にSSHできる寸法。

Tsung1台テスト

構築できたこの1台でTsungが動作するかテストします

テストシナリオファイル

以下のような、stress-test.xmlファイルをローカルPCで準備.

<?xml version="1.0"?>
<!DOCTYPE tsung SYSTEM "/usr/local/share/tsung/tsung-1.0.dtd">
<tsung loglevel="notice" version="1.0">
  <clients>
    <client host="localhost" weight="1" cpu="8" maxusers="5000"/>
  </clients>
<servers>
  <server host="test.server.xx" port="443" type="ssl"></server>
</servers>
  
  <load>
   <arrivalphase phase="1" duration="2" unit="minute">
     <users maxnumber="3000" arrivalrate="100" unit="second"></users>
   </arrivalphase>
  </load>

  <options>
   <option type="ts_http" name="user_agent">
    <user_agent probability="80">Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.8) Gecko/20050513 Galeon/1.3.21</user_agent>
    <user_agent probability="20">Mozilla/5.0 (Windows; U; Windows NT 5.2; fr-FR; rv:1.7.8) Gecko/20050511 Firefox/1.0.4</user_agent>
   </option>
  </options>

 <sessions>
  <session name="stress-test" probability="100" type="ts_http">

    <for from="1" to="10" var="i">
      <request subst="true">
        <http url="/stress"
          contents="team=kamesan&amp;count=987"
          content_type="application/x-www-form-urlencoded" method="POST">
        </http>
      </request>
    </for>

  </session>
 </sessions>
</tsung>
  • 8CPUを利用したlocalhost
  • 秒間100ユーザづつ、3000ユーザに達するまで増加
  • テストサーバ(https)に3000ユーザが10回ポストする

というシナリオです.
先頭のtsung-1.0.dtdパスが間違っていると(インストールしたサーバ環境に準じて無いと)動かないので注意が必要です。

$ scp -i ~/.ssh/tsung.pem stress-test.xml ec2-user@xxx.xxx.xxx.xxx:/home/ec2-user/work

テスト実行

実行

ログフォルダつくってTsungテスト実行

$ cd ~/work
$ mkdir logs
$ tsung -l logs -f stress-test.xml start

Creating local Tsung directory /home/ec2-user/.tsung
Starting Tsung
Log directory is: /home/ec2-user/work/logs/20170505-0532
[os_mon] memory supervisor port (memsup): Erlang has closed
[os_mon] cpu supervisor port (cpu_sup): Erlang has closed
グラフ作成
$ cd logs/20170505-0532
$ /usr/local/lib/tsung/bin/tsung_stats.pl --stats tsung.log

creating subdrectory data
creating subdrectory gnuplot_scripts
creating subdrectory images
warn, last interval (9) not equal to the first, use the first one(10)
No data for Bosh
No data for Match
No data for Event
No data for Async
No data for Errors
圧縮
$ cd ..
$ tar -zcvf log.tar.gz 20170505-0532
ダウンロード

ローカルPCから圧縮したtarファイルをダウンロード

scp -i ~/.ssh/tsung.pem ec2-user@xxx.xxx.xxx.xxx:/home/ec2-user/work/logs/log.tar.gz ~/work/logs

graph.htmlやreport.htmlでテスト応答速度、エラー、TsungサーバのCPU使用率等々が確認できます。

EC2複数台構成

AMI作成

AWS EC2管理画面から構築したTsungサーバを
アクション > イメージ > イメージの作成 でAMIを作成する

AMI複製

AMIからスレーブサーバとしてクラスタリングしたい数だけ複製します。
AWS EC2管理画面で
インスタンスの作成 > マイAMI > 作成したAMI
を選択し、以降の設定は1号機同様に指定し作成します。

各スレーブサーバ設定

knownhosts

1号機のlocalhost設定を削除

$ rm -rf ~/.ssh/knownhosts
$ ssh localhost

 
 

全サーバ設定(1号機もです)

Firewall解除

各サーバ間通信するためにFirewallを解除

$ sudo chkconfig iptables off
$ sudo /etc/init.d/iptables stop
hosts設定

hostsに各TsungサーバのプライベートIPを追加

$ sudo vi /etc/hosts
<tsung1_Private_IP> tsung1
<tsung2_Private_IP> tsung2
<tsung3_Private_IP> tsung3

$ sudo /etc/rc.d/init.d/network restart

tsung1を1号機(マスター兼スレーブ)とし、2,3号機も指定します。
 
 

マスターサーバ(1号機)設定

hostname設定

HOSTNAMEを書き換える

$ sudo vi /etc/sysconfig/network

HOSTNAME=tsung1

SSHログアウトして、AWS EC2管理画面から再起動して、変更が反映されているか確認

$ hostname

tsung1
なぜhostname設定するのか
$ erl -rsh ssh -sname foo -setcookie mycookie
(foo@tsung1)1> slave:start(tsung2,bar,"-setcookie mycookie").

foo@tsung1じゃなくてfoo@ip-10-0-0-7とかだと{error,timeout}になる。
{ok,bar@tsung2a}が帰ってくるようにhostnameの変更が必要。

SSH接続確認

SSHコマンドで確認

ssh tsung1
ssh tsung2
ssh tsung3

Erlangで確認

$ erl -rsh ssh -sname foo -setcookie mycookie

(foo@tsung1)1> slave:start(tsung2,bar,"-setcookie mycookie").
{ok,bar@tsung2}

(foo@tsung1)1> slave:start(tsung3,bar,"-setcookie mycookie").
{ok,bar@tsung3}

Tsung複数台テスト

テストシナリオファイル

以下のような、stress-test.xmlファイルをローカルPCで準備.
clientの部分をlocalhostから変更し、tsung1, 2, 3としました。

<?xml version="1.0"?>
<!DOCTYPE tsung SYSTEM "/usr/local/share/tsung/tsung-1.0.dtd">
<tsung loglevel="notice" version="1.0">
  <clients>
    <client host="tsung1" weight="1" cpu="8" maxusers="2000">
    	<ip scan="true" value="eth0" />
    </client>
    <client host="tsung2" weight="1" cpu="8" maxusers="2000"/>
    	<ip scan="true" value="eth0" />
    </client>
    <client host="tsung3" weight="1" cpu="8" maxusers="2000"/>
    	<ip scan="true" value="eth0" />
    </client>
  </clients>
<servers>
  <server host="test.server.xx" port="443" type="ssl"></server>
</servers>
  
  <load>
   <arrivalphase phase="1" duration="2" unit="minute">
     <users maxnumber="3000" arrivalrate="100" unit="second"></users>
   </arrivalphase>
  </load>

  <options>
   <option type="ts_http" name="user_agent">
    <user_agent probability="80">Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.8) Gecko/20050513 Galeon/1.3.21</user_agent>
    <user_agent probability="20">Mozilla/5.0 (Windows; U; Windows NT 5.2; fr-FR; rv:1.7.8) Gecko/20050511 Firefox/1.0.4</user_agent>
   </option>
  </options>

 <sessions>
  <session name="stress-test" probability="100" type="ts_http">

    <for from="1" to="10" var="i">
      <request subst="true">
        <http url="/stress"
          contents="team=kamesan&amp;count=987"
          content_type="application/x-www-form-urlencoded" method="POST">
        </http>
      </request>
    </for>

  </session>
 </sessions>
</tsung>

これを1台テストと同じように実行し結果が得られれば構築成功です!