2006年08月24日
こんなに簡単! Linuxでロードバランサ (1)
DSASのロードバランサは高価なアプライアンス製品ではなく、LinuxのLVS (Linux Virtual Server)を利用しています。
安価、というか、ハードウエア以外は金銭的コストがゼロなので、一般のクライアントからのアクセスを受ける外部ロードバランサのほかに、内部サービス用のロードバランサも配置しています。それぞれactive, backupで2台ずつあるので合計で4台もロードバランサがあることになります。(こんな構成を製品を使って組んだら数千万円すっとびますね)
また、ネットワークブートでディスクレスな構成にしているので、ハードディスが壊れてロードバランサがダウンした、なんてこともありません。
ですので「ロードバランサは高くてなかなか導入できない」という話を耳にする度にLVSをお勧めしているのですが、どうも、
等々の不安の声も聞きます。
そこでこれから数回に渡って、How toスタイルでLinuxでロードバランサを作ってみたいと思います。
今回は初回ということで、ごくごく基本的な
というところまでやってみたいと思います。
では、はじまりはじまり〜
安価、というか、ハードウエア以外は金銭的コストがゼロなので、一般のクライアントからのアクセスを受ける外部ロードバランサのほかに、内部サービス用のロードバランサも配置しています。それぞれactive, backupで2台ずつあるので合計で4台もロードバランサがあることになります。(こんな構成を製品を使って組んだら数千万円すっとびますね)
また、ネットワークブートでディスクレスな構成にしているので、ハードディスが壊れてロードバランサがダウンした、なんてこともありません。
ですので「ロードバランサは高くてなかなか導入できない」という話を耳にする度にLVSをお勧めしているのですが、どうも、
- なんか難しそう
- ちゃんと動くか不安
- 性能が出ないんじゃないか
等々の不安の声も聞きます。
そこでこれから数回に渡って、How toスタイルでLinuxでロードバランサを作ってみたいと思います。
今回は初回ということで、ごくごく基本的な
- 複数のWebサーバにロードバランスする
というところまでやってみたいと思います。
では、はじまりはじまり〜
構成図と下準備
今回はサーバが3台登場します。
- lv1 = ロードバランサ
- w101 = Webサーバその1
- w102 = Webサーバその2
ネットワーク構成はこんな感じです。
<internet>
│
//
│
│[10.10.31.11]
│{10.10.31.100} = example.org
┌─┴─┐
│ lv1 │
└─┬─┘
│[192.168.31.11]
│
━━┯━━━━━┷━━━━┯━━━━━━━━ 192.168.31.0/24
│ │
│[192.168.31.101] │[192.168.31.102]
┌─┴─┐ ┌─┴─┐
│ w101 │ │ w102 │
└───┘ └───┘
- 10.10.31.0/24
- 説明上、このアドレス帯をグローバルアドレスとして使います。
- 10.10.31.11 : lv1の外側(eth0)のIPアドレスです。
- 10.10.31.100: Webサービス用のバーチャルIPアドレス(VIP)です。ブラウザはこのIPアドレスに向けてHTTPアクセスしてきます。
- 10.10.31.11 : lv1の外側(eth0)のIPアドレスです。
- 192.168.31.0/24
- 構内のネットワーク用のアドレス帯です。
- 192.168.31.11: lv1の内側(eth1)のIPアドレスです。
- 192.168.31.101: リアルサーバw101のIPアドレス(RIP)です。
- 192.168.31.102: リアルサーバw102のIPアドレス(RIP)です。
- 192.168.31.11: lv1の内側(eth1)のIPアドレスです。
サーバが3台なので、そのへんの古いPCを掻き集めれば構成できると思いますし、VMwareやParallels Desktopなどをお持ちの方はさくっと組めると思いますので、実際に手を動かして確認してもらえればと思います。
Webサービスのリアルサーバとなるw101、w102ではApache等のHTTPサーバが動いていて、バーチャルドメイン「example.org」でHTTPアクセスできるようになっているものとします。
例えばこんな感じに。便宜的に、w101とw102とで異なるコンテンツを返すようにしています。
lv1$ curl -H 'Host: example.org' http://w101/
w101 nano
lv1$ curl -H 'Host: example.org' http://w102/
w102 desu
ロードバランサの設定
さて、前置きが長くなりましたが、いよいよロードバランサとなるlv1をいじります。
まずはIPVSをサポートしたkernelをビルドします。今回は(ディストリビューション付属のものではなく)素のkernel 2.6.16.27を使います。
具体的なkernel設定は、kernel 2.4の例ですがLVS-mini-HOWTO 3.15.3. 2.4.x kernelsを参考にしてください。
とりあえずならば、以下のカテゴリの項目を全部モジュールにしてしまえばいいでしょう。
- Networking
- Networking options
- ★いくつか必要。LVS-mini-HOWTO 3.15.3. 2.4.x kernelsを参考に。
- IP: Virtual Server Configuration
- ★この下全部
- ★この下全部
- Network packet filtering (replaces ipchains)
- Core Netfilter Configuration
- ★この下全部
- ★この下全部
- IP: Netfilter Configuration
- ★この下全部
- ★この下全部
- Core Netfilter Configuration
- ★いくつか必要。LVS-mini-HOWTO 3.15.3. 2.4.x kernelsを参考に。
- Networking options
新しいkernelで起動できたら、IPVSの管理コマンド、ipvsadm をインストールします。
ipvsadmはkernelのIPVSのバージョンに依存します。
ipvsadmをコンパイルしたときのIPVSのバージョンと、kernelのIPVSのバージョンが異なっていると期待した動作をしないことがあるので、kernelをバージョンアップした際は気をつけてください。
ipvsadmのIPVSバージョンは次のようにして確認できます。
# ipvsadm -v
ipvsadm v1.24 2005/12/10 (compiled with popt and IPVS v1.2.1)
kernelのIPVSバージョンは次のようにして確認できます。
$ grep IP_VS_VERSION_CODE /usr/src/linux/include/net/ip_vs.h
#define IP_VS_VERSION_CODE 0x010201
kernel 2.6.10で、IPVSが1.2.0から1.2.1に変わりました。ディストリビューション付属のipvsadmは1.2.1より古いIPVSでコンパイルされているかもしれないので、今回はソースからipvsadmをコンパイルしなおします。
ipvsadmのソースコードは
からダウンロードできます。
ipvsadmのインストールは次のようにします。
$ wget http://www.linux-vs.org/software/kernel-2.6/ipvsadm-1.24.tar.gz
$ tar zxf ipvsadm-1.24.tar.gz
$ cd ipvsadm-1.24
$ make
# make install
# ipvsadm --version
ipvsadm v1.24 2005/12/10 (compiled with popt and IPVS v1.2.1)
いよいよipvsadmを使ったロードバランスの設定です。
まずは、http://example.orgのサービス用のバーチャルIPアドレス(VIP)である、10.10.31.100をlv1の上流NIC (eth0) に IP aliasします。ここではiproute2のipコマンドを使っていますが、ifconfigを使っても構いません。
lv1# ip addr add 10.10.31.100 label eth0:100 dev eth0
lv1$ ip addr show eth0 label eth0:100
inet 10.10.31.100/32 scope global eth0:100
これでlv1がVIP宛てのパケットを受け取れるようになったので、おまたせのロードバランスの設定です。
まずは念のため設定をリセットして、
lv1# ipvsadm -C
VIP (10.10.31.100) を追加します。ここでは、HTTP (ポート80) を、最小コネクション (lc) でリアルサーバにバランスするように設定します。
ipvsadm -A -t <VIP>:<ポート> -s <バランスアルゴリズム>
lv1# ipvsadm -A -t 10.10.31.100:80 -s lc
続いて、VIPにひも付くリアルサーバのIPアドレス(RIP)を追加します。
「パケット転送方法」は3つあります。
- -g --gatewaying
- Direct Server Return (DSR)
- -i --ipip
- IPIPのカプセリング
- -m --masquerading
- NAT
詳細は別の回にゆずります。今回は、構成が簡単なNAT (-m) にします。ちなみに、NATにした場合は、リアルサーバが返すパケットは、lv1を通ってクライアントに返されます。(一方、DSRの場合は戻りのパケットはlv1を通らないで返すことができるので、ロードババランサの負荷が軽減されます)
ipvsadm -a -t <VIP>:<ポート> -r <RIP> <パケット転送方法>
lv1# ipvsadm -a -t 10.10.31.100:80 -r 192.168.31.101 -m
lv1# ipvsadm -a -t 10.10.31.100:80 -r 192.168.31.102 -m
ちゃんと設定できたか確認してみましょう。
lv1# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.10.31.10:80 lc
-> 192.168.31.101:80 Masq 1 0 0
-> 192.168.31.102:80 Masq 1 0 0
IPVSの設定はこれで終わりです。たったこれだけです。どうでしょうか? 意外と簡単だったのではないでしょうか?
ただ、lv1とリアルサーバとの間でパケットをやり取りするにはもうちょっと設定が必要です。
まず、lv1でパケット転送を有効にします。
lv1# echo '1' > /proc/sys/net/ipv4/ip_forward
次回再起同時も有効になるように、/etc/sysctl.confに
net.ipv4.ip_forward = 1
と追加してsysctl -pしておきましょう。
最後にリアルサーバw101、w102のデフォルトゲートウェイの設定です。先にipvsadmで設定したように、今回はNAT方式を使うので、リアルサーバはlv1にパケットを返さなければなりません。ですので、リアルサーバのデフォルトゲートウェイをlv1(の内側のNICの192.168.31.11)に向けます。
Debianの場合は、/etc/network/interfacesで指定します。w101の/etc/network/interfacesは次のようになります。
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.31.101
netmask 255.255.255.0
network 192.168.31.0
broadcast 192.168.31.255
gateway 192.168.31.11
これでロードバランスできるようになりました。では早速試してみましょう!
lv1の外から、10.10.31.100にhttp://example.orgなHTTPリクエストを何回かしてみます。
client$ curl -H 'Host: example.org' http://10.10.31.100/
w101 nano
client$ curl -H 'Host: example.org' http://10.10.31.100/
w102 desu
どうでしょうか? うまくロードバランスされたでしょうか?
クライアントマシン、lv1、w101、w102でtcpdumpでパケットダンプしながらHTTPアクセスしてみると、パケットの流れが見えておもしろいと思います。
うまくいったら、試しに、リアルサーバw102をサービスから外してみましょう。
lv1で以下のように実行します。
lv1# ipvsadm -d -t 10.10.31.100:80 -r 192.168.31.102
lv1# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.10.31.100:80 lc
-> 192.168.31.101:80 Masq 1 0 4
外したら、先ほどと同じように、http://example.orgにアクセスしてみましょう。全て、w101から応答が返ってくるはずです。
リアルサーバをサービスから外すにはもう一つ方法があります。
ipvsadm -Lnを見ると、「Weight」という項目があります。
バランスアルゴリズムによってはリアルサーバごとに重みづけすることができ、その値が「Weight」なんですが、ここをゼロにすると、IPVSの設定上はリアルサーバが登録されていてもweight 0のサーバにはバランスしないようにすることができます。
では再度、w102を追加して (ipvsadm -a -t 10.10.31.100:80 -r 192.168.31.102 -m) w102にもバランスされるのを確認してから、weightをゼロにしてみます。
lv1# ipvsadm -e -t 10.10.31.100:80 -r 192.168.31.102 -m -w 0
lv1# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 10.10.31.100:80 lc
-> 192.168.31.101:80 Masq 1 0 0
-> 192.168.31.102:80 Masq 0 0 0
w102のWeightがゼロになってますね。
この状態でhttp://example.orgにアクセスすると、w101からだけ応答が返ってくるのが確認できると思います。
w102のWeightを1にしてサービスに復帰させるには次のようにします。
lv1# ipvsadm -e -t 10.10.31.100:80 -r 192.168.31.102 -m -w 1
まとめ
最初の一歩ということで、複数のリアルサーバにNAT方式でロードバランスするところまで説明しました。
かなりはしょったところがあるので、その他の設定項目やパラメータはドキュメントを参照してもらえればと思います。
さて、ここまでで負荷分散はできるようになったのですが、実は冗長化はできていません。w102のWebサーバがダウンしても、lv1はw102にパケットを転送してしまいます。
次回は冗長化の実現ということで、keepalivedを使って、Webサーバへのヘルスチェックとリアルサーバの管理をやってみたいと思います。
参考
- LVS-mini-HOWTO
- LVS-HOWTO
- 20. LVS: Running a firewall on the director: Interaction between LVS and netfilter (iptables).
IPVSとNetfilter (iptables) の関係の図があります。
- 20. LVS: Running a firewall on the director: Interaction between LVS and netfilter (iptables).
- 『サーバ負荷分散技術』
- 『CDNプロトコル入門 - アクセス集中からWebを守る』
この記事へのトラックバック
1. あ〜あ。 [ cage ] 2006年10月30日 17:47
DSAS開発者の部屋:こんなに簡単! Linuxでロードバランサ (1)DSASのロードバランサは高価なアプライアンス製品ではなく、LinuxのLVS (Linux Virtual Server)を利用しています。
良いこと知っちゃったよ。
って知らなかったのはオレだけ???
2. Linux Virtual Server [ エセプログラマーの戯言 ] 2008年01月24日 07:08
Linuxでの、負荷分散システムの一つに、[http://www.linux-vs.org/ LVS](Linux Virtual Server)というものがあります。
これは、オープンソースで提供されており、無料で使用することが出来ます。
こいつを使って、負荷分散をやってみようと思い、調べて見たところ...
3. LVS [ エセプログラマーの戯言 ] 2008年01月28日 05:18
LVSについて、[http://blogs.yahoo.co.jp/yohei0511/1453793.html 前回]、「ipvsadmをソースからコンパイルしてインストールしなければならない」と書きましたが、yum でインストールしたやつで出来ました。
参考URL:
http://d.hatena.ne.jp/yotena/20070304/1172994170
...
4. こんなに簡単! Linuxでロードバランサ [ pligg.com ] 2010年03月16日 10:42
低価格で冗長化を実現する。
<br />
<br />ただし、ハートビートのタイムラグが大きいので完全ノンストップ環境は今のところまだ難しい。
5. IPVSでopenblocks600をロードバランサ化 [ インフラ技術の実験室 ] 2011年05月22日 22:19
IPVSを使用してOpenblocks600をロードバランサにするための設定を説明します。
6. SAS開発者の部屋:こんなに簡単! Linuxでロードバランサ (1) [ ] 2012年02月03日 18:35
DSAS開発者の部屋:こんなに簡単! Linuxでロードバランサ (1)
この記事へのコメント
1. Posted by パー子 2006年12月08日 15:54
ディストリビューション付属のものではなく素のkernel 2.6.16.27を使う!? うわぁートラブッたら対応できないレベルの話だなぁ。LVS-mini-HOWTO 3.15.3. 2.4.x kernelsを読め!? 英語でこれだけのボリュームのある文書を十分に理解するなんて敷居が高すぎるぅ・・・。というのが「難しそう」の内容だと思うのですが・・・。