ラズパイでサーバーを構築していると、いつダウンするか分かりません。そんな時でも、サーバーを冗長化することで稼働し続けるシステムにできないかと考え、「Keepalived」を使った冗長化システムを構築したので紹介します。
今までのシステム構成は以下です。
この構成だと、稼働中のMasterがダウンすると転送先が途絶えてしまうので、手動でスレーブ側に切り替えるまでサービスが停止してしまいます。障害はある日突然おきてしまうので、すぐに切り替えることができない場合も想定されます。まずいです・・・・
そこで、それらの問題を解決できる、Keepalivedを使った冗長化システムを考えてみました。ポイントは、ルータの転送先アドレスは固定にしたいので、VIP(仮想IP)用います。冗長化したサーバー間のやり取りは、Keepalivedを使えば、VRRP(Virtual Router Redundancy Protocol)を実現できるので、障害発生時に自動でSlave側に切り替えてくれるはずです。
では、実際にシステムを組んでみて検証してみます。
まずは、Keepalivedをインストールします。
$sudo apt-get install keepalived
今回のシステムでは、VIP(仮想IP)を使うので、システムのデバイスに割り当てられていないIPアドレスをバインドしてやる必要があります。
$su #echo 1 > /proc/sys/net/ipv4/ip_nonlocal_bind
上記コマンドで一時的に割り付けられますが、再起動すると設定がきえてしまうので、再起動後も反映されるためには以下の値を/etc/sysctl.confに追記して設定を反映します。
↓/etc/sysctl.confに以下を追記 net.ipv4.ip_nonlocal_bind = 1 $sudo sysctl -p
今回のシステムに合わせて、keepalivedの設定を作成します。「/etc/keepalived/keepalived.conf」という新しいファイルを作成して編集します。
Master側の設定ファイルです。
設定で注意するポイントは以下です。
- virtual_router_idとauth_passは、MasterとSlaveで同じ値に設定
- priorityの設定は、master側を高い値に設定
- masterとslave側のIPアドレスとvirtual ipaddressを同じサブネットで設定
master側の設定ファイル「keepalived.conf」の記載例です。
global_defs {
vrrp_garp_master_refresh 60
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 150
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
# ユニキャスト設定の補足を参照
# unicast_peer {
# 192.168.30.11
# 192.168.30.12
# }
virtual_ipaddress {
192.168.30.20
}
}
slave側の設定ファイル「keepalived.conf」の記載例です。priority の設定値をmaster側より低い値に設定しています。
global_defs {
vrrp_garp_master_refresh 60
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1234
}
# ユニキャスト設定の補足を参照
# unicast_peer {
# 192.168.30.11
# 192.168.30.12
# }
virtual_ipaddress {
192.168.30.20
}
}
以上で、設定は完了です。設定を反映させるためにkeepalivedを再起動します。
$ sudo service keepalived restart
keepalivedが正しく動作しているかを検証します。
まずは、master側の状態を確認します。master側もslave側も稼働している場合は、priorityの設定値が高いmaster側にVIPが割り付けられます。(期待通りです)
$ ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 ・・・(省略) inet 192.168.30.11/24 brd 192.168.30.255 scope global noprefixroute eth0 ★ここは設定したmaster側のIPアドレス valid_lft forever preferred_lft forever inet 192.168.30.20/32 scope global eth0 ★ここがVIPのアドレス ・・・(省略) valid_lft forever preferred_lft forever 3: wlan0: mtu 1500 qdisc noop state DOWN group default qlen 1000 ・・・(省略)
続いて、slave側の状態を確認します。master側もslave側も稼働している場合は、priorityの設定値が低いslave側にはVIPが割り付けられません。VIPの割り付けがないですね。(期待通りです)
$ ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 ・・・(省略) inet 192.168.30.12/24 brd 192.168.30.255 scope global noprefixroute eth0 ★ここは設定したslave側のIPアドレス ★ここにVIPの割り付けがないことを確認 ・・・(省略) valid_lft forever preferred_lft forever 3: wlan0: mtu 1500 qdisc noop state DOWN group default qlen 1000 ・・・(省略)
では、master側のEhternetケーブルを抜いてみます。物理的にケーブルを抜いてみました。
slave側の状態を再度確認します。master側がダウンしているので、VRRPで障害を検出して、slave側にVIPが割りつけられます。(期待通りです)
$ ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 ・・・(省略) inet 192.168.30.12/24 brd 192.168.30.255 scope global noprefixroute eth0 ★ここは設定したslave側のIPアドレス valid_lft forever preferred_lft forever inet 192.168.30.20/32 scope global eth0 ★ここがVIPのアドレス ・・・(省略) valid_lft forever preferred_lft forever 3: wlan0: mtu 1500 qdisc noop state DOWN group default qlen 1000 ・・・(省略)
最後に、master側のEhternetケーブルを挿し戻します。
slave側の状態を確認します。master側が復活したので、priorityの設定値が低いslave側にはVIPが割り付けられません。(期待通りです)
$ ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 ・・・(省略) inet 192.168.30.12/24 brd 192.168.30.255 scope global noprefixroute eth0 ★ここは設定したslave側のIPアドレス ★ここにVIPの割り付けがないことを確認 ・・・(省略) valid_lft forever preferred_lft forever 3: wlan0: mtu 1500 qdisc noop state DOWN group default qlen 1000 ・・・(省略)
master側の状態を確認します。master側が復活すると、priorityの設定値が高いmaster側にVIPが割り付けられます。(全て期待通りです)
$ ip a 1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 ・・・(省略) inet 192.168.30.11/24 brd 192.168.30.255 scope global noprefixroute eth0 ★ここは設定したmaster側のIPアドレス valid_lft forever preferred_lft forever inet 192.168.30.20/32 scope global eth0 ★ここがVIPのアドレス ・・・(省略) valid_lft forever preferred_lft forever 3: wlan0: mtu 1500 qdisc noop state DOWN group default qlen 1000 ・・・(省略)
全て期待通りに動作していることが確認できました。これでmaster側がダウンした場合でも、slave側に切り替わってサービスを継続できます。ラズパイでサーバーを稼働している場合は、冗長化をおこなうことが重要だと思います。MicroSDが壊れた場合でも、安心して交換作業ができますね。同時に壊れたらどうするかということも頭によぎりましたが、考えないことにしました・・・・(3重化?)
【ユニキャスト設定の補足】
暫く稼働していて気づいたのですが、MASTER側のログに1秒間隔でWarningメッセージが出力されていました。(BACKUP側には出力されず)1秒間隔っていうので…マスタ側からスレーブ側に送っている「VRRP Advertisement」の送信間隔と一致していると思い設定を見直しました。マルチキャストでやり取りできる場合は、設定ファイル(keepalived.conf)の以下のブブはいらないはずです。
unicast_peer {
192.168.30.11
192.168.30.12
}
しかも、マスタ側からスレーブ側の送信するので、以下のように記載しないと1秒周期で鬼のようなWarningメッセージがログに出力されます….
MASTER側の設定ファイル
unicast_src_ip 192.168.30.11
unicast_peer {
192.168.30.12
}
BACKUP側の設定ファイル
unicast_src_ip 192.168.30.12
unicast_peer {
192.168.30.11
}
とりあえず、マルチキャスト設定(コメント扱い)と、上記のユニキャスト設定にして試してみましたが、どちらの場合もWarningメッセージは出力されないようになりました。
マルチキャストが通らない場合は、ユニキャスト設定が必要になると思いますので、環境に合わせて設定されると良いと思います。
【ユニキャストとマルチキャストについて】
ユニキャストとは、単一のアドレスを指定して、1対1で行われるデータ通信のことです。
マルチキャストとは、特定のアドレスを指定して、1対複数で行われるデータ通信のことです。