LVS環境構築
はじめに
centos5.6で、LVS環境を構築する。
環境構成は、以下の通り。LVSはNATではなく、DSRで稼働させる。
------------- -------------------|client(AWS)| | ------------- Global IP1 Global IP2 ~~~~~~~~~~ Internet ~~~~~~~~~~ | -------- |router| -------- | ------------------------------------------------------------- | | | | | ---VIP:192.168.1.30-- | | | | | | | | 192.168.1.22 192.168.1.23 192.168.1.20 192.168.1.21 192.168.1.18 -------- -------- -------- -------- -------- | LVS1 | -- VRRP -- | LVS2 | | web1 | | web2 | | sorry | -------- -------- -------- -------- --------
web/sorryサーバには、それぞれ以下の文字列を表示するページを用意しておく。
web1 : test1
web2 : test2
sorry: sorry
また、web1,2のヘルスチェック用に /health.cgi ページを用意しておく(status code 200を返すだけ)。
LVS1,2 環境構築
パッケージインストール
LVS1,2サーバに、それぞれパッケージをインストール
rp_filter設定
今回構築している環境では、Interfaceが1つのみなので、rp_filterは有効(1)にしたままにしている。
もし、Interfaceが追加されて、外(eth1)/内(eth0)の2枚環境になるようであれば、
以下の設定をすれば良いと思う。
keepalived.conf設定
LVSの冗長性を確保するためのkeepalivedを利用する。
keepalivedのパラメータ設定として、keepalived.confを設定する。
ここでは、メール通知設定などは省略する。
※本番運用であれば欠かせないと思いますが。
各パラメータの意味は、下記サイトや「24時間365日 サーバ/インフラを支える技術」などを参考に。
LVSを使ったブローカーの構築:「keepalived.conf」についての説明
本家サイトのUserGuide
- LVS1 /etc/keepalived/keepalived.conf
virtual_server_group HTTP100 { 192.168.1.30 80 } virtual_server group HTTP100 { delay_loop 3 lvs_sched lc lvs_method DR protocol TCP virtualhost www.example.org sorry_server 192.168.1.18 80 # web1 real_server 192.168.1.20 80 { weight 1 inhibit_on_failure # health check HTTP_GET { url { path /health.cgi status_code 200 } connect_timeout 3 } } # web2 real_server 192.168.1.21 80 { weight 1 inhibit_on_failure # health check HTTP_GET { url { path /health.cgi status_code 200 } connect_timeout 3 } } } # VRRP vrrp_instance VI { state BACKUP interface eth0 garp_master_delay 5 virtual_router_id 1 priority 101 nopreempt advert_int 1 authentication { auth_type PASS auth_pass himitsu } virtual_ipaddress { 192.168.1.30/24 dev eth0 } }
- LVS2 /etc/keepalived/keepalived.conf
virtual_server_group HTTP100 { 192.168.1.30 80 } virtual_server group HTTP100 { delay_loop 3 lvs_sched lc lvs_method DR protocol TCP virtualhost www.example.org sorry_server 192.168.1.18 80 # web1 real_server 192.168.1.20 80 { weight 1 inhibit_on_failure # health check HTTP_GET { url { path /health.cgi status_code 200 } connect_timeout 3 } } # web2 real_server 192.168.1.21 80 { weight 1 inhibit_on_failure HTTP_GET { url { path /health.cgi status_code 200 } connect_timeout 3 } } } # VRRP vrrp_instance VI { state BACKUP interface eth0 garp_master_delay 5 virtual_router_id 1 priority 100 nopreempt advert_int 1 authentication { auth_type PASS auth_pass himitsu } virtual_ipaddress { 192.168.1.30/24 dev eth0 } }
web1,2、sorry 環境構築
iptables設定
webサーバ側では、VRRPで指定した仮想IP(192.168.1.30)は直接持たず、
iptablesによるアドレス変換(DNAT)で処理させる。
# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
#
# iptables -t nat -A PREROUTING -d 192.168.1.30 -j REDIRECT
# /etc/init.d/iptables save
# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
REDIRECT all -- anywhere 192.168.1.30
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
#
# /etc/init.d/iptables restart
LVS環境起動
LVS1,2でkeepalivedを起動し、動作確認を行う。
まずは、LVS1をmaster、LVS2をbackup環境として稼働させる。
keepalived起動
- LVS1 作業
masterとなる LVS1 からkeepalivedを起動する。
# /etc/init.d/keepalived start
# tail /var/log/messages
〜
Keepalived_vrrp: VRRP_Instance(VI) Transition to MASTER STATE
Keepalived_vrrp: VRRP_Instance(VI) Entering MASTER STATE
Keepalived_vrrp: VRRP_Instance(VI) setting protocol VIPs.
Keepalived_vrrp: VRRP_Instance(VI) Sending gratuitous ARPs on eth0 for 192.168.1.30
Keepalived_vrrp: Netlink reflector reports IP 192.168.1.22 added
Keepalived_healthcheckers: Netlink reflector reports IP 192.168.1.22 added
avahi-daemon[3291]: Registering new address record for 192.168.1.30 on eth0.
Keepalived_vrrp: VRRP_Instance(VI) Sending gratuitous ARPs on eth0 for 192.168.1.30
#
実際にipコマンドで仮想IPが設定されているか確認する。
# ip addr show dev eth0
2: eth0:
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 192.168.1.22/24 brd 192.168.1.255 scope global eth0
inet 192.168.1.30/24 scope global secondary eth0
#
- LVS2 作業
次にbackupとなる LVS2 のkeepalivedを起動する。
# /etc/init.d/keepalived start
# tail /var/log/messages
〜
Keepalived_vrrp: VRRP_Instance(VI) Entering BACKUP STATE
Keepalived_vrrp: VRRP sockpool: [ifindex(2), proto(112), fd(11,12)]
#
ipコマンドで仮想IPが設定されて"いない"事を確認する。
# ip addr show dev eth0
2: eth0:
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 192.168.1.23/24 brd 192.168.1.255 scope global eth0
#
動作確認
ここまでで、LVS環境の構築ができたので、クライアント環境からHTTPリクエストを投げて
LVS環境を通し、分散/冗長されているか動作確認する。
パターン1:正常系
master経由で、web1,2にリクエストが振られ、クライアント環境へ意図した応答が変えるか確認。
LVS1:master LVS2:backup web1:正常稼働 web2:正常稼働
- クライアントからのリクエスト
# while(true); do curl -H 'Host: www.example.org' http://[Global IP1]; sleep 1; done
test1
test2
test1
test2
〜
#
パターン2:異常系
lvs1で障害が発生し、LVS2がmasterとなった状態で、
web1,2にリクエストが振られ、クライアント環境へ意図した応答が変えるか確認。
LVS1:障害! LVS2:master web1:正常稼働 web2:正常稼働
- クライアントからのリクエスト
# while(true); do curl -H 'Host: www.example.org' http://[Global IP1]; sleep 1; done
test1
test2
test1
test2
〜
#
ただし、LVS1のkeepalivedをダウンさせた際、クライアントからのリクエストが1度コネクションエラーとなった。
パターン3:異常系
web1で障害(apacheダウン)が発生した状態で、master経由で web2にリクエストが振られ、クライアント環境へ意図した応答が変えるか確認。
LVS1:master LVS2:backup web1:障害! web2:正常稼働
- クライアントからのリクエスト
# while(true); do curl -H 'Host: www.example.org' http://[Global IP1]; sleep 1; done
test2
test2
test2
test2
〜
#
パターン4:異常系
web2で障害(apacheダウン)が発生した状態で、master経由で web2にリクエストが振られ、クライアント環境へ意図した応答が変えるか確認。
LVS1:master LVS2:backup web1:正常稼働 web2:障害!
- クライアントからのリクエスト
# while(true); do curl -H 'Host: www.example.org' http://[Global IP1]; sleep 1; done
test1
test1
test1
test1
〜
#
パターン5:異常系
web1,2で障害(apacheダウン)が発生した状態で、master経由で sorryにリクエストが振られ、クライアント環境へ意図した応答が変えるか確認。
LVS1:master LVS2:backup web1:障害! web2:障害! sorry:正常稼働
- クライアントからのリクエスト
# while(true); do curl -H 'Host: www.example.org' http://[Global IP1]; sleep 1; done
sorry
sorry
sorry
sorry
〜
#
からレスポンスが返る事が確認できた。