小型/堅牢/メンテナンスフリー OpenBlockS 600の限界に挑戦

第3回LVSによる堅牢で安価なロードバランサ(後編)

LVSの設定とパフォーマンス

前回の前編では、WebサーバのLVS(Linux Virtual Server)をめざして、仮想サーバのロードバランサとリアルサーバ、接続確認用のクライアントを用意しました。ロードバランサとなるOpenBlockS 600には、Debianをインストールして、ipvsadmとkeepalivedパッケージを追加インストールしました。リアルサーバにはApacheをインストールして、Webサーバとして動作させています。LVSの設定はしないままで、クライアントからリアルサーバへの接続を確認して、おしまいとなりました。

今回の後編では、LVSの設定を手動と自動の二通り説明します。まず、IPVSの設定をipvsadmコマンドで手動で行い、負荷分散の様子を見てみます。それから、Keepalivedを設定、動作させ、リアルサーバのダウンと復旧に対処しながらWebサービスが続けられることを確認します。

最後に、どの程度の負荷分散の効果があるのか、ベンチマークをとってみます。

IPVSの構築

OpenBlockS 600でipvsadmコマンドをオプションなしで実行してください。図1のとおり表示されるはずです。

図1 ipvsadmコマンドの実行結果
obs600# ipvsadmIP Virtual Server version 1.2.1 (size 4096)
Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConnInActConn

もし、図2のようにip_vsモジュールがみつからないというエラーが出たら、カーネルモジュールの依存性リストを更新します図3⁠。

図2 ip_vsモジュールがみつからない
obs600# ipvsadmFATAL: Module ip_vs not found.
Can t initialize ipvs: Protocol not availableAre you sure that IP Virtual Server is built inthe kernel or as module?
図3 カーネルモジュールの依存性リストの更新
obs600# depmod -a

LVS-NAT

それではIPVSの設定をしていきましょう。これは、Linuxカーネル内の仮想サーバテーブルをipvsadmコマンドで編集します。以下、用語はipvsadmコマンドのマニュアルページにしたがいます。

仮想サーバテーブルの消去

まだIPVSの設定はしていませんが、図4のとおり、仮想サーバテーブルを消去するコマンドを実行しておきましょう。

図4 仮想サーバテーブルの消去
obs600# ipvsadm -C

仮想サービスの追加

仮想サービスを図5のとおり追加します。オプション-A は、仮想サービスの追加を示します。

図5 仮想サービスの追加
obs600# ipvsadm -A -t 192.168.253.120:80 -s rr

オプション-tは、TCPサービスを使用することを指定します。その値として、仮想IPアドレス192.168.253.120とWebサービスを意味するポート番号80を指定しました。

オプション-sで、リアルサーバへのスケジューリングアルゴリズム(振り分け方)を指定します。ここでは、ラウンドロビンrrを指定しました。接続要求をリアルサーバに均等に振り分けます。

スケジューリングアルゴリズムは全部で10個あります。OpenBlockS 600のカーネルでは、モジュールとしてすべて有効にしてあるので、rrの他に、wrr、lc、wlc、lblc、lblcr、dh、sh、sed、nqが指定できます。それぞれの意味は、ipvsadmコマンドのマニュアルページなどをご覧ください。

仮想サービスへのリアルサーバの追加

仮想サービスへリアルサーバを追加します図6⁠。

図6 仮想サービスへのリアルサーバの追加
obs600# ipvsadm -a -t 192.168.253.120:80 -r 172.16.14.121:80 -m 
obs600# ipvsadm -a -t 192.168.253.120:80 -r 172.16.14.122:80 -m 
obs600# ipvsadm -a -t 192.168.253.120:80 -r 172.16.14.123:80 -m

オプション-aは、仮想サービスへのリアルサーバの追加を示します。オプション-tとその値は、仮想サービス追加と同じです。オプション-rで、リアルサーバのIPアドレスとポート番号を指定します。オプション-mは、パケットフォワーディング方法がNATであることを示します。

パケットフォワーディング方法は、NATの他にダイレクトルーティング(-g)とトンネリング(-i)があります。ここでは、ネットワーク構成をNATに合わせたので、他の方法は指定できません。

仮想サーバテーブルの表示

IPVSの設定が図7のとおりになっているか確認してください。

図7 仮想サーバテーブルの表示
obs600# ipvsadm
IP Virtual Server version 1.2.1 (size 4096)
Prot LocalAddress:Port Scheduler Flags 
-> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.253.120:www rr
-> 172.16.14.123:www Masq 1 0 0 
-> 172.16.14.122:www Masq 1 0 0 
-> 172.16.14.121:www Masq 1 0 0

接続の確認

クライアントからcurlコマンドで仮想IPアドレスに接続してみてください。仮想サーバから図8のように応答があれば成功です。

図8 接続の確認
client$ curl http://192.168.253.120/
realserver3 
client$ curl http://192.168.253.120/
realserver2 
client$ curl http://192.168.253.120/
realserver1

ここでは、応答のあったリアルサーバを区別するためにコンテンツを違うものとしておきました。コンテンツを同じものにしておけば、どのリアルサーバから応答があったのか、クライアントからはわかりません。これで、Webサービスを3台のリアルサーバに負荷分散させることができました。

リアルサーバがダウンした場合

ところで、リアルサーバがダウンした場合はどうなるでしょうか。リアルサーバrealserver3のhttpdを停止して、クライアントから接続してみましょう。curlコマンドの実行結果のうちには、図9に示したとおり、リアルサーバrealserver1とrealserver2からの応答の他に、接続ができないと表示されています。これでは、クライアントが仮想サーバに接続したときに、Webサービスが受けられない場合があることになってしまいます。

図9 リアルサーバrealserver3がダウンした場合の応答
client$ curl http://192.168.253.120/
curl: (7) couldn t connect to host
client$ curl http://192.168.253.120/
realserver2 
client$ curl http://192.168.253.120/
realserver1

リアルサーバの重みを0にする

そのような場合に対処するために、仮想サービス中のリアルサーバrealserver3を図10のとおり編集してみましょう。オプション-eは、仮想サービスのリアルサーバの編集を示します。オプション-wで、重み(Weight)を指定します。リアルサーバrealserver3の重みを0にしました。

図10 リアルサーバの重みを0にする
obs600# ipvsadm -e -t 192.168.253.120:80 -r 172.16.14.123:80 -m -w 0
obs600# ipvsadm
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.253.120:www rr
-> 172.16.14.123:www Masq 0 0 0
-> 172.16.14.122:www Masq 1 0 0

curlコマンドでの接続結果は、図11のようになります。今度は、リアルサーバrealserver1とrealserver2から応答があり、接続ができないという表示はありません。したがって、クライアントが仮想サーバに接続したときに、Webサービスが受けられないということはなくなりました。

図11 リアルサーバrealserver3がダウンした場合の応答(重み0)
client$ curl http://192.168.253.120/
realserver2 
client$ curl http://192.168.253.120/
realserver1 
client$ curl http://192.168.253.120/
realserver2

リアルサーバが復旧した場合

それでは、リアルサーバが復旧した場合はどうなるでしょうか。リアルサーバrealserver3のhttpdを開始して、クライアントから接続してみましょう。curlコマンドでの接続結果は、やはり図11のようになり、リアルサーバrealserver3からの応答がないままです。これは、リアルサーバrealserver3の重みが0のままだからです。

リアルサーバの重みを1にする

仮想サービス中のリアルサーバrealserver3を図12のとおり編集してみましょう。リアルサーバrealserver3の重みを1にしました。

図12 リアルサーバの重みを1にする
obs600# ipvsadm -e -t 192.168.253.120:80 -r 172.16.14.123:80 -m -w 1
obs600# ipvsadm
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.253.120:www rr
-> 172.16.14.123:www Masq 1 0 0
-> 172.16.14.122:www Masq 1 0 0

curlコマンドでの接続結果は図8のようになり、すべてのリアルサーバから応答が確認できました。

Keepalived

ここまで、手動で対処したリアルサーバがダウンしているか否かの確認と、仮想サーバサービスの設定の編集を、デーモンとして管理するのがKeepalivedです。

/etc/keepalived/keepalived.conf

OpenBlockS 600のKeepalivedの設定ファイル/etc/keepalived/keepalived.confをリスト1に示しました。この設定ファイルは、keepalivedパッケージに含まれる見本samples/keepalived.conf.virtual_server_groupを元にkeepalived.conf.SYNOPSIS.gzを参考にして書きました。以下、用語はkeepalived.conf.SYNOPSIS.gzにしたがっています。

リスト1 /etc/keepalived/keepalived.conf
virtual_server 192.168.253.120 80 {
    delay_loop 6
    lvs_sched rr
    lvs_method NAT
    protocol TCP

    real_server 172.16.14.121 80 {
        inhibit_on_failure
        HTTP_GET {
            url {
                path /index.html
                status_code 200
            }
        }
    }

    real_server 172.16.14.122 80 {
        inhibit_on_failure
        HTTP_GET {
            url {
                path /index.html
                status_code 200
            }
        }
    }

    real_server 172.16.14.123 80 {
        inhibit_on_failure
        HTTP_GET {
            url {
                path /index.html
                status_code 200
            }
        }
    }
}

リスト1にはLVSコンフィグレーションが記述してあります。

virtual_serverで始まるブロックが仮想サーバの宣言です。仮想IPアドレス192.168.253.120とポート番号80を指定しています。

先のIPVSの設定に対応して、スケジューリングアルゴリズムをlvs_schedでラウンドロビンrrに、パケットフォワーディング方法をlvs_methodでNATに指定しています。

real_serverで始まるブロックはリアルサーバの宣言です。HTTP_GETはHTTPのGETメソッドで、リアルサーバがダウンしているか否か確認(ヘルスチェック)することを指定しています。ヘルスチェックの間隔はdelay_loopで指定します。inhibit_on_failureは、ヘルスチェックの結果が失敗ですと、リアルサーバの重みを0に設定します。リアルサーバの復旧が確認できれば、重みが1に設定されます。

Keepalivedの起動

仮想サーバテーブルの消去

KeepalivedがIPVSの設定をするので、図4のとおり仮想サーバテーブルを消去します。

Keepalivedの起動

図13のとおり、Keepalivedを起動してください。

図13 Keepalivedの起動確認
obs600# /etc/init.d/keepalived start
Starting keepalived: keepalived.

仮想サーバテーブルの表示

IPVSの設定の確認をすると、図7のように表示されるはずです。

接続の確認

クライアントからcurlコマンドで仮想IPアドレスに接続してみてください。仮想サーバから、図8のように応答があれば成功です。

うまく動作しない場合、設定ファイル/etc/keepalived/keepalived.confに誤りがないか確認してください。

リアルサーバがダウンした場合

さて、リアルサーバがダウンした場合はどうなるでしょうか。リアルサーバrealserver3のhttpdを停止して、クライアントから接続してみましょう。

curlコマンドの実行結果のうちには、図11に示したとおり、リアルサーバrealserver1とrealserver2から応答があり、接続ができないという表示はありません。

ipvsadmコマンドを実行して、realserver3の重みが0になっていることが確認できます。

リアルサーバが復旧した場合

それでは、リアルサーバが復旧した場合はどうなるでしょうか。リアルサーバrealserver3のhttpdを開始して、クライアントから接続してみましょう。

curlコマンドでの接続結果は、図8のようになります。リアルサーバrealserver3からも応答するようになりました。

ipvsadmコマンドを実行して、realserver3の重みが1になっていることが確認できます。

ベンチマーク

Webサーバの負荷分散ができるようになったので、性能を測定してみます。Apacheに含まれるベンチマークツールApacheBench(abコマンド)を使います。

同時リクエスト数が多い場合

クライアントから仮想IPアドレスに対してabコマンドを実行します。図14にabコマンドの実行結果を示しました。

図14 abの実行結果
client$ ab -c 1000 -n 1000 http://192.168.253.120/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.253.120 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests

Server Software:      Apache/2.2.15
Server Hostname:      192.168.253.120
Server Port:          80

Document Path:        /
Document Length:      12 bytes

Concurrency Level:    1000
Time taken for tests: 0.626 seconds
Complete requests:    1000
Failed requests:      0
Write errors:         0
Total transferred:    277207 bytes
HTML transferred:     12000 bytes
Requests per second:  1597.64 [#/sec] (mean)
Time per request:     625.924 [ms] (mean)
Time per request:     0.626 [ms] (mean, across all concurrent requests)
Transfer rate:        432.50 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   18   9.7     14      46
Processing:    20  135  79.1    127     319
Waiting:       20  134  78.9    127     319
Total:         32  153  86.5    142     363

Percentage of the requests served within a certain time (ms)
  50%    142
  66%    155
  75%    218
  80%    242
  90%    293
  95%    329
  98%    348
  99%    355
 100%    363 (longest request)

abコマンドのオプションには、リクエスト数1,000(-n 1000)と同時に実行するリクエスト数1,000(-c 1000)を指定しました。

得られた結果のうち、1秒間に処理したリクエスト数(Requests per second)表1に示しました。表中の数値は、10回測定した結果の平均値です。比較のため、LVS-NATなしの場合、すなわちクライアントからリアルサーバに対してabコマンドを実行した結果も示しました。

表1 "ab -c 1000 -n 1000"の結果(Requests per second)
LVS-NAT[#/sec](mean)
1605.68
992.48

LVS-NATを使用すると、性能はLVS-NATを使用しない場合の約1.6倍になっています。負荷分散の効果がありました。

同時リクエスト数が少ない場合

同じ条件で、同時に実行するリクエスト数だけを100(-c 100)に減らした場合の結果を表2に示しました。

表2 "ab -c 100 -n 1000"の結果(Requests per second)
LVS-NAT[#/sec](mean)
2183.62
4164.11

LVS-NATの処理がボトルネックとなっているものの、同時に実行するリクエスト数1,000の場合に較べると性能は上がっています。

ロードバランサ編:おわりに

OpenBlockS 600とオープンソースソフトウェアを組み合わせると、堅牢で安価なロードバランサを構築することができます。この記事をお読みになって、読者がOpenBlockS 600を使ってみようという気になられたならば、筆者の目的は達成されたことになります。

ここでは、LVSの基本的な機能のほんの一部を設定して動作確認しました。どのような機能があるのか、どう設定するのかは、ソフトウェアの付属文書や参考ページをご覧ください。実運用されましたら、ぷらっとホームまでお知らせいただき、導入事例として紹介することができましたら幸いです。

参考ページ

The Linux Virtual Server Project
URL:http://www.linuxvirtualserver.org/
IPVS Software
URL:http://www.linuxvirtualserver.org/software/ipvs.html
Keepalived
URL:http://www.keepalived.org/
こんなに簡単! Linuxでロードバランサ(1)
URL:http://dsas.blog.klab.org/archives/50664843.html
こんなに簡単! Linuxでロードバランサ(2)
URL:http://dsas.blog.klab.org/archives/50665382.html
ab - Apache HTTP server benchmarking tool
URL:http://httpd.apache.org/docs/2.2/programs/ab.html

おすすめ記事

記事・ニュース一覧