haproxyを利用して冗長化ロードバランサを構築する

はじめに

こんにちは。サイオステクノロジー 小林です。

今回は haproxyとkeepalivedを組み合わせた 冗長化ロードバランサを構築するお話しです。

このブログが開設されて数年立ちますが、意外にもまだ haproxyを扱った記事がなく、個人的にも好きなソフトウェアなので、少しでも良さが伝わればと思いつつ、お話しさせて頂こうと思いました。

haproxy とは

haproxy とは、Linux系システムで利用可能なオープンソースソフトウェアのHTTPプロキシソフトウェアです。haproxy + keepalived で構成することにより、冗長化のL7ロードバランサ-(※1)として機能させることができます。
※1) オプションのパラメータを追加することによりtransparent proxy としてL4の振舞に変更することもできますが、今回のインストール編ではデフォルトのL7ロードバランサとしてご紹介します。

さて、本記事は全2回シリーズに分けてお話しさせて頂こうと思います。

  1. インストール編
  2. 動作確認編

環境構成

導入バージョン

・CentOS 7.5
・haproxy 1.5.18-8
・keepalived 1.3.5-8
・httpsd 2.4.6-88

Webサーバ構築

バックエンドとなるWebサーバ(Apache)の構築に関しては、以下記事を参照し構築してください。
【WEB01/WEB02/WEB03で以下実施】
https://tech-lab.sios.jp/archives/12738

構築

全体構成

以下のような構成を想定しています。

  • ネットワークインターフェース名は、従来のethXX表記を使用
  • eth0=”frontend”、eth1=”backend”としてfirewalldのゾーンを定義
  • 割り振り先となるバックエンドサーバは、Webサーバ3ノード構成(Apacheを3インスタンスに分割)
  • haproxyは Active-Standby構成
  • SSLの終端をhaproxyが担う
  • 自動フェイルバックは行わない

kousei

構築前提

  • 手順上の操作はすべてrootで操作
  • SELinuxは無効

インストール

haproxy及びkeepalivedをインストールします。また、今回SSLを利用するにあたり自己証明書を作成するため、opensslパッケージを追加でインストールします。
【PROXY01/PROXY02で実施】

# yum install -y haproxy keepalived openssl

firewalld設定

PROXY01及びPROXY02ノード間においてVRRPアドバタイズ通信できるようにfirewalldを許可します。
また、併せてクライアントからのHTTPS通信を許可します。
【PROXY01/PROXY02で実施】

# firewall-cmd --add-rich-rule='rule protocol value="vrrp" accept' --zone=frontend --permanent
# firewall-cmd --add-port=443/tcp --zone=frontend --permanent
# firewall-cmd --reload
# firewall-cmd --list-all --zone=frontend
frontend (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources:
  services:
  ports: 443/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
        rule protocol value="vrrp" accept
# 許可されたポートが追加されていることを確認

ログ出力設定

haproxyのログ出力設定

haproxyのログ出力設定を行います。haproxyはデフォルトでlocal2を使用して出力されます。
また、本手順では動作確認時の可読性を考慮して、プロキシログとヘルスチェック等のシステム系のログを分割して出力するよう設定しています。
【PROXY01/PROXY02で実施】

# mkdir /var/lib/haproxy/dev
# mkdir /var/log/haproxy
# vim /etc/rsyslog.conf
※rsyslog.confの最下行に追記
# haproxy
$AddUnixListenSocket /var/lib/haproxy/dev/log
$template haproxy,"%timegenerated:1:10:date-rfc3339% %timegenerated:12:23:date-rfc3339% %msg%\n

local2.=info             -/var/log/haproxy/haproxy.log;haproxy
&stop
local2.=notice           -/var/log/haproxy/haproxy_admin.log;haproxy
&stop

keepalivedのログ出力設定

keepalivedのログ出力設定を行います。keepalivedはデフォルトでlocal1を使用して出力されます。
【PROXY01/PROXY02で実施】

# mkdir /var/log/keepalived
# vim /etc/rsyslog.conf
※rsyslog.confの最下行に追記
# keepalived
local1.*                 -/var/log/keepalived/keepalived.log
&stop

keepalived設定

HAの設定を行います。今回はフロントエンド側(eth0)からのHTTPリクエスト処理をWEBサーバへ振り分けを行いますので、eth0デバイスに対してVIPを設定します。
【PROXY01/PROXY02で実施】

# vim /etc/keepalived/keepalived.conf
vrrp_script chk_haproxy {
    script "killall -0 haproxy"
    interval 3 fall 3
}

vrrp_instance VI_1 {
#自動フェイルバック無効
    state BACKUP
#バインドさせるインターフェース名を指定
    interface eth0
    virtual_router_id 188
    priority 100
#VRRPアドバタイズ間隔を以下で設定することで、フェイルオーバー時間をある程度制御できるように設定
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass root2019t_04
    }
    virtual_ipaddress {
        192.168.188.10 dev eth0
    }
    track_script {
        chk_haproxy
    }
}

haproxy設定

haproxyの設定を行います。Globalセクションではhaproxy全体に係る設定を行い、backendセクションでクライアントからリクエストを受けた処理を受け渡すホストを設定します。
【PROXY01/PROXY02で実施】

# vim /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    log         /dev/log local2
    log-send-hostname
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon
    nbproc      1
    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats
#機能モードの指定。今回はHTTPプロキシのため「https」を設定
    mode                    https
#---------------------------------------------------------------------
# listen
#---------------------------------------------------------------------
listen stats
bind 192.168.188.8:9090
    mode https
    maxconn 64
    stats enable
    stats uri /haproxy/
    stats refresh 10s
    stats auth admin:<yourpassword>

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend https-ex
♯リッスンさせるインターフェースを指定。今回SSL終端として機能させるため証明書を指定し、SSL3.0によるネゴシエーションを無効にします。
bind 192.168.188.10:443 ssl crt /etc/haproxy/ssl/proxy.lab.sios.com.crt no-sslv3
     reqadd X-Forwarded-Proto:\ https
     option forwardfor
     use_backend TEST-WEB
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend TEST-WEB
    mode https
#WEBサーバ3ノードに対してラウンドロビンによる負荷分散を設定
    balance roundrobin
    server WEB01 web01.lab.sios.com:8081 maxconn 200 check inter 3s fall 10 rise 5
    server WEB02 web02.lab.sios.com:8082 maxconn 200 check inter 3s fall 10 rise 5
    server WEB03 web03.lab.sios.com:8083 maxconn 200 check inter 3s fall 10 rise 5

サービス起動・起動確認

haproxy及びkeepalivedのサービスを起動します。また、keepalivedによりVIPがバインドされていること、haproxyのバックエンドに対するヘルスチェックが成功していることを確認します。
【PROXY01で以下実施】

# systemctl start keepalived.service
# systemctl status keepalived.service
# systemctl start haproxy.service
# systemctl status haproxy.service
# ip a show
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:35:76:e0 brd ff:ff:ff:ff:ff:ff
    inet 192.168.188.8/24 brd 192.168.188.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet 192.168.188.10/32 scope global eth0
#VIPがバインドされていることを確認

# tail -n100 /var/log/haproxy/haproxy_admin.log
haproxy[20739]: Health check for server TEST-WEB/WEB01 succeeded, reason: Layer4 check passed, check duration: 3ms, status: 10/10 UP.
haproxy[20740]: Health check for server TEST-WEB/WEB02 succeeded, reason: Layer4 check passed, check duration: 8ms, status: 10/10 UP.
haproxy[20740]: Health check for server TEST-WEB/WEB03 succeeded, reason: Layer4 check passed, check duration: 2ms, status: 10/10 UP
#ヘルスチェックが成功していること

簡易動作確認

クライアントからcurlを利用してHTTPSのリクエスト送信して疎通を確認します。疎通が問題なければ、バックエンド側で用意したWebサーバのページが表示されます。

> curl -X GET https://192.168.188.10 -k
THIS web01.lab.sios.com

> curl -X GET https://192.168.188.10 -k
THIS web02.lab.sios.com

> curl -X GET https://192.168.188.10 -k
THIS web03.lab.sios.com

続いて、haproxyのリクエストログを確認します。
クライアントからのリクエストが正常に送信されていることが確認できます。

2019-04-25 12:32:04.619  haproxy[12022]:***client address***:65410 [25/Apr/2019:12:32:04.593] https-ex~ TEST-WEB/WEB01 24/0/1/0/25 200 245 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
2019-04-25 12:32:05.230  haproxy[12022]:***client address***:65411 [25/Apr/2019:12:32:05.215] https-ex~ TEST-WEB/WEB02 13/0/1/0/14 200 245 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1"
2019-04-25 12:32:05.920  haproxy[12022]:***client address***:65415 [25/Apr/2019:12:32:05.895] https-ex~ TEST-WEB/WEB03 23/0/0/1/24 200 245 - - ---- 1/1/0/0/0 0/0 "GET / HTTP/1.1"

※以下記事で、動作確認について紹介しておりますので、あわせて確認ください。
https://tech-lab.sios.jp/archives/16123

最後に

今回はhaproxyとkeepalivedのインストール及び各種設定までをご紹介しました。
次回は実際にクライアントからリクエストを送信した際の挙動やStandbyへのフェイルオーバーの動作確認を紹介する予定です。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です