[CentOS6][IPVS+Keepalived] 同一サブネット内でWEBサーバの負荷分散(DSR)


Create: 2012/10/23
LastUpdate: 2012/10/27

同一サブネット内でWEBサーバの負荷分散を行うロードバランサを構築します。
構築イメージは下図のとおり。
クライアントから http://192.168.1.70/ にアクセスすると、WEBサーバ#1、WEBサーバ#2 に負荷分散します。
なお、Keepalived のルーティング方式はDSR(Direct Server Return)を使用します。下図のような同一サブネット内の構成ではルーティング方式にNATは使用できません。DSRとNATの違いについては「LVSで実現するロードバランサ - KLablabWiki」や「高トラフィックに対応できるLinuxロードバランサを目指して ~ LVSをNATからDSRへ」が参考になります。



1.仮想マシンの用意


ロードバランサ1台とWEBサーバ2台を XenServer6.02 の仮想マシンで用意します。
仮想マシンには、 こちら の手順で最小構成の CentOS6.0 をインストールしたあと、CentOS6.3 に yum で update しました。
この時点でのサーバの状態は以下のとおり。
  • OS: CentOS6.3
  • 導入パッケージ: 最小構成
  • デフォルト言語: ja_JP.UTF-8
  • タイムゾーン: Asia/Tokyo
  • SELinux: 無効
  • ファイヤーウォール: iptables 停止、ip6tables 停止

2.ロードバランサの構築


epel レポジトリ から keepalived と ipvsadm をインストールします。 ipvsadm は、IPVSを制御するためのツールです。
# yum --enablerepo=epel install keepalived ipvsadm 
keepalived を以下のように設定します。
  • スケジューリングアルゴリズム: rr (round-robin)
  • ヘルスチェック種別: HTTP_GET
  • ヘルスチェックページ: /index.html
  • ヘルスチェックの条件: ステータスコードが200
  • ヘルスチェックのタイムアウト: 5秒
設定ファイル(/etc/keepalived/keepalived.conf)の内容は以下のとり。
# vi /etc/keepalived/keepalived.conf
! IPVS

virtual_server_group WEB_GROUP1 {
  192.168.1.70 80
}

virtual_server group WEB_GROUP1 {
  delay_loop   3
  lvs_sched    rr
  lvs_method   DR
  protocol     TCP
  virtualhost  example.org

  real_server 192.168.1.81 80 {
    weight 1
    inhibit_on_failure
    HTTP_GET {
      url {
        path /index.html
        status_code 200
      }
    }
    connect_port    80
    connect_timeout 5
  }

  real_server 192.168.1.82 80 {
    weight 1
    inhibit_on_failure
    HTTP_GET {
      url {
        path /index.html
        status_code 200
      }
    }
    connect_port    80
    connect_timeout 5
  }
}
設定ファイルの各パラメータの意味については、以下のページが参考になります。
Keepalived の設定ファイルに記載した仮想IP(192.168.1.70)をeth0にIPエイリアスします。今回は動作確認したいだけなので、一時的な設定にしています。再起動すると、この設定は消えます。再起動しても消えないようにしたい場合は、 ここ を参考にしてください。
# ifconfig eth0:0 192.168.1.70
ロードバランサのネットワーク関連の状態は以下のとおり。赤字はコマンド。
# ifconfig -a
eth0      Link encap:Ethernet  HWaddr 46:C2:09:46:6D:DC
          inet addr:192.168.1.61  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: 2001:c90:8023:a9d1:44c2:9ff:fe46:6ddc/64 Scope:Global
          inet6 addr: fe80::44c2:9ff:fe46:6ddc/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:12608 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2262 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2448862 (2.3 MiB)  TX bytes:295391 (288.4 KiB)
          Interrupt:24

eth0:0    Link encap:Ethernet  HWaddr 46:C2:09:46:6D:DC
          inet addr:192.168.1.70  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:24

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.1.0     *               255.255.255.0   U     0      0        0 eth0
link-local      *               255.255.0.0     U     1002   0        0 eth0
default         192.168.1.1     0.0.0.0         UG    0      0        0 eth0
# service iptables status
iptables: ファイアウォールが稼働していません。


3.WEBサーバの構築


以下、WEBサーバ2台を同じように構築します。
まず、Apache をインストールします。
# yum install httpd 
動作確認とヘルスチェックを兼ねたページを作成します。動作確認でどちらのWEBサーバで動いたかわかるように、WEBサーバ#1 と WEBサーバ#2 ではページの内容を変えます。
# cat /var/www/html/index.html
<html>
<head>
 <title>WEB#1 - TOP PAGE</title>
</head>
<body>
 <h1>WEB#1 - Top Page</h1>
</body>
</html>
Apache を起動します。
# service httpd start
iptables コマンドを使用して、ロードバランサの仮想IP(192.168.1.70)宛てのパケット自分宛にDNATします。これは、DSR構成時だけに必要な対応です。
# iptables -t nat -A PREROUTING -p tcp -d 192.168.1.70 -j REDIRECT
WEBサーバのネットワーク関連の状態は以下のとおり。赤字はコマンド
# ifconfig -a
eth0      Link encap:Ethernet  HWaddr 46:A5:F7:B9:DE:06
          inet addr:192.168.1.81  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: 2001:c90:8023:a9d1:44a5:f7ff:feb9:de06/64 Scope:Global
          inet6 addr: fe80::44a5:f7ff:feb9:de06/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:15240 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3282 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2740599 (2.6 MiB)  TX bytes:471679 (460.6 KiB)
          Interrupt:247

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:18 errors:0 dropped:0 overruns:0 frame:0
          TX packets:18 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1380 (1.3 KiB)  TX bytes:1380 (1.3 KiB)

# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.1.0     *               255.255.255.0   U     0      0        0 eth0
link-local      *               255.255.0.0     U     1002   0        0 eth0
default         192.168.1.1     0.0.0.0         UG    0      0        0 eth0
# service iptables status
テーブル: nat
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination
1    REDIRECT   tcp  --  0.0.0.0/0            192.168.1.70

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination


4.動作確認


WEBサーバ2台でApacheが起動していることを確認したら、ロードバランサで Keepalived を起動します。
# service keepalived start 
ロードバランサで ipvsadm コマンドを実行して、仮想サーバテーブルにエントリが追加されているか確認します。
# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.1.70:80 rr
  -> 192.168.1.81:80              Route   1      0          0
  -> 192.168.1.82:80              Route   1      0          0
クライアントからブラウザで http://192.168.1.70/ にアクセスします。
再表示ボタンをクリックすると下図のページが交互に表示され負荷分散を確認できます。
ちにみに、ここではIE7を使用して確認していますが、IE7以外のブラウザで、毎回、"favicon.ico" をGETするタイプのブラウザは、ページが切り替わりません。再表示するたびに2回リクエストし、WEBサーバ#1から "index.html" をGETし、WEBサーバ#2から "favicon.ico" をGETするからです。





WEBサーバ#1のログを見ると、以下のとおり。"KeepAliveClient"は、ロードバランサのヘルスチェックです。クライアントからのアクセスには、クライアントのIPアドレスが記録され、ロードバランサからのアクセスは、仮想IPではなく実IPが記録されています。
192.168.1.61 - - [24/Oct/2012:09:44:36 +0900] "GET /index.html HTTP/1.0" 200 105 "-" "KeepAliveClient"
192.168.1.61 - - [24/Oct/2012:09:44:42 +0900] "GET /index.html HTTP/1.0" 200 105 "-" "KeepAliveClient"
192.168.1.10 - - [24/Oct/2012:09:44:47 +0900] "GET / HTTP/1.1" 200 105 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
192.168.1.61 - - [24/Oct/2012:09:44:48 +0900] "GET /index.html HTTP/1.0" 200 105 "-" "KeepAliveClient"
ちなみに、この環境では、ロードバランサやWEBサーバから "curl http://192.168.1.70/" のようにして、ロードバランサにアクセスすることはできません。