ビビリフクロウの足跡

とあるインフラSEの勉強&備忘ブログ

haproxyをkeepalivedで冗長化して高可用性ロードバランサを構築する

ロードバランサとして活用できるhaproxyですが、ロードバランサ冗長性確保用デーモンであるkeepalivedを使って冗長化してみたので、その手法をメモしておきます。

なんでいきなりhaproxy + keepalivedかというと、Kubernetesの冗長化においてkubeletやkubectlからのkube-apiserverやetcdへのアクセスはMasterノードが複数になるためロードバランスしてやらなくてなりません。ですのでロードバランサが必須になるんですが、単純にロードバランサを追加するだけだとロードバランサ自体がSPOFになってしまうので、ロードバランサ自体の高可用性も勉強してみた、という形です。

構成

構成としては以下の通りとします。

  • Webサーバ
    • IP: 192.168.0.60, ホスト名: apache-01.bbrfkr.mydns.jp
    • IP: 192.168.0.61, ホスト名: apache-02.bbrfkr.mydns.jp
  • ロードバランサ
    • IP: 192.168.0.62, ホスト名: haproxy-01.bbrfkr.mydns.jp
    • IP: 192.168.0.63, ホスト名: haproxy-01.bbrfkr.mydns.jp
    • VIP: 192.168.0.64

VIP: 192.168.0.64へのHTTPアクセスを背後のhaproxy-01, haproxy-02が受け付け、haproxyはさらに背後のapache-01, apache-02にリクエストを流す、という単純な構成です。

構築手順

  • SELinux、firewalldの無効化(haproxy-01, haproxy-02)

検証のため、無効化します。

# sed -i 's/SELINUX=.*/SELINUX=permissive/g' /etc/selinux/config
# systemctl disable firewalld
# reboot
  • haproxy、keepalivedのインストール(haproxy-01, haproxy-02)
# yum -y install haproxy keepalived
  • haproxyの設定(haproxy-01, haproxy-02)
# vi /etc/haproxy/haproxy.cfg
frontend main *:80
    default_backend    web

backend web
    balance    roundrobin
    server    web1  192.168.0.60:80  check
    server    web1  192.168.0.61:80  check
  • haproxyの起動と自動起動設定(haproxy-01, haproxy-02)
# systemctl enable haproxy
# systemctl start haproxy
# vi /etc/keepalived/keepalived.conf
vrrp_script chk_haproxy {
    script "systemctl is-active haproxy"
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 1
    priority 101
    virtual_ipaddress {
        192.168.0.64
    }
    track_script {
        chk_haproxy
    }
}
# vi /etc/keepalived/keepalived.conf
vrrp_script chk_haproxy {
    script "systemctl is-active haproxy"
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 1
    priority 100
    virtual_ipaddress {
        192.168.0.64
    }
    track_script {
        chk_haproxy
    }
}
# systemctl enable keepalived
# systemctl start keepalived

動作確認

構築手順で実施した作業で、haproxy-01にVIP: 192.168.0.64が割り当てられているはずです。

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:1a:4a:16:02:c7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.62/25 brd 192.168.0.127 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.0.64/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::21a:4aff:fe16:2c7/64 scope link
       valid_lft forever preferred_lft forever

curlで確認しても、VIP: 192.168.0.64に対するリクエストがラウンドロビンでロードバランスされていることが分かるはずです。

# watch -n 0.1 curl 192.168.0.64

この状態で障害を想定し、haproxy-01のサービスhaproxyを停止します。

# systemctl stop haproxy

すると少ししてhaproxy-01からVIPが外れます。

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:1a:4a:16:02:c7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.62/25 brd 192.168.0.127 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::21a:4aff:fe16:2c7/64 scope link
       valid_lft forever preferred_lft forever

その後、haproxy-02にVIPが付与されます。(IPフェイルオーバ)

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:1a:4a:16:02:c8 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.63/25 brd 192.168.0.127 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.0.64/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::21a:4aff:fe16:2c8/64 scope link
       valid_lft forever preferred_lft forever

VIP: 192.168.0.64に対するリクエストは引き続き処理できるようになっています。

# watch -n 0.1 curl 192.168.0.64

IPフェイルバックを試してみましょう。haproxy-01のサービスhaproxyを起動します。

# systemctl start haproxy

すると少ししてhaproxy-02からVIPが外れます。

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:1a:4a:16:02:c8 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.63/25 brd 192.168.0.127 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::21a:4aff:fe16:2c8/64 scope link
       valid_lft forever preferred_lft forever

その後、haproxy-01にVIPが付与されます。(IPフェイルバック)

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:1a:4a:16:02:c7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.62/25 brd 192.168.0.127 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.0.64/32 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::21a:4aff:fe16:2c7/64 scope link
       valid_lft forever preferred_lft forever