haproxyによるWEB負荷分散をおこなってみた

概要

こんにちは、テクニカルサポートの牛山です。

AlmaLinuxにて、haproxyを利用したWEBの負荷分散をしてみたいと思います。

今回、利用する環境は、haproxyサーバ1台、WEBサーバ2台構成とします。

haproxyサーバからWEB2台の private ip に対してチェックをおこないます。

サーバ名 private ip
WEB01 10.0.0.224
WEB02 10.0.0.97

haproxy構成図

トラブルを防ぐため、iptablesやfirewalldやnftables等が動作していないことおよび、SELinuxが無効になっていることとします。

WEB01での作業

Apacheのインストール(WEB01)

haproxyでWEB負荷分散するためには、分散先でWEBサービスを Listen していなければいけないのでapacheのインストールをおこないます。

[root@WEB01 ~]# dnf -y install httpd

・
・[中略]
・
Installing:
 httpd                                      x86_64                      2.4.37-47.module_el8.6.0+2935+fb177b09.2                      appstream                      1.4 M
・
・[中略]
・
Complete!

[root@WEB01 ~]# systemctl --now enable httpd

Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.

 →apacheサービスの自動起動を有効にし、サービスを開始します。

コンテンツ設置(WEB01)

haproxyによって分散先がわかるように、以下の様なコンテンツを設置します。

設置後、 http://{WEB01のグローバルIP}/ に対してアクセスをおこない、緑の背景に「WEB01のコンテンツが表示されているよ!」と表示されれば問題ありません。

[root@WEB01 ~]# vim /var/www/html/index.html

<!DOCTYPE html>
<html>
        <head>
                <meta charset="UTF-8">
                <title>WEB01のコンテンツ</title>
        </head> <!-- head -->

        <body style="background-color:green;">
                <h1>WEB01のコンテンツが表示されているよ!</h1><br>
        </body> <!-- body -->
</html> <!-- html -->

WEB02での作業

Apacheのインストール(WEB02)

WEB02でもWEB01同様の作業を実施します。

[root@WEB02 ~]# dnf -y install httpd

・
・[中略]
・
Installing:
 httpd                                      x86_64                      2.4.37-47.module_el8.6.0+2935+fb177b09.2                      appstream                      1.4 M
・
・[中略]
・
Complete!

[root@WEB02 ~]# systemctl --now enable httpd

Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.

 →apacheサービスの自動起動を有効にし、サービスを開始します。

コンテンツ設置(WEB02)

haproxyによって分散先がわかるように、以下の様なコンテンツを設置します。

設置後、 http://{WEB02のグローバルIP}/ に対してアクセスをおこない、ピンクの背景に「WEB02のコンテンツが表示されているよ!」と表示されれば問題ありません。

[root@WEB02 ~]# vim /var/www/html/index.html

<!DOCTYPE html>
<html>
        <head>
                <meta charset="UTF-8">
                <title>WEB02のコンテンツ</title>
        </head> <!-- head -->

        <body style="background-color:pink;">
                <h1>WEB02のコンテンツが表示されているよ!</h1>
        </body> <!-- body -->
</html> <!-- html -->

haproxyサーバでの作業

haproxyインストール

[root@haproxy ~]# dnf install haproxy

Last metadata expiration check: 0:09:46 ago on Sat 25 Jun 2022 05:21:37 PM JST.
Dependencies resolved.
===============================================================================================================================================
 Package                         Architecture                   Version                                Repository                         Size
===============================================================================================================================================
Installing:
 haproxy                         x86_64                         1.8.27-4.el8                           appstream                         1.4 M

Transaction Summary
===============================================================================================================================================
Install  1 Package

Total download size: 1.4 M
Installed size: 4.2 M
Is this ok [y/N]: y
・
・[中略]
・

[root@haproxy ~]# systemctl --now enable haproxy

Created symlink /etc/systemd/system/multi-user.target.wants/haproxy.service → /usr/lib/systemd/system/haproxy.service.

 →haproxyサービスの自動起動を有効にし、サービスを開始します。

haproxy設定ファイルの編集

[root@haproxy ~]# cp -p /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.org
[root@haproxy ~]# cp -p /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg_$(date +"%Y%m%d")
 →あらかじめ、バックアップを取ります。

設定の確認

以下の様にデフォルトで、 log 127.0.0.1 local2 となっており、 syslogの種類が local2 となっていることを確認します。

[root@haproxy ~]# cat /etc/haproxy/haproxy.cfg

#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
・
・[中略]
・
    log         127.0.0.1 local2
・
・[中略]
・

haproxyインストールしたての /etc/haproxy/haproxy.cfg は以下のようになっているので変更します。

・
・[中略]
・
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main
    bind *:5000
    acl url_static       path_beg       -i /static /images /javascript /stylesheets
    acl url_static       path_end       -i .jpg .gif .png .css .js

    use_backend static          if url_static
    default_backend             app

#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend static
    balance     roundrobin
    server      static 127.0.0.1:4331 check

#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
    balance     roundrobin
    server  app1 127.0.0.1:5001 check
    server  app2 127.0.0.1:5002 check
    server  app3 127.0.0.1:5003 check
    server  app4 127.0.0.1:5004 check

設定変更

ログフォーマット変更

haproxy.cfgdefault セクションで option httplog が指定されていますが、今回は、指定なしのデフォルトフォーマットにしたいと思いますので、こちらの行を削除します。

フォーマットの種類として、3種類存在し、「default」と「option tcplog」と「option httplog」が存在します。

  1. default
    defaultでは送信元アドレスと送信先アドレス、およびインスタンス名のみが出力されます。
     
    出力例: Jul 8 22:29:51 localhost haproxy[2336]: Connect from ***.***.***.***:64157 to 10.0.0.56:80 (http_web/HTTP)

  2. option tcplog
    tcplogでは接続時間、セッションのステータス、接続数、フロントエンド、バックエンドの
    数など詳細なログが出力されます。
     
    出力例: Jul 8 22:13:11 localhost haproxy[2180]: ***.***.***.***:64024 [08/Jul/2022:22:13:10.706] http_web app/WEB02 0/1/544 606 -- 2/2/0/0/0 0/0

  3. option httplog
    httplogではtcplog情報に加えリクエスト、ステータスコード、ヘッダとクッキーの情報が付加されます。
     
    出力例: Jul 8 21:40:16 localhost haproxy[1986]: ***.***.***.***:63588 [08/Jul/2022:21:40:16.074] http_web app/WEB01 0/0/1/1/2 200 611 - - ---- 2/2/0/0/0 0/0 "GET / H TTP/1.1"

アクセス振り分け

以下のように、80番ポートで Listen し、分散先として、WEB01およびWEB02の private ip を指定するようにします。

[root@haproxy ~]#vim /etc/haproxy/haproxy.cfg

・
・[中略]
・
     option                  httplog ←defaultsにある、「option httplog」行を削除。
・
・[中略]
・
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend http_web
    bind *:80
    mode http
    default_backend app

#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
    balance     roundrobin
    mode http
    server WEB01 10.0.0.224:80 check
    server WEB02 10.0.0.97:80 check

diffの結果として、以下のような感じになることを確認します。

[root@haproxy ~]# diff -u /etc/haproxy/haproxy.cfg_$(date +"%Y%m%d") /etc/haproxy/haproxy.cfg

--- /etc/haproxy/haproxy.cfg_20220625   2022-04-19 04:31:18.000000000 +0900
+++ /etc/haproxy/haproxy.cfg    2022-06-25 20:02:21.718000000 +0900
@@ -46,7 +46,6 @@
 defaults
     mode                    http
     log                     global
-    option                  httplog
     option                  dontlognull
     option http-server-close
     option forwardfor       except 127.0.0.0/8
@@ -64,27 +64,16 @@
 #---------------------------------------------------------------------
 # main frontend which proxys to the backends
 #---------------------------------------------------------------------
-frontend main
-    bind *:5000
-    acl url_static       path_beg       -i /static /images /javascript /stylesheets
-    acl url_static       path_end       -i .jpg .gif .png .css .js
-
-    use_backend static          if url_static
-    default_backend             app
-
-#---------------------------------------------------------------------
-# static backend for serving up images, stylesheets and such
-#---------------------------------------------------------------------
-backend static
-    balance     roundrobin
-    server      static 127.0.0.1:4331 check
+frontend http_web
+    bind *:80
+    mode http
+    default_backend app

 #---------------------------------------------------------------------
 # round robin balancing between the various backends
 #---------------------------------------------------------------------
 backend app
     balance     roundrobin
-    server  app1 127.0.0.1:5001 check
-    server  app2 127.0.0.1:5002 check
-    server  app3 127.0.0.1:5003 check
-    server  app4 127.0.0.1:5004 check
+    mode http
+    server WEB01 10.0.0.224:80 check
+    server WEB02 10.0.0.97:80 check

haproxyログ出力設定

haproxyのログを、 rsyslog で受信できるようにするため、 rsyslog 側での設定変更をします。

[root@haproxy ~]# netstat -nlp | grep 514
 →UDP 514番ポートで受信するようにしたいため、あらかじめ Listen していないことを確認します。
※なにも出力がなければokです。

[root@haproxy ~]# cp -p /etc/rsyslog.conf /etc/rsyslog.conf_$(date +"%Y%m%d")
[root@haproxy ~]# cp -p /etc/rsyslog.conf /etc/rsyslog.conf.org
 →あらかじめ設定ファイルのバックアップをおこないます。

rsyslog 設定ファイルを編集します。

module(load="imudp") # needs to be done just once および input(type="imudp" port="514") がコメントアウトされているのでコメントアウトを外します。
 →これで、UDP 514番ポート待ち受けが有効になります。

# ### sample forwarding rule ### の上側あたりに、 local2.* /var/log/haproxy.log の記述を追加します。
 →こちらを追加することにより、haproxyのログが、 /var/log/haproxy.log に記録されます。

rsyslog 設定ファイルの diff 結果は以下の通りとなります。

[root@haproxy ~]# diff -u /etc/rsyslog.conf_$(date +"%Y%m%d") /etc/rsyslog.conf

--- /etc/rsyslog.conf_20220625  2022-05-30 16:47:31.000000000 +0900
+++ /etc/rsyslog.conf   2022-06-25 21:08:50.901000000 +0900
@@ -16,8 +16,8 @@

 # Provides UDP syslog reception
 # for parameters see http://www.rsyslog.com/doc/imudp.html
-#module(load="imudp") # needs to be done just once
-#input(type="imudp" port="514")
+module(load="imudp") # needs to be done just once
+input(type="imudp" port="514")

 # Provides TCP syslog reception
 # for parameters see http://www.rsyslog.com/doc/imtcp.html

@@ -64,6 +64,8 @@
 # Save boot messages also to boot.log
 local7.*                                                /var/log/boot.log

+# Log all the haproxy messages in one place.
+local2.*                                                /var/log/haproxy.log

 # ### sample forwarding rule ###

[root@haproxy ~]# systemctl restart haproxy rsyslog
 →最後に haproxyrsyslog サービスを再起動し、設定を適用します。

事後確認

http://{haproxyのグローバルIP}/ にアクセスし、ページリロード毎に、コンテンツが切り替わる事および、 haproxy.log のみにログが出力されていることを確認できればログ設定と負荷分散が上手くおこなえています。

ページリロード毎に以下、画像のように切り替わります。

haproxy_WEB1
                 ↑↓
haproxy_WEB2

まとめ

私自身、haproxyについて、あまり理解できていなかったですが、実際に構築してみて、少しは理解できたかなぁと思いました。

簡単に冗長化できて感無量です!

返信を残す

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

CAPTCHA