SEIL/x86 FujiとkeepalivedでVRRP

既存ルーターであるSEIL/x86 FujiとVRRPを組んで、MAP-Eゲートウェイが使用できない場合にPPPoE回線側にフォールバックするようにします。

SEIL/x86 FujiとkeepalivedでVRRP

先日書いた 味見日報 - MAP-E は仕様変更があった場合に急に繋がらなくなる可能性もありそうなので、既存ルーターであるSEIL/x86 FujiとVRRPを組んで、MAP-Eゲートウェイが使用できない場合にPPPoE回線側にフォールバックするようにします。

味見日報 - MAP-E (2) とも言う。

環境

SEIL/x86 Fuji

1
2
# show system version 
SEIL/x86 Fuji Ver. 7.02 (Release)

MAP-Eゲートウェイ

1
2
3
4
$ uname -a
Linux ipoe-gw 5.4.0-65-generic #73-Ubuntu SMP Mon Jan 18 17:25:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
$ dpkg -l keepalived | grep keepalived
ii  keepalived     1:2.0.19-2   amd64        Failover and monitoring daemon for LVS clusters

IPアドレスは以下のようにします。

  • 192.168.1.1: 既存ルーターのVIP
  • 192.168.1.2: 既存ルーター#1の実IP(SEIL側。PPPoEへのフォールバック用)
  • 192.168.1.4: MAP-EゲートウェイのVIP
  • 192.168.1.5: MAP-Eゲートウェイの実IP(MAP-Eゲートウェイ側)

設定

VRRPは以下の設定を行います。

  • Priority
    • MAP-Eゲートウェイ: 245
    • 既存ルーター(SEIL): 240
  • Preempt: On
    • MAP-Eが使えるときは常にMAP-Eを優先します
  • vrid: 4
    • VIPの末尾から採用

SEIL/x86 Fuji vrrp configuration

1行だけ。

1
vrrp lan1 add vrid 4 address 192.168.1.4/24 priority 240

!!! note SEIL/x86 Fujiはauthenticationをサポートしていない(RFC3768まで)ので、認証コードもありません。RFC5798があれば…

* https://www.seil.jp/doc/index.html#fn/vrrp/vrrpv2.html    
* https://tools.ietf.org/html/rfc5798

keepalived configuration

keepalivedでは、VRRPの設定以外に以下の設定も盛り込みます。

  • MAP-Eトンネル経由の通信で、想定したグローバルIPv4アドレスを使っているかチェックする

Install keepalived

まずはkeepalivedを入れます。

1
$ sudo apt install -y keepalived

Create MAP-E tunnel check script

MAP-Eのトンネルが機能しているかチェックするスクリプトを書きます。

1
2
3
#!/bin/bash

[[ "$(curl -s https://api.ipify.org)" == "192.0.2.1" ]]

!!! note * 192.0.2.1 は文書用アドレスなので、実際は自身の環境におけるMAP-EのグローバルIPv4アドレスを入れます。 * https://api.ipify.org は重くて応答が遅い場合があるので https://inet-ip.info/iphttps://checkip.amazonaws.com など、自分の環境から安定して応答が得られそうなサービスを使います。僕は最近 https://inet-ip.info/ip に変えました。

実行権限を与えておきます。成功時にexit code 0を返すようになっていればOKです。 この場合、アドレスが一致しないと1が返ります。

1
2
3
4
$ sudo chmod +x /etc/keepalived/check_mape.sh
$ sudo /etc/keepalived/check_mape.sh 
$ echo $?
0

Create keepalived.conf

/etc/keepalived/keepalived.conf を書きます。先ほど書いたスクリプトを vrrp_scriptscript に指定します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
vrrp_script check_mape {
    script "/etc/keepalived/check_mape.sh"
    interval 10  # Run script every i seconds
    fall 3       # If script returns non-zero f times in succession, enter FAULT state
    rise 2       # If script returns zero r times in succession, exit FAULT state
    timeout 5    # Wait up to t seconds for script before assuming non-zero exit code
}

vrrp_instance mape {
    state MASTER
    interface eth0
    garp_master_delay 5
    virtual_router_id 4
    priority 245
    preempt
    advert_int 1
    virtual_ipaddress {
        192.168.1.4
    }
    track_script {
        check_mape
    }
}

!!! note interval / fall / rise / timeout の値は適当ですので、環境に合わせて設定してください。

Start keepalived

後は起動して完了です。

1
2
$ sudo systemctl enable keepalived
$ sudo systemctl start keepalived

状態確認

SEIL/x86 Fuji vrrp status

1
2
3
4
5
6
7
8
# show status vrrp
interface: lan1
vrid: 4
      priority: 240
      state: backup
      address #0: 192.168.1.4/24
      interval: 1 sec
      preempt: on

keepalived status

keepalivedのログから最終ステートがMASTERなのを確認します。

1
2
$ journalctl -u keepalived | grep Entering | tail -1
Feb 05 04:55:23 ipoe-gw Keepalived_vrrp[22253]: (mape) Entering MASTER STATE

keepalivedは/32のアドレスを付与するので、指定したアドレスを持っていればOKです。

1
2
3
4
5
6
$ ip -4 address show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 192.168.1.5/24 brd 192.168.1.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.1.4/32 scope global eth0
       valid_lft forever preferred_lft forever

その他

いつ切り替わったか気になる時は Qiita - keepalivedの通知をSlackへ流す 設定を追加しておくと良いと思います。

内部NWでメールを飛ばす場合は特に気にならないのですが、Slack通知を使う場合はMAP-Eの接続が途絶えた場合に通知経路をどうするか考える必要がありそうです。

雑な考えだと hooks.slack.com は1つのAレコードしか持っていない気がするので、FAULTした場合は以下のようにSlack向けの経路を一時的に設定することで通知の欠損を回避できると思います。

1
2
3
4
5
6
if [[ "$STATE" == "FAULT" ]]; then
    SLACK_IP=$(dig +short hooks.slack.com A)
    ip route add ${SLACK_IP}/32 via 192.168.1.1
    curl ...
    ip route del ${SLACK_IP}/32 via 192.168.1.1
fi

トンネル疎通確認用の経路だけ常にトンネルに向けておいて、keepalivedのnotify契機でデフォルトルートを設定する方が妥当でしょうか。 この辺りは考えだすと止まらないので一旦棚上げにしてしまいます。

終わり

RFC準拠だからSEILともVRRPするのは問題ないと思っていたので、フォールバックの仕組みとしては問題なく動きそう。

障害発生時やMAP-Eの仕様変更があった時に上手く気付けると良いなぁ。

Built with Hugo
テーマ StackJimmy によって設計されています。