LVS と keepalived で作る冗長化されたロードバランサ

スタッフブログ

インフラエンジニアの桐山です。

物理サーバー環境でもクラウドサービスでも構成上ロードバランスを必要とするサーバが必要になったり、ネットワーク経路を冗長化したくなった時、どういう構成をどういう仕組みで作るか……が課題になることが多々あります。
ネットワークの中継点となる「ロードバランサ」や外部へのアクセス経路となる「デフォルトゲートウェイ」となるサーバは、ネットワーク構成の最大のSPOF(単一障害点)となりがちなので、これらのサーバーを冗長化しフェイルオーバーしてくれる構成にしたくなることは今までも何度となくありました。

今回は、最近あたらしくサービスを開始するために構築した環境のネットワークの冗長化と負荷分散の構成についてお話したいと思います。

LVS と keepalived

LVS(Linux Virtual Server) は、Linux 上で Layer4 の負荷分散装置と同様の機能を実現するためのソフトウェアで、 IPVS(IP Virtual Server) と ipvsadm ユーティリティーで構成されています。この LVS と keepalived などのソフトウェアを組み合わせて実サーバのサービス監視を行うことで、ネットワークの冗長化やロードバランスを行うことができるようになります。
ネットワーク経路の冗長化構成は、 VRRP(Virtual Router Redundancy Protocol) を使って行います。VRRPを使用することで、物理的には2台あるネットワーク機器などを論理的(仮想的)に、1台の機器のようにすることができ、keepalived などのソフトウェアを使って設定することでネットワーク経路を冗長化することができます。
LVS には、ソフトウェアロードバランサーの機能もあり、これも VRRPと同様に keepalived と組み合わせることで振分け先のサーバーの状態を監視し、アクセスが出来ない場合はリクエストを振り分けないようにすることができるようになります。

今回はこの LVS と keepalived の組み合わせで冗長化されたロードバランサを構築します。

構築するサーバの構成

グローバル側の IP アドレス構成

10.0.10.50: グローバル側 VRRP 仮想アドレス
10.0.10.51: lvs1 の eth0
10.0.10.52: lvs2 の eth0

ローカル側の IP アドレス構成

192.168.100.10: ローカル側 VRRP 仮想アドレス
192.168.100.11: lvs1 の eth1
192.168.100.12: lvs2 の eth1
192.168.100.101: Web サーバ1 の IP アドレス
192.168.100.102: Web サーバ2 の IP アドレス

ソフトウェアのインストールとカーネルパラメータの設定

サーバを 2台用意し、それぞれに ipvsadm と keepalived をインストールします。
今回 Debian(buster) で構築していますので、以下のコマンドでインストールできます。

root@lvs1:~# apt install −y ipvsadm keepalived

任意のサーバーへの振り分けを許可するため、カーネルのパラメータを変更します。

vi /etc/sysctl.conf

net.ipv4.ip_forward = 1
net.ipv4.conf.default.rp_filter = 0

それぞれのサーバで変更後、以下のコマンドで有効化します。

root@lvs1:~# sysctl -p

keepalived の冗長化設定

keepalived の設定を lvs1 と lvs2 でそれぞれ以下のように設定します。

  • lvs1 の keepalived 設定

    /etc/keepalived/keepalived.conf

    vrrp_instance VI {
        state BACKUP
        interface eth1
        garp_master_delay 5
        virtual_router_id 1
        priority 100
        nopreempt
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass XXX999XXX
        }
        virtual_ipaddress {
            10.0.10.50/24     dev eth0
            192.168.100.10/22  dev eth1
        }
    }
  • lvs2 の keepalived 設定

    /etc/keepalived/keepalived.conf

    vrrp_instance VI {
        state BACKUP
        interface eth1
        garp_master_delay 5
        virtual_router_id 1
        priority 101
        nopreempt
        advert_int 1
        authentication {
            auth_type PASS
            auth_pass XXX999XXX
        }
        virtual_ipaddress {
            10.0.10.50/24     dev eth0
            192.168.100.10/22  dev eth1
        }
    }

2つの違いは priority の数値のみです。どちらも state が BACKUP になっていますが、先に起動したほうが MASTER に昇格するので、特に気にしなくても問題ありません。

設定が完了したら、それぞれのサーバの keepalived デーモンを再起動します。

root@lvs1:~# systemctl restart keepalived.service

冗長化の挙動

virtual_ipaddressの部分が仮想IPアドレスになります。今回の構成では外部からのアクセス用の仮想グローバルIPアドレスと、内部サーバがデフォルトゲートウェイとして利用する仮想ローカルIPアドレスがそれぞれ設定されています。
通常は state が MASTER な方にこの仮想IPアドレスが割り振られますが、MASTER になっているサーバがダウンすると、自動的に BACKUP が MASTER に昇格し、仮想IPアドレスが自動的にフェイルオーバーされます。この仮想IPアドレスの割当が自動的に変更されることにより、外部からのアクセスも、デフォルトゲートウェイもダウンすることなくサービスの運用が継続できます。

lvs1 をダウンさせる

lvs1 をダウンさせ lvs2のログを見ると、state が MASTER に昇格されたことがわかります。

tail -F /var/log/messages

Oct 11 16:11:51 lvs2 Keepalived_vrrp[441]: (VI) Backup received priority 0 advertisement
Oct 11 16:11:52 lvs2 Keepalived_vrrp[441]: (VI) Entering MASTER STATE
Oct 11 16:12:13 lvs2 Keepalived_vrrp[441]: (VI) sent 0 priority

この状態で lvs2 のIPアドレスを確認すると、仮想IPアドレスの割当が lvs2 の方に変わっているはずです。
その後、lvs1 が復旧したとしても、lvs2 が MASTER になった状態で動き続けます。

keepalived のロードバランサ設定

冗長化に続いて、次はロードバランサとして機能させる設定を同じ keepalived の設定ファイルに入れます。グローバル側の仮想IPアドレス 10.0.10.5080 ポートにアクセスがあると、Web サーバ1 または、Web サーバ2 の IP アドレスの 80 ポートに振り分けられるように設定します。

/etc/keepalived/keepalived.conf

〜〜〜 省略 〜〜〜
virtual_server 10.0.10.50 80 {
    delay_loop 6
    lb_algo rr
    lb_kind NAT
    protocol TCP

    real_server 192.168.100.101 80 {
        TCP_CHECK {
                connect_timeout 10
        }
    }
    real_server 192.168.100.102 80 {
        TCP_CHECK {
                connect_timeout 10
        }
    }
}

ロードバランスのアルゴリズム(lb_algo)や分散方式の設定(lb_kind)については、環境に合わせて適宜変更が必要なことと、Webサーバの監視設定などを入れてダウン時の挙動などを設定するべきではありますが、この設定だけで 2台の Webサーバに対して負荷分散することができます。

設定したロードバランスの状態を確認

ipvsadm コマンドでロードバランスの状態を確認すると以下のように状態が表示され、Webサーバ1とWebサーバ2に振り分けが行われることが確認できます。

root@lvs1:~# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.10.50:80 rr persistent 10
  -> 192.168.100.101:80            Route   1      0          0
  -> 192.168.100.102:80            Route   1      0          0

まとめ

LVS+keepalived の構成で冗長化されたロードバランサーの構成を簡単につくることができました。さらに自動でフェイルオーバーもしてくれる素晴らしい構成になっています。今回は簡易な設定での説明でしたが、LVS も Keepalived も多くの設定項目があり、必要に応じてさまざまな構成を実現することができます。
ネットワークの分岐点になる部分の冗長化を行うことで SPOF になる部分が減れば、少しは枕を高くして寝られるかな……と思っています。