SoftLayerの無料ベアメタルでOpenStackの学習をする(16) - 第15章「動的に変化するシステムの自動テスト手法」

[前回はこちら](http://qiita.com/orz/items/232b650a19c97a6369fe)
***
#これはなに
[「OpenStackクラウドインテグレーション オープンソースクラウドによるサービス構築入門」](http://www.shoeisha.co.jp/book/detail/9784798139784)の実習をSoftLayerの無料ベアメタルで行う記録である。
![OpenStackクラウドインテグレーション オープンソースクラウドによるサービス構築入門](http://www.seshop.com/static/images/product/17681/L.png)

# 第15章 動的に変化するシステムの自動テスト手法

当章の支援ファイルは[こちら](https://github.com/josug-book1-materials/chapter15)。

## 15.1 本章で扱うテスト

### 15.1.1 負荷テストの目的

クラウドでは構成変更の自由度が高いので、どのような構成が期待する負荷に耐えるだけではなくコスト面から望ましいか検証が重要。
今回は Gatling でテストを自動化する。

### 15.1.2 機能テストの目的

OpenStackではアプリとインフラが密接に連携する。インフラ担当でも機能テストは重要。
今回は Selenium でテストを自動化する。

## 15.2 負荷テスト

この節のファイルは[こちら](https://github.com/josug-book1-materials/chapter15/tree/master/gatling)。

### 15.2.1 負荷テストツール:Gatling

Scalaベースの独自DSLでテストを書く。ScalaベースなのでJava環境が必要。作成されるindex.hmlを開くと結果がグラフになって表示される。

### 15.2.2 負荷テストの実施

lbs×1、web×1、app×1、dbs×1の構成を準備する。lbs以外は第11章のプレイブックを利用した。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=web create_sample_vm.yml
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=web create_sample_vm.yml
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=web create_sample_vm.yml
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=web create_sample_vm.yml
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=app create_sample_vm.yml
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=dbs create_sample_vm.yml
(venv)[ansible@step-server ~]$ ansible-playbook -i sample_app_inventory.py -e target=dbs install_sample_app.yml
(venv)[ansible@step-server ~]$ ansible-playbook -i sample_app_inventory.py -e target=app install_sample_app.yml
(venv)[ansible@step-server ~]$ ansible-playbook -i sample_app_inventory.py -e target=web install_sample_app.yml

[root@step-server 07]# function get_uuid () { cat - | grep " id " | awk '{print $4}'; }
[root@step-server 07]# export MY_DMZ_NET=`neutron net-show dmz-net | get_uuid`
[root@step-server 07]# nova boot --flavor standard.xsmall --image "centos-base" \
> --key-name key-for-internal --user-data userdata_lbs.txt \
> --security-groups sg-all-from-console,sg-web-from-internet \
> --availability-zone az1 \
> --nic net-id=${MY_DMZ_NET} \
> lbs01

[root@step-server ~]# export MY_LBS_IP=`nova show lbs01 | grep " dmz-net" | awk '{print $5}'`
[root@step-server ~]# echo $MY_LBS_IP
[root@step-server ~]# ssh -i key-for-internal.pem root@${MY_LBS_IP}

[root@lbs01 ~]# vi /etc/nginx/conf.d/lbs.conf
[root@lbs01 ~]# service nginx restart
[root@lbs01 ~]# exit

[root@step-server ~]# curl http://${MY_LBS_IP}
```

負荷テストを行う stress-test サーバーを作成する。[userdata_stress.txt](https://github.com/josug-book1-materials/chapter15/blob/master/gatling/userdata_stress.txt)に対して[このように](https://github.com/josug-book1-materials/chapter15/blob/master/gatling/01_boot_stress_vm.sh)起動する。
[userdata_stress.txt](https://github.com/josug-book1-materials/chapter15/blob/master/gatling/userdata_stress.txt)では、Javaの導入、Gatlib自体とテストの導入・設定、nginxの導入・設定が行われる。

<pre>
[root@step-server ~]# cp chapter15/gatling/userdata_stress.txt .
[root@step-server ~]# MY_DEFAULT_NET=`neutron net-show work-net | get_uuid`
[root@step-server ~]# nova boot --flavor standard.small \
> --image "centos-base" \
> --key-name key-for-internal --user-data userdata_stress.txt \
> --security-groups sg-all-from-console,sg-web-from-internet \
> --availability-zone az1 \
> --nic net-id=${MY_DEFAULT_NET} stress-test
+--------------------------------------+----------------------------------------------------+
| Property                             | Value                                              |
+--------------------------------------+----------------------------------------------------+
| OS-DCF:diskConfig                    | MANUAL                                             |
| OS-EXT-AZ:availability_zone          | nova                                               |
| OS-EXT-STS:power_state               | 0                                                  |
| OS-EXT-STS:task_state                | scheduling                                         |
| OS-EXT-STS:vm_state                  | building                                           |
| OS-SRV-USG:launched_at               | -                                                  |
| OS-SRV-USG:terminated_at             | -                                                  |
| accessIPv4                           |                                                    |
| accessIPv6                           |                                                    |
| adminPass                            | DZd3g63pXncb                                       |
| config_drive                         |                                                    |
| created                              | 2015-04-04T01:52:59Z                               |
| flavor                               | standard.small (101)                               |
| hostId                               |                                                    |
| id                                   | a538d57b-c547-4270-9af1-58503cfcf3af               |
| image                                | centos-base (098f948e-e80b-4b1a-8a46-f8d2dd57e149) |
| key_name                             | key-for-internal                                   |
| metadata                             | {}                                                 |
| name                                 | stress-test                                        |
| os-extended-volumes:volumes_attached | []                                                 |
| progress                             | 0                                                  |
| security_groups                      | sg-all-from-console, sg-web-from-internet          |
| status                               | BUILD                                              |
| tenant_id                            | 106e169743964758bcad1f06cc69c472                   |
| updated                              | 2015-04-04T01:52:59Z                               |
| user_id                              | 98dd78b670884b64b879568215777c53                   |
+--------------------------------------+----------------------------------------------------+
</pre>

外部から stress-test にアクセスできるようにExt-NetのFloating IPを割り当てる。

<pre>
[root@step-server ~]# neutron floatingip-create Ext-Net
Created a new floatingip:
+---------------------+--------------------------------------+
| Field               | Value                                |
+---------------------+--------------------------------------+
| fixed_ip_address    |                                      |
| floating_ip_address | 192.168.100.139                      |
| floating_network_id | 36733654-35d1-47c9-9942-dab9400c52f0 |
| id                  | 03807cca-b712-4bc7-b7ce-628c1b790810 |
| port_id             |                                      |
| router_id           |                                      |
| status              | DOWN                                 |
| tenant_id           | 106e169743964758bcad1f06cc69c472     |
+---------------------+--------------------------------------+

[root@step-server ~]# nova floating-ip-associate stress-test 192.168.100.139
</pre>

stress-testにログインしてパラメーター設定ファイルのGAT_HOSTにlbs01のアドレスをセットする。

<pre>
[root@step-server ~]# ssh -i key-for-internal.pem root@10.0.0.4
The authenticity of host '10.0.0.4 (10.0.0.4)' can't be established.
RSA key fingerprint is 23:53:0a:e2:49:99:f6:cb:8c:e7:45:2e:27:4f:f1:4e.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.0.4' (RSA) to the list of known hosts.

[root@stress-test ~]# cd /root/gatling

[root@stress-test gatling]# vi paramset.sh

[root@stress-test gatling]# cat paramset.sh
export GAT_HOST=192.168.0.42
export GAT_SCHEME=http
export GAT_PATH=/
export GAT_RPT=3
export GAT_USER=5
export GAT_DUR=5
export GAT_NAME=SampleAppGet
</pre>

テストを実行する。初回はScalaのコードをJavaバイナリーに変換するために時間がかかる。

<pre>
[root@stress-test gatling]# source paramset.sh

[root@stress-test gatling]# sh sample.app.get.sh
SampleAppGet_u5_r3_s5 start.
GATLING_HOME is set to /root/gatling
Simulation SampleAppGet started...

================================================================================
2015-04-04 11:13:48                                           0s elapsed
---- SampleAppGetGet_u5_r3_s5 --------------------------------------------------
[                                                                          ]  0%
          waiting: 5      / active: 0      / done:0
---- Requests ------------------------------------------------------------------
> Global                                                   (OK=0      KO=0     )

================================================================================


================================================================================
2015-04-04 11:13:52                                           4s elapsed
---- SampleAppGetGet_u5_r3_s5 --------------------------------------------------
[##########################################################################]100%
          waiting: 0      / active: 0      / done:5
---- Requests ------------------------------------------------------------------
> Global                                                   (OK=15     KO=0     )
> request_get_0                                            (OK=5      KO=0     )
> request_get_1                                            (OK=5      KO=0     )
> request_get_2                                            (OK=5      KO=0     )
================================================================================

Simulation finished
Generating reports...
Parsing log file(s)...
Parsing log file(s) done

================================================================================
---- Global Information --------------------------------------------------------
> request count                                         15 (OK=15     KO=0     )
> min response time                                     10 (OK=10     KO=-     )
> max response time                                    242 (OK=242    KO=-     )
> mean response time                                    46 (OK=46     KO=-     )
> std deviation                                         63 (OK=63     KO=-     )
> response time 95th percentile                        157 (OK=157    KO=-     )
> response time 99th percentile                        225 (OK=225    KO=-     )
> mean requests/sec                                   3.69 (OK=3.69   KO=-     )
---- Response Time Distribution ------------------------------------------------
> t < 800 ms                                            15 (100%)
> 800 ms < t < 1200 ms                                   0 (  0%)
> t > 1200 ms                                            0 (  0%)
> failed                                                 0 (  0%)
================================================================================

Reports generated in 0s.
Please open the following file: /usr/share/nginx/html/gatling/SampleAppGet_u5_r3_s5-1428113628240/index.html
</pre>

今回はSoftlayer上のベアメテルにUbuntu Serverを導入しているのでGUI環境は用意されていない。クライアントからWebブラウザーでアクセスできるように、ベアメタルのホスト区画のPublic IPで受けたいクエストを、stress-test の nginx に転送する。

<pre>
user01@test:~$ sudo vi /etc/nginx/conf.d/proxy.conf
[sudo] password for user01:
Sorry, try again.
[sudo] password for user01:
user01@test:~$ cat /etc/nginx/conf.d/proxy.conf
server {
  listen 80;
  server_name [ベアメタルのホスト区画のPublic IP];
  location /  {
    auth_basic "Input ID/PASS";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://192.168.100.139/;
  }
}

user01@test:~$ sudo service nginx restart
 * Restarting nginx nginx                     
</pre>

http://[ホスト区画のPublic IP]/gatling/ にアクセスするとBasic認証の後、テスト結果がリストされる。

![テスト結果のリスト](https://qiita-image-store.s3.amazonaws.com/0/71995/11bb601d-d102-6689-a5f0-503a613470a8.png)

リンクをクリックすると結果がグラフとデータで表示される。

![15-2.png](https://qiita-image-store.s3.amazonaws.com/0/71995/b63f3164-b6fe-bda1-c1fb-7fa1099a7f2b.png)

ではテスト本番。lbs01 で割り振りwebサーバーを一台にする。

```
[root@lbs01 ~]# cat /etc/nginx/conf.d/lbs.conf
upstream web-server {
  server 192.168.0.36:80;
#  server 192.168.0.37:80;
#  server 192.168.0.38:80;
#  server 192.168.0.39:80;
}

server {
  listen 80 default_server;
  server_name _;

  location / {
    proxy_pass http://web-server/;
  }
}
[root@lbs01 ~]# service nginx restart
Stopping nginx:                                            [  OK  ]
Starting nginx:                                            [  OK  ]
```

150ユーザーのテストをする。ユーサー数150、起動時間150、繰り返し50を設定しテストを実行する。

```
[root@stress-test gatling]# export GAT_USER=150
[root@stress-test gatling]# export GAT_DUR=150
[root@stress-test gatling]# export GAT_RPT=50

[root@stress-test gatling]# sh sample.app.get.sh

SampleAppGet_u150_r50_s150 start.
GATLING_HOME is set to /root/gatling
Simulation SampleAppGet started...
～～～～～～～
Reports generated in 1s.
Please open the following file: /usr/share/nginx/html/gatling/SampleAppGet_u150_r50_s150-1428116347258/index.html
```

webサーバーを2台にする。

```
[root@lbs01 ~]# cat /etc/nginx/conf.d/lbs.conf
upstream web-server {
  server 192.168.0.36:80;
  server 192.168.0.37:80;
#  server 192.168.0.38:80;
#  server 192.168.0.39:80;
}

server {
  listen 80 default_server;
  server_name _;

  location / {
    proxy_pass http://web-server/;
  }
}
```

```
300ユーザーのテストをする。ユーサー数300、起動時間300、繰り返し50を設定しテストを実行する。

```
[root@stress-test gatling]# export GAT_USER=300
[root@stress-test gatling]# export GAT_DUR=300
[root@stress-test gatling]# export GAT_RPT=50

[root@stress-test gatling]# sh sample.app.get.sh
～～～～～～～
Reports generated in 2s.
Please open the following file: /usr/share/nginx/html/gatling/SampleAppGet_u300_r50_s300-1428120261061/index.html

```

```
[root@lbs01 ~]# cat /etc/nginx/conf.d/lbs.conf
upstream web-server {
  server 192.168.0.36:80;
  server 192.168.0.37:80;
  server 192.168.0.38:80;
  server 192.168.0.39:80;
}

server {
  listen 80 default_server;
  server_name _;

  location / {
    proxy_pass http://web-server/;
  }
}
```

```
[root@lbs01 ~]# export GAT_USER=600
[root@lbs01 ~]# export GAT_DUR=600
[root@lbs01 ~]# export GAT_RPT=50
[root@stress-test gatling]# sh sample.app.get.sh
～～～～～～～
Reports generated in 3s.
Please open the following file: /usr/share/nginx/html/gatling/SampleAppGet_u600_r50_s600-1428120857898/index.html
```

全件成功している。

![結果のグラフ-成功件数](https://qiita-image-store.s3.amazonaws.com/0/71995/064b4d88-d897-57a0-329f-bd50443e24bf.png)

しかも並列実行数が最大で2件しかない。

![結果のグラフ-並列実行数](https://qiita-image-store.s3.amazonaws.com/0/71995/f04f7f3e-8f08-4885-70b3-ca7de452d982.png)

やり方が悪いかと再チェックしたら、1件のレスポンスが短すぎると並列実行数が増加しないため、データを入力してレスポンスタイムを調整するようにとの記述があった。

今回のdbsはansibleのプレイブックで作っているのでユーザーをansibleに切り替えてdbsにログインし、mysqlのインターフェースからデータを50件投入した。

```
[root@step-server ~]# su - ansible
[ansible@step-server ~]$ ssh -i .ssh/id_rsa root@192.168.0.41
[root@dbs-835563b1-cd98-4fa5-912b-3a07063e4c34 ~]# mysql -u root

mysql> insert into sample_bbs.contents (timestamp,text) values (current_timestamp(),'負荷テストデータ');
Query OK, 1 row affected (0.00 sec)

mysql> select count(*) from sample_bbs.contents;
+----------+
| count(*) |
+----------+
|       50 |
+----------+
1 row in set (0.00 sec)
```

そして再度、webサーバー数を調整しながら負荷テストを再実行する。しかし、やっとコンスタントにコンスタント並列数が2になる程度。

![結果のグラフ-並列実行数2](https://qiita-image-store.s3.amazonaws.com/0/71995/04d4b765-3668-99c9-c4bb-a92c8dfd96cf.png)

テキストデータを長めにして、データを300件にした。

```
mysql> select count(*) from sample_bbs.contents;
+----------+
| count(*) |
+----------+
|      300 |
+----------+
1 row in set (0.00 sec)
```

webサーバー1台の状態で150ユーザーのテストをする。最大で123並列まで達したが、エラーは発生しなかった。

![結果のグラフ-123並列](https://qiita-image-store.s3.amazonaws.com/0/71995/e6e28ecd-362e-94c3-afc4-a8c2446ccbe6.png)

そのまま、webサーバー1台の状態で600ユーザーのテストをしてみる。142ユーザーでエラーが発生した。

![結果のグラフ-1](https://qiita-image-store.s3.amazonaws.com/0/71995/55757cd9-672f-f9fc-aaa7-cd5e42b62ab7.png)

今回の構成・現在のデータ量であれば、1台あたり140件のリクエストを処理できそうだ。

***

ここから、テストの目的が変わる。
結果を見みると並列数に応じてレスポンスタイムが悪化している。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/71995/1ad86b6d-e9a6-f84a-9cf2-fc3e9dd2cb0c.png)

ここからレスポンスタイム改善のために、APPサーバーの負荷分散を行う。
これまでの構成は、下記であった。

```
lbs×1 → web×n → app×1 → dbs×1
```

これを、下記のようにする。

```
lbs×1 → web×n → app-lbs×1 → app×n → dbs×1
```

さらに、appが小さいものが複数の時と大きなものが1台の時とどちらがいいか比較する。

まず、app用のlbsを作成する。フロントのlbsと同じユーザーデータを利用する。webとappの間に入るのでネットワークはdmz-netとapp-netに接続する。起動コマンドは[こちら](https://github.com/josug-book1-materials/chapter15/blob/master/gatling/02_boot_applbs.sh)に用意されている。


<pre>
[root@step-server ~]# function get_uuid () { cat - | grep " id " | awk '{print $4}'; }
[root@step-server ~]# MY_DMZ_NET=`neutron net-show dmz-net | get_uuid`
[root@step-server ~]# MY_APP_NET=`neutron net-show app-net | get_uuid`

[root@step-server ~]# nova boot --flavor standard.xsmall --image "centos-base" \
> --key-name key-for-internal --user-data userdata_lbs.txt \
> --security-groups sg-all-from-console,sg-all-from-app-net \
> --availability-zone az1 --nic net-id=${MY_DMZ_NET} --nic net-id=${MY_APP_NET} \
> lbs_forapp01
+--------------------------------------+----------------------------------------------------+
| Property                             | Value                                              |
+--------------------------------------+----------------------------------------------------+
| OS-DCF:diskConfig                    | MANUAL                                             |
| OS-EXT-AZ:availability_zone          | nova                                               |
| OS-EXT-STS:power_state               | 0                                                  |
| OS-EXT-STS:task_state                | scheduling                                         |
| OS-EXT-STS:vm_state                  | building                                           |
| OS-SRV-USG:launched_at               | -                                                  |
| OS-SRV-USG:terminated_at             | -                                                  |
| accessIPv4                           |                                                    |
| accessIPv6                           |                                                    |
| adminPass                            | x39STaBy2z7d                                       |
| config_drive                         |                                                    |
| created                              | 2015-04-04T06:39:23Z                               |
| flavor                               | standard.xsmall (100)                              |
| hostId                               |                                                    |
| id                                   | 01902e7a-59e9-4b12-b97b-c8f2fc97e17b               |
| image                                | centos-base (098f948e-e80b-4b1a-8a46-f8d2dd57e149) |
| key_name                             | key-for-internal                                   |
| metadata                             | {}                                                 |
| name                                 | lbs_forapp01                                       |
| os-extended-volumes:volumes_attached | []                                                 |
| progress                             | 0                                                  |
| security_groups                      | sg-all-from-console, sg-all-from-app-net           |
| status                               | BUILD                                              |
| tenant_id                            | 106e169743964758bcad1f06cc69c472                   |
| updated                              | 2015-04-04T06:39:23Z                               |
| user_id                              | 98dd78b670884b64b879568215777c53                   |
+--------------------------------------+----------------------------------------------------+
</pre>

作成したlbs-forapp01に入りポート5555へのアクセスをappに転送するように設定する。

<pre>
[root@lbs-forapp01 ~]# vi /etc/nginx/conf.d/app_lbs.conf
[root@lbs-forapp01 ~]# cat etc/nginx/conf.d/app_lbs.conf
cat: etc/nginx/conf.d/app_lbs.conf: No such file or directory
[root@lbs-forapp01 ~]# cat /etc/nginx/conf.d/app_lbs.conf
upstream web-server {
  server 192.168.0.42:5555;
}

server {
  listen 5555 default_server;
  server_name _;

  location / {
    proxy_pass http://web-server/;
  }
}
[root@lbs-forapp01 ~]# service nginx restart
Stopping nginx:                                            [  OK  ]
Starting nginx:                                            [  OK  ]
</pre>

webサーバーはansibleのプレイブックで作っているのでansibleの環境からwebサーバーに入り、endpoint.confのrest_hostをlbs-forapp01のapp-netのものにする。これを4台分実施する。

<pre>
(venv)[ansible@step-server ~]$ ssh -i .ssh/id_rsa root@192.168.0.37

[root@web-197644c9-c72d-4133-b4f8-9eb7bbb6780c ~]# vi /root/sample-app/endpoint.conf
[root@web-197644c9-c72d-4133-b4f8-9eb7bbb6780c ~]# cat /root/sample-app/endpoint.conf
[rest-server]
rest_host = 172.16.10.26
rest_endpoint = http://%(rest_host)s:5555/bbs

[db-server]
db_host = 127.0.0.1
db_endpoint = mysql://user:password@%(db_host)s/sample_bbs?charset=utf8
[root@web-197644c9-c72d-4133-b4f8-9eb7bbb6780c ~]# sh /root/sample-app/server-setup/web.init.sh restart

Starting web.py                                            [  OK  ]
</pre>

1書より負荷に耐えられそうな環境なので、50並行、webサーバー×1でテストする。これでテストをする。

現在のappサーバーは xsmall×1 である。このテストは先ほど完了しているので、先ほどのデータを使う。

```
[root@stress-test gatling]# export GAT_USER=150
[root@stress-test gatling]# export GAT_DUR=150
[root@stress-test gatling]# export GAT_RPT=50
[root@stress-test gatling]# export GAT_NAME=APP_xsmall_x1

[root@stress-test gatling]# sh sample.app.get.sh
```

実行結果はこちら。

![xsmall_x1の結果](https://qiita-image-store.s3.amazonaws.com/0/71995/f5fc5e70-1bbc-f1e3-c248-b256bf5983ab.png)


次に、small×1 のテストである。
ansible のyamlを修正して、standard.smallを使うようにして、playbookで作成する。

```
(venv)[ansible@step-server ~]$ vi create_sample_vm.yml
(venv)[ansible@step-server ~]$ cat create_sample_vm.yml
～～～～～～～
      app:
        flavor_ram: 1024
        flavor_name: "standard.small"
        image_name: "centos-base"
～～～～～～～

(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=app create_sample_vm.yml

(venv)[ansible@step-server ~]$ ansible-playbook -i sample_app_inventory.py -e target=app install_sample_app.yml
```

このプレイブック実行で既存のappサーバーにもendpoind.confのコピー・編集
をしようするが、既存のため失敗する。編集済みのため無視すればよい。今回のプレイブックは複数回の実行を想定されていないだけである。

lbs-forapp01では新しいappサーバーを利用するように設定変更する。

```
[root@lbs-forapp01 ~]# vi /etc/nginx/conf.d/app_lbs.conf
[root@lbs-forapp01 ~]# cat /etc/nginx/conf.d/app_lbs.conf
upstream web-server {
  server 172.16.10.27:5555;
}

server {
  listen 5555 default_server;
  server_name _;

  location / {
    proxy_pass http://web-server/;
  }
}
[root@lbs-forapp01 ~]# service nginx restart
Stopping nginx:                                            [  OK  ]
Starting nginx:                                            [  OK  ]
```

small_x1とわかるようにテスト名を変えてテストを実施する。

```
[root@stress-test gatling]# export GAT_NAME=APP_small_x1
[root@stress-test gatling]# sh sample.app.get.sh
```

![small_x1の結果](https://qiita-image-store.s3.amazonaws.com/0/71995/d1802b68-34ef-39a7-78ff-37500e0472b2.png)

次に、medium×1 のテストである。
手順は先ほどと同じ。
ansible のyamlを修正して、standard.mediumを使うようにして、playbookで作成する。
lbs-forapp01では新しいappサーバーを利用するように設定変更する。
medium×1とわかるようにテスト名を変えてテストを実施する。

```
[root@stress-test gatling]# export GAT_NAME=APP_medium_x1
[root@stress-test gatling]# sh sample.app.get.sh
```

![medium_x1の結果](https://qiita-image-store.s3.amazonaws.com/0/71995/bff89ac2-9b4d-03a6-82c4-a09b899d8d99.png)

次に、xsmall×2 のテストである。
手順は先ほどと同じ。
ansible のyamlを修正して、standard.xsmallを使うようにして、playbookで作成する。
lbs-forapp01では最初のxsmallと今回の新しいappサーバーの両方を利用するように設定変更する。
xsmall×2とわかるようにテスト名を変えてテストを実施する。

```
[root@stress-test gatling]# export GAT_NAME=APP_xsmall×2
[root@stress-test gatling]# sh sample.app.get.sh
```

![xsmall×2の結果](https://qiita-image-store.s3.amazonaws.com/0/71995/cd0513f7-ce22-f234-e20b-d238977d664c.png)

Type | Min | Max | Mean | Std Dev | 95th pct | 99th pct | Req/s
:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:
xsmall×1 | 45 | 19108 | 4197 |1742 | 6197 | 6355 | 20.83
small_x1 | 42 | 19035 | 4177 | 1724 | 6075 | 6197 | 20.97
medium_x1 | 43 | 12586 | 4208 | 1740 | 6173 | 6305 | 20.77
xsmall_x2 | 44 | 9498 | 4140 | 1720 | 6092 | 6242 | 20.95

後になるほど最大レスポンスタイム(Max)が改善されているが、99th pctの値はあまり変わらずおおきな違いが見られない。例外的な長いレスポンスが発生しているだけのよううだ。

今回の環境でボトルネックは別？ということで、**webをxsmall×1固定**でapp側をいじっていたのを、**webをxsmall×2**-app_lbs-xsmall×1でテストしてみる。

![web-xsmall×2-app_lbs-xsmall×1の結果](https://qiita-image-store.s3.amazonaws.com/0/71995/ac9f8f11-26d3-bbc5-3976-4562c71804d5.png)

Type | Min | Max | Mean | Std Dev | 95th pct | 99th pct | Req/s
:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:
web-xsmall×2-app_lbs-xsmall×1|45 | 2913|1627|	767| 2691|2812 |32.68

すごく改善された。今回の設定ではappの前にwebがボトルネックになっていたようだ。

パフォーマンスチューニングは難しい。目標が無いとゴールも無くいつまでもやることとなる。

## 15.3 Webアプリケーション機能テストの自動化

当節の支援ファイルは[こちら](https://github.com/josug-book1-materials/chapter15/tree/master/selenium)。

### 15.3.1 Selenium

ここは機能テストの自動化に使うSeleniumの説明である。

### 15.3.2 v2アプリケーション確認テストの実施

こちらでも「まずはじめに第8章の手順を元にサンプルアプリversion2を展開した環境を構築します」だそうだ。[build_chap08.sh](https://github.com/josug-book1-materials/chapter05-10/blob/master/08/build_chap08.sh)が用意されているので、これを実行する。

```
[root@step-server ~]# source openrc
[root@step-server ~]# mkdir $HOME/work_chapter
[root@step-server ~]# cp chapter05-10/06/userdata_dbs.txt $HOME/work_chapter
[root@step-server ~]# cp chapter05-10/07/userdata_lbs.txt $HOME/work_chapter
[root@step-server ~]# cd /root/chapter05-10/08/
[root@step-server 08]# sh build_chap08.sh

```

サーバーが起動した。

<pre>
[root@step-server ~]# nova list --field name,networks
+--------------------------------------+---------------------------------------------+------------------------------------------------------------------+
| ID                                   | Name                                        | Networks                                                         |
+--------------------------------------+---------------------------------------------+------------------------------------------------------------------+
| 65d3400d-3467-4563-9ff5-9c0e30c7157e | step-server                                 | work-net=10.0.0.1, 192.168.100.131                               |
| 22613a28-72c7-4d09-90f2-e712ce40354f | v2-app01                                    | dmz-net=192.168.0.55; app-net=172.16.10.35; dbs-net=172.16.20.23 |
| 5816b7f0-0202-4fa2-96b7-3a5f121a84b3 | v2-dbs01                                    | dmz-net=192.168.0.54; dbs-net=172.16.20.22                       |
| 0b7b1682-d74c-496c-bc53-53b0cb96d41a | v2-lbs01                                    | dmz-net=192.168.0.60                                             |
| 0cfe3cd5-7023-408a-8ca7-5b6c6c668cb1 | v2-web-0cfe3cd5-7023-408a-8ca7-5b6c6c668cb1 | dmz-net=192.168.0.56; app-net=172.16.10.36                       |
| 1b22efd6-bb64-4818-823f-c3e2af24d3c6 | v2-web-1b22efd6-bb64-4818-823f-c3e2af24d3c6 | dmz-net=192.168.0.57; app-net=172.16.10.37                       |
| 30fefe0a-4b56-4aef-981f-4bca96cf9001 | v2-web-30fefe0a-4b56-4aef-981f-4bca96cf9001 | dmz-net=192.168.0.59; app-net=172.16.10.39                       |
| cec1a0fc-7880-4179-b474-663dacec5789 | v2-web-cec1a0fc-7880-4179-b474-663dacec5789 | dmz-net=192.168.0.58; app-net=172.16.10.38                       |
+--------------------------------------+---------------------------------------------+------------------------------------------------------------------+
</pre>

v2-lbs01でnginxを構成する。

<pre>
[root@v2-lbs01 ~]# vi /etc/nginx/conf.d/ilbs.conf
[root@v2-lbs01 ~]# cat /etc/nginx/conf.d/ilbs.conf
upstream web-server {
  server 192.168.0.56:80;
  server 192.168.0.57:80;
  server 192.168.0.58:80;
  server 192.168.0.59:80;
}

server {
  listen 80 default_server;
  server_name _;

  location / {
    proxy_pass http://web-server/;
  }
}
[root@v2-lbs01 ~]# service nginx restart
Stopping nginx:                                            [  OK  ]
Starting nginx:                                            [  OK  ]
</pre>

機能テストサーバーを起動する。[userdata_functest.txt](https://github.com/josug-book1-materials/chapter15/blob/master/selenium/userdata_functest.txt)を利用する。
起動コマンドは、負荷テストサーバーを起動した[こちら](https://github.com/josug-book1-materials/chapter15/blob/master/gatling/01_boot_stress_vm.sh)からuser-data名とサーバー名を変更するだけだ。



<pre>
[root@step-server selenium]# nova boot --flavor standard.small \
> --image "centos-base" \
> --key-name key-for-internal --user-data userdata_functest.txt \
> --security-groups sg-all-from-console,sg-web-from-internet \
> --availability-zone az1 \
> --nic net-id=${MY_DEFAULT_NET} func-test
+--------------------------------------+----------------------------------------------------+
| Property                             | Value                                              |
+--------------------------------------+----------------------------------------------------+
| OS-DCF:diskConfig                    | MANUAL                                             |
| OS-EXT-AZ:availability_zone          | nova                                               |
| OS-EXT-STS:power_state               | 0                                                  |
| OS-EXT-STS:task_state                | scheduling                                         |
| OS-EXT-STS:vm_state                  | building                                           |
| OS-SRV-USG:launched_at               | -                                                  |
| OS-SRV-USG:terminated_at             | -                                                  |
| accessIPv4                           |                                                    |
| accessIPv6                           |                                                    |
| adminPass                            | N3jWRXEMogb6                                       |
| config_drive                         |                                                    |
| created                              | 2015-04-04T23:28:23Z                               |
| flavor                               | standard.small (101)                               |
| hostId                               |                                                    |
| id                                   | 006fd761-9049-4ea3-9b83-d194a8aa75a9               |
| image                                | centos-base (098f948e-e80b-4b1a-8a46-f8d2dd57e149) |
| key_name                             | key-for-internal                                   |
| metadata                             | {}                                                 |
| name                                 | func-test                                          |
| os-extended-volumes:volumes_attached | []                                                 |
| progress                             | 0                                                  |
| security_groups                      | sg-all-from-console, sg-web-from-internet          |
| status                               | BUILD                                              |
| tenant_id                            | 106e169743964758bcad1f06cc69c472                   |
| updated                              | 2015-04-04T23:28:24Z                               |
| user_id                              | 98dd78b670884b64b879568215777c53                   |
+--------------------------------------+----------------------------------------------------+
</pre>

結果が確認できるように外部ネットワークのFloating IPをつけておく。

<pre>
[root@step-server selenium]# neutron floatingip-create Ext-Net
Created a new floatingip:
+---------------------+--------------------------------------+
| Field               | Value                                |
+---------------------+--------------------------------------+
| fixed_ip_address    |                                      |
| floating_ip_address | 192.168.100.140                      |
| floating_network_id | 36733654-35d1-47c9-9942-dab9400c52f0 |
| id                  | 929ebbca-f761-4586-966a-0623dbb58f04 |
| port_id             |                                      |
| router_id           |                                      |
| status              | DOWN                                 |
| tenant_id           | 106e169743964758bcad1f06cc69c472     |
+---------------------+--------------------------------------+

[root@step-server selenium]# nova floating-ip-associate func-test 192.168.100.140
</pre>

いよいと機能テストを実施する。機能テストサーバーにログインして内容を確認する。

```
[root@step-server ~]# ssh -i key-for-internal.pem root@10.0.0.5
[root@func-test ~]# cd selenium/
[root@func-test selenium]# ls
exec_test.sh  sample.png  v2app_test.py
```

テスト用のスクリプトは[こちら](https://github.com/josug-book1-materials/chapter15/blob/master/selenium/sampletest.py)。引数を指定した実行コマンドサンプルは[こちら](https://github.com/josug-book1-materials/chapter15/blob/master/selenium/exec_test.sh)。
「-H 192.168.0.60」には自分のlbsのアドレスを指定する。

```
[root@func-test selenium]#  python v2app_test.py -H 192.168.0.60 -o /usr/share/nginx/html/selenium/ -u sample.png -t "v2 test"
-- 1. Get test start.
  save snap /usr/share/nginx/html/selenium/SampleApp_v2test-1428193002/1.get_after.png
-- 1. OK: Get test is succes.
-- 2. Upload test start
  save snap /usr/share/nginx/html/selenium/SampleApp_v2test-1428193002/2-1.pre_upload.png
It is first writing
  save snap /usr/share/nginx/html/selenium/SampleApp_v2test-1428193002/2-2.after_upload.png
-- 2. OK: Upload test is success.
-- 3. Unupload test start.
  save snap /usr/share/nginx/html/selenium/SampleApp_v2test-1428193002/3-1.pre_unupload.png
  save snap /usr/share/nginx/html/selenium/SampleApp_v2test-1428193002/3-2.after_unupload.png
-- 3. OK: Unupload test is success.
All test completed
```

外部から機能テストサーバーのnginxにアクセスできるようにホスト区画のnginxのReverse Proxyを調整後、手元のブラウザーでアクセスする。

http://ホスト区画/selenium/ にテスト結果が保存されている。

![テスト結果のリスト](https://qiita-image-store.s3.amazonaws.com/0/71995/befa25a7-1e23-7c1a-a210-892b9d4e2f9c.png)

フォルダーを開くとテストステップ毎のイメージが保管されている。

![ステップ毎のイメージ](https://qiita-image-store.s3.amazonaws.com/0/71995/1e866591-62c1-f231-18f0-7283fc845fc3.png)

イメージのアップロード後を示す 2-2.after_upload.png を確認すると正常に処理されていることが確認できる。

![アップロード後のイメージ](https://qiita-image-store.s3.amazonaws.com/0/71995/be337d75-c83e-de54-9dff-9a8ab809d826.png)

これで完了！テストの完了宣言を投稿する。

```
[root@func-test selenium]# python v2app_test.py -H 192.168.0.60 -o /usr/share/nginx/html/selenium/ -u sample.png -t "It's completed."
```

![完了宣言後のイメージ](https://qiita-image-store.s3.amazonaws.com/0/71995/2e623e99-408a-19ec-b2a6-5d96460ab166.png)



***
第15章の完了。
***
第16章は「Yahoo! JapanのOpenStack活用事例」と読む章であり実習は無い。これですべて完了！！！

SoftLayerの500$引きキャンペーンを適用した無料のベアメタルで32GBのサーバーを占有できたこと、無料期間が最大でも一ヶ月(次のアニバーサリーデート/月締め日まで)と期間が限られれていたので締め切りを意識して集中して学習できたことでゴールできた。

東京、メキシコ、フランクフルトの500$引きキャンペーンの申し込みは終了したが、シドニーとモントリオールの500$引きキャンペーンは[2015/06/07まで申し込み可能](http://www.softlayer.com/info/global-expansion)だ。

![シドニー500$引きキャンペーン](https://qiita-image-store.s3.amazonaws.com/0/71995/69c37595-7554-2a15-4c73-fe9ad81cc257.png)

こちらでも、また、何かをやってみたい。

***
[前回はこちら](http://qiita.com/orz/items/232b650a19c97a6369fe)