haproxyをkeepalivedで冗長化して高可用性ロードバランサを構築する
ロードバランサとして活用できるhaproxyですが、ロードバランサ冗長性確保用デーモンであるkeepalivedを使って冗長化してみたので、その手法をメモしておきます。
なんでいきなりhaproxy + keepalivedかというと、Kubernetesの冗長化においてkubeletやkubectlからのkube-apiserverやetcdへのアクセスはMasterノードが複数になるためロードバランスしてやらなくてなりません。ですのでロードバランサが必須になるんですが、単純にロードバランサを追加するだけだとロードバランサ自体がSPOFになってしまうので、ロードバランサ自体の高可用性も勉強してみた、という形です。
構成
構成としては以下の通りとします。
- Webサーバ
- ロードバランサ
- 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
- keepalivedの設定(haproxy-01)
# 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 } }
- keepalivedの設定(haproxy-02)
# 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 } }
- keepalivedの起動と自動起動設定(haproxy-01, haproxy-02)
# 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