ボールを蹴りたいシステムエンジニア

ボール蹴りが大好きなシステムエンジニア、ボールを蹴る時間確保の為に時間がある時には勉強する。

LinuxでLVSを用いてロードバランサ(DSR方式)の構築を行う。

LVSとはLinuxでの負荷分散(ロードバランサ)環境構築の為のソリューション。
ラウンドロビン方式や重みづけの設定が楽に行える。
注意点として、LVSでは負荷分散の為の振り分けこそ行うがサーバーダウン時の自動切り離し等の冗長化は行えない。
冗長化を行う為には、LVSをラッパーしたkeepalivedを使用するのが一般的。

参考
http://blog.idcf.jp/entry/cloud/keepalived/

今回は冗長化は行わず、単純なラウンドロビンでの負荷分散を行う。

また転送方式には代表的な所で下記2つがあるが、DSRを採用する。

NAT(Network Address Translation)
クライアントからパケットを受け取ると、送信先IPアドレスがリアルサーバーのものに置き換えられる。
LVSサーバーを必ず通るのでLVSサーバーの負荷が上がる。
Apache等のアクセスログでのIPアドレスは接続元のIPアドレスになる。

ダイレクト・ルーティング(DSR方式)
クライアントからのパケットを直接リアルサーバーに転送する。
IPアドレスなどは変更されないので、リアルサーバーはエンドユーザーに直接応答を送信する。
LVSサーバーの負荷は下がる。
リアルサーバーも直接クライアントと通信が出来ないといけない。
Apacheなどのアクセスログに残るのはLVSのアドレスになる?(未確認)
負荷分散を行う機器とサービスを提供するサーバは、同一のネットワーク上に置かなければならないという制限がある。

参考
http://k-1-ne-jp.blogspot.jp/2013/02/lvsipvsadm.html

環境

以下3台をVMwareで構築。

  • LBサーバー(LVSサーバー)

OS:CentOS6 
(eth0)IP:192.168.11.30
(eth1)IP:10.0.10.30

  • WEBサーバーA(リアルサーバー)

OS:CentOS6 
(eth0)IP:10.0.10.40

  • WEBサーバーB(リアルサーバー)

OS:CentOS6
(eth0)IP:10.0.10.111

一般的にロードバランサ構成の場合、ロードバランサ宛先側のバックエンドサーバーを実サーバー(リアルサーバー)というらしい。

手順

WEBサーバー2台での設定作業

デフォルトゲートウェイ設定

バックエンドのWEBサーバーではデフォルトゲートウェイをLBサーバーに設定する必要があるのでその設定。

networkファイル編集

[root@localhost ~]# vi /etc/sysconfig/network

LBサーバーのIPを指定

GATEWAY=10.0.10.30

デフォルトゲートウェイ設定後はサーバー再起動が必要ぽいので注意。

ネットワークインターフェイス毎にデフォルトゲートウェイが異なる場合は
/etc/sysconfig/network-script/ifcfg-eth*
に設定するらしい。
両方に記述しては駄目。

設定ファイル変更で反映されなかったのでrouteコマンドを実行。
※ネットワーク再起動やサーバー再起動で消えるらしいので注意

[root@localhost ~]# route add default gw 10.0.10.30

反映された

[root@web ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.10.0       0.0.0.0         255.255.255.0   U     0      0        0 eth0
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
0.0.0.0         10.0.10.30      0.0.0.0         UG    0      0        0 eth0
Apache環境構築

WEBサーバー2台にApacheをインストールし、それぞれのサーバーのレスポンスが分かるようなファイルを配置。
今回は取り敢えず動作確認が取れればいいので簡単にyumでインストール

インストール

yum install -y httpd

起動

/etc/init.d/httpd start

index.htmlファイル配置

WEBサーバーA

echo server111 > /var/www/html/index.html       

WEBサーバーB

echo server40 > /var/www/html/index.html

index.htmlにアクセスすると以下のようにサーバーが分かる。

curl http://localhost
server40

最後に、リアルサーバーでiptables設定。
下記のIPはLVSサーバーのIPを指定する。
※この設定はDSR方式の場合のみなので、NAT方式の場合は不要

iptables -t nat -A PREROUTING -d 10.0.10.30 -j REDIRECT  

80番ポートも解放

iptables -A INPUT -p tcp ---sport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT

LBサーバーでの作業

ipvsadmのインストールと設定を行う。
ipvsadmとはIPVS(IP Virtual Server)を制御するためのツール。 仮想サーバグループの追加やリアルサーバの割り当てができるほか、 現在の接続状況や転送レートの表示などができる。
IPVSadministratorの略?

ipフォワード設定

ipvsadmの設定前に、まずはipフォワードの設定を許可します。
設定

vi /etc/sysctl.conf

値を1に設定する。

net.ipv4.ip_forward = 1

IPv4 転送を有効にする設定。
異なるセグメント間のネットワークを有効にするイメージ。
下記記事が参考なる。
http://d.hatena.ne.jp/eco31/20110221/1298260941

ipv6に対応しない為、下記をコメントアウト

#net.bridge.bridge-nf-call-ip6tables = 0
#net.bridge.bridge-nf-call-iptables = 0
#net.bridge.bridge-nf-call-arptables = 0

設定を反映
※sysctlはカーネルの内部状態を設定、参照するための機能

[root@localhost ~]# sysctl -p

net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
ipvsadmインストール設定

ipvsadm インストール

yum -y install ipvsadm

ipvsadm起動

/etc/rc.d/init.d/ipvsadm start

ipvsadmを起動スクリプト自動起動設定

chkconfig ipvsadm on 

仮想サービステーブルをクリア

ipvsadm -C

仮想サービスを登録。
今回は実際のLBサーバーのIPを指定してるけど仮想IPを割り当てるのが一般らしい。
IPアドレス、ポート番号、プロトコルで一意となるようにする。
ここで指定するIPは自身のローカルIP。
「-t」をつける事で、<アドレス>:<ポート番号>と指定できる。
「-s」で分散方法を指定、デフォルトの「wlc: 重み付け最小コネクション数」を使用する。

ipvsadm -A -t 10.0.10.30:80 -s wlc

※参考までに、NAT方式で転送する場合
同一セグメントにはできない為

ipvsadm -A -t 192.168.10.30:80 -s wlc

実サーバーを登録
「-a」で実サーバーを登録
「-t」で仮想サービスを指定
「-r」の後ろに実サーバーを指定
転送オプションの指定として、「-g」でDSRを指定している。
他にも転送方法はあるので、詳細はmanで確認する。

ipvsadm -a -t 10.0.10.30:80 -r 10.0.10.40:80 -g 
ipvsadm -a -t 10.0.10.30:80 -r 10.0.10.111:80 -g 

※参考までに、NAT方式で転送する場合
転送オプションの指定として、「-m」でLVS-NAT(アドレス変換)を指定している。

ipvsadm -a -t 192.168.10.30:80 -r 10.0.10.40:80 -m 
ipvsadm -a -t 192.168.10.30:80 -r 10.0.10.111:80 -m 

仮想サービステーブルを確認

[root@lb ~]# ipvsadm -l 
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.10.30:http wlc
  -> 10.0.10.40:http              Masq    1      0          0         
  -> 10.0.10.111:http             Masq    1      0          0   

設定を保存

/etc/rc.d/init.d/ipvsadm save

iptables設定

iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --sport 80 -j ACCEPT

iptables -A OUTPUT -p tcp  --dport 80 -j ACCEPT
iptables -A OUTPUT -p tcp  --sport 80 -j ACCEPT

他サーバーから疎通確認
別でIPが10.0.10.50のクライアント・サーバーを立てて、そちらからアクセス。
ロードバランスされている
今回はラウンドロビンなので交互にアクセスされてる

[root@localhost ~]# curl http://192.168.10.30
server40
[root@localhost ~]# curl http://192.168.10.30
server111

試しにWEBサーバーBをダウンさせてみる。
冒頭で触れた通り、LVS冗長化には対応してないので、ダウンしてようがアクセスが行く。
冗長化対応の為には別途keepaliveインストールが必要。

[root@localhost ~]# curl http://192.168.10.30
server40
[root@localhost ~]# curl http://192.168.10.30
curl: (7) couldn't connect to host

ハマった所

LVS環境構築後、curlアクセスで固まった場合

curlで固まる場合は、LBサーバーとWEBサーバーどちらかのiptables設定でdropされてる可能性大。
iptablesの設定でDropしたパケットはログ出力する等して地道にポート開放設定すべし。

こんな感じでwebサーバー側のiptablesでINPUTがDropされてる事がある。

Feb 15 19:46:29 web kernel: Dropped by INPUT: IN=eth0 OUT= MAC=00:0c:29:5c:ba:fd:00:0c:29:73:76:73:08:00 SRC=192.168.10.30 DST=10.0.10.40 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=21323 DF PROTO=TCP SPT=45687 DPT=80 WINDOW=65495 RES=0x00 SYN URGP=0 

この辺でかなりハマった・・・

上記でも解決しない場合

WEBサーバー側でDSR のバランシングに応答するため、LBサーバーとサーバーへのパケットをリダイレクト処理。

iptables -t nat -A PREROUTING -d 10.0.10.30 -j REDIRECT  

但しこの設定は振り分け設定を下記のようなオプション「-g」でDSRとした場合のみ。
「-m」でのnatの場合は不要

ipvsadm -a -t 10.0.10.30:80 -r 10.0.10.111:80 -g 
実サーバー登録時にエラー

以下のようなエラーが・・・

ipvsadm -A -t 10.0.10.30:80 -s wl
Scheduler or persistence engine not found

ちょっとハマったけど、単純に分散方法の指定がおかしい。
最後のcが足りなかった・・・
イージーミス
下記で解決。

ipvsadm -A -t 192.168.10.30:80 -s wlc

やり残し&続いてやる事

LBサーバーからのアクセス、実サーバー自身からのアクセス時にレスポンスが返ってこない

…何言ってるかわからないと思いますが。

1.LBサーバーから下記のようにアクセスするとレスポンス返ってこない

curl http://10.0.10.30

2.例えば、10.0.10.40サーバーから下記でアクセスした場合、かつ内部的に10.0.10.40自身にロードバランサされた時にレスポンスが返ってこない
(別サーバー10.0.10.111にロードバランサされた時はレスポンスある)


恐らくだけど、下記が理由?
http://qiita.com/nagais/items/b9b1940cdaf9a17b4088
>同一筐体だとLVSMaster機が初回に処理した時にARP登録され、次回以降のリクエストがLVS通らず直接ARP登録されたインターフェースへいくのでダメ。。

んー、違うかも。
これはちょっと調査必要かも。

keepalivedを使用して冗長化構成構築

後日やってみます

メモ

今回、LVSのDSRでロードバランサなのですが、NAT構成の場合LVSのサーバとアプリケーションサーバが同一のネットワークセグメントに存在すると振り分けがうまくいかないらしいので、LBサーバーでは2枚NICを挿すか、trunkやIPエイリアスを用いてネットワークが2つある構成に無いといけないみたいなので要注意。

http://hryksbt.b.osdn.me/archives/273