LVS+keepalived の設定 2

備忘録として、DSRによるLVSkeepalivedの設定を段階的に書く。

前提は以下とする。

  • LVSの転送方式はDSR
  • ネットワークは単一セグメントで超簡単なもの
  • OSはCentOS6.5

今回はkeepalivedを導入する。

ネットワーク構成

今回は前回と同じ、以下の構成。

  • LVSはeth0 = 192.168.1.100。さらに後々を考えてVirtualIPとしてeth0:0 = 192.168.1.10を設定。クライアントはこのアドレス(VIP)にアクセスする。
  • MySQL:Masterはeth0 = 192.168.1.200、ただしLVSとは関係ない。
  • MySQL:Slave1はeth0 = 192.168.1.201、MySQL:Slave2はeth0 = 192.168.1.202
  • 全サーバ(LVS + Slave1 + Slave2)は NetworkManagerとSELinuxをoffにする。

(LVS上の)keepalivedの設定

もしもLVSの設定をしていれば、それらを削除する。
具体的には:

  • ipvsadm -Cで設定をクリア
  • ifcfg-eth0:0など、VIP用の設定ファイルを削除。当然、ネットワークはrestart。
Firewall

3306番ポートを開けておく。

インストール

keepalivedパッケージをインストール。

# yum install keepalived
システムパラメータの設定

パケットフォワーディングを行うため、net.ipv4.ip_forwardを有効にする*1
具体的には/etc/sysctl.confを編集し、sysctl -pを実行する。

# vi /etc/sysctl.conf
net.ipv4.ip_forward = 1
# /sbin/sysctl -p
# cat /proc/sys/net/ipv4/ip_forward 
1
keepalived.confの設定

/etc/keepalived/keepalived.confを編集する。

# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived

# 障害通知関係の設定
global_defs {
   notification_email {
	# 障害通知メールの宛先
   	mail@example.com
   }
   # 障害通知メールの送信元
   notification_email_from mail@example.com
   # 障害通知メールを送信するSMTPサーバ名
   smtp_server 10.10.0.1
   smtp_connect_timeout 30
   # 障害発生したLVSを特定するための、一意な名前
   router_id LVS_1
}

# VirtualIP管理+LVS相互監視のための設定
vrrp_instance VI_1 {
    # “MASTER” or “”BACKUP
    state BACKUP
    # 監視するネットワークデバイス
    interface eth0
    #
    virtual_router_id 1
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # Virtual IPの指定
    virtual_ipaddress {
        192.168.1.10/24 dev eth0
    }
}

# 仮想サーバの設定
virtual_server 192.168.1.10 3306 {
    # 監視周期。単位は秒。
    delay_loop 30
    # 負荷分散方式。rr = ラウンドロビン
    lvs_sched rr
    # パケット転送方式。 DR = Direct Return
    lvs_method DR

   # rrなら不要。
 #    persistence_timeout 50

    # 監視するプロトコル
    protocol TCP
    # 全real serversがダウンした場合、Sorryサーバに向ける。
	# この構成の場合はMasterでもよいが、過負荷でマスターまでダウンさせるのも….
    #    sorry_server XXX.XXX.XXX.XXX YY

    # 実サーバ(Slave1)の設定
    real_server 192.168.1.201 3306 {
    # rrの重み付け
        weight 1
    # 設定すると、実サーバがダウンした場合、重みを0にする。
    # 後述するが、サーバが復活すると重みは設定値(ここでは1)に戻る。
        inhibit_on_failure

    # サーバ監視: TCPポートにアクセスするだけの超簡易的方法
        TCP_CHECK {
            connect_port 3306
            connect_timeout 30
            nb_get_retry 3
            delay_before_retry 3
        }
	# ダウンと判断した場合の実行スクリプトを書く。今回はパス。後でじっくり検討する。
        # notify_down "shell script" 
    }

    # 実サーバ(Slave2)の設定
    real_server 192.168.1.202 3306 {
        weight 1
        inhibit_on_failure
        TCP_CHECK {
            connect_port 3306
            connect_timeout 30
            nb_get_retry 3
            delay_before_retry 3
        }
        # notify_down "shell script" 
    }
}

設定が終ったらサービスを開始する。

# service keepalived start
設定確認

設定内容はipvsadmで確認できる。

# ipvsadm -S
-A -t 192.168.1.10:mysql -s wlc
-a -t 192.168.1.10:mysql -r 192.168.1.201:mysql -g -w 1
-a -t 192.168.1.10:mysql -r 192.168.1.202:mysql -g -w 1

# 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.10:3306 rr
  -> 192.168.1.201:3306           Route   1      0          0         
  -> 192.168.1.202:3306           Route   1      0          0 

ネットワークはifconfigでは確認できないので、ipコマンドで以下のようにする。

# ip addr show eth0
0: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:c3:3a:be brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
    inet 192.168.1.10/24 scope global secondary eth0
    inet6 fe80::20c:29ff:fec3:3abe/64 scope link 
       valid_lft forever preferred_lft forever

inetで(実と仮想の)2つのIPaddressが設定されていれば成功。

MySQL:Slaveの設定

MySQL:Slaveサーバ側の設定は前回のLVS単体のときと変わらず。
しかし情報がバラバラになると理解し難いので、ここにも書く。

Firewall

3306番ポートを開けておく。

MySQL

MySQLを初期化し、起動する。

# mysql_install_db

# mysqld_safe &

次に、Client:192.168.1.5 からアクセスできるように、ユーザ(ここではroot)の権限設定を行う。

# mysql
mysql> GRANT ALL ON *.* TO root@'192.168.1.5’
システムパラメータの変更

以下のパラメータを/etc/sysctl.confに追記する。

net.ipv4.conf.lo.arp_ignore = 1
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2

編集後、設定を反映させる。

# /sbin/sysvtl -p
仮想loopbackデバイス作成

LVSのVIPと同じIPをlo:0に登録。

# cd /etc/sysconfig/network-scripts
# cp ifcfg-lo ifcfg-lo:0
# vi ifcfg-lo:0
DEVICE=lo:0
IPADDR=192.168.1.10
# NETMASKはこれでなければならない。
NETMASK=255.255.255.255 
NETWORK=192.168.1.0
# If you're having problems with gated making 127.0.0.0/8 a martian,            
# you can change this to something else (255.255.255.255, for example)          
BROADCAST=192.168.1.255
ONBOOT=yes
NAME=loopback0

作成したら再起動。

# service network restart

動作確認

ClientからLVSのVIP(192.168.1.10)にアクセスすると、どちらかのスレーブに飛ぶ。

# mysql -h 192.168.1.10

LVS上で以下のコマンドを実行すると動作状況がみえる。

# 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.10:3306 rr
  -> 192.168.1.201:3306           Route   1      6          0         
  -> 192.168.1.202:3306           Route   1      5          0         

ここで意図的にSlave2をダウンさせる。
すると監視ルールに則って、Slave2の重みが0になる。

# 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.10:3306 rr
  -> 192.168.1.201:3306           Route   1      6          0         
  -> 192.168.1.202:3306           Route   0      5          0         

そして、Slave2を復旧(再起動)させると、重みが元に戻る。

# 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.10:3306 rr
  -> 192.168.1.201:3306           Route   1      9          0         
  -> 192.168.1.202:3306           Route   1      5          0         

WEBサーバならいいけども、DBの場合は一旦ダウンしたものを再起動した瞬間にサービス提供してはマズいはず*2


これが大変参考になった。

*1:net.ipv4.conf.default.rp_filterなどは有効のままでよさげ

*2:データの不一致が起きているかもしれないし、復旧作業のために起動したかもしれない