LoginSignup
3
6

More than 5 years have passed since last update.

Apache mod_heartbeat を使ってみる

Posted at

CentOS 7 の Apache 2.4 に mod_heartbeat とか mod_watchdog という変なモジュールがあったので興味本位で使ってみました。

使っただけなので詳しいことは調べていません。

概要

Apache の mod_proxy_balancer で負荷分散するときにリアルサーバからのハートビートを元にバランス先を判断するもののようです。

以下の3つのモジュールを組み合わせて使います。

  • mod_watchdog
    • 他のモジュールで定期的なタスクを実行するためのモジュール
    • mod_heartbeatmod_heartmonitor で定期的なタスクを実行するために必要
    • リバースプロキシとリアルサーバの両方で有効にする
    • いわゆる software watchdog のことではない
    • 下記のページが詳しい
    • mod_watchdog | しんじつのなみだ
  • mod_heartbeat
    • リアルサーバからハートビートを送信するためのモジュール
    • リアルサーバで有効にする
    • ハートビートはマルチキャストで送信される
    • いわゆる Linux-HA の heartbeat とは関係ない
  • mod_heartmonitor
    • ハートビートを受信してバランス先を管理するためのモジュール
    • リバースプロキシで有効にする

Vagrant

Vagrant で環境を作ります。

Vagrant.configure(2) do |config|

  config.vm.box = "ngyuki/centos-7"

  config.vm.define "rev" do |cfg|
    cfg.vm.hostname = "rev"
    cfg.vm.network "forwarded_port", guest: 80, host: 8080
    cfg.vm.network "private_network", ip: "192.168.33.10", virtualbox__intnet: "apache-hb"
  end

  config.vm.define "sv1" do |cfg|
    cfg.vm.hostname = "sv1"
    cfg.vm.network "forwarded_port", guest: 80, host: 8081
    cfg.vm.network "private_network", ip: "192.168.33.11", virtualbox__intnet: "apache-hb"
  end

  config.vm.define "sv2" do |cfg|
    cfg.vm.hostname = "sv2"
    cfg.vm.network "forwarded_port", guest: 80, host: 8082
    cfg.vm.network "private_network", ip: "192.168.33.12", virtualbox__intnet: "apache-hb"
  end

  config.vm.provision "shell", inline: <<-SHELL
    yum -y install httpd
    uname -n > /var/www/html/index.html
  SHELL
end

rev がいわゆるリバースプロキシ型の L7 ロードバランサで、sv1 と sv2 がリアルサーバです。

使用している Box はプライベートな Box なのでわたし以外使えませんが、epel-release とか git とかを追加しているだけなので、普通の CentOS 7 と特に変わりありません。

それでは起動します。

vagrant up

mod_heartbeat を使わずに分散

リアルサーバ(sv1/sv2)の Apache を開始します。

systemctl start httpd.service

リバースプロキシ(rev)で次のように設定します。

cat <<'EOS'> /etc/httpd/conf.d/rev.conf
<VirtualHost *:80>
    ServerName localhost
    <Location />
        ProxyPass balancer://app/
        ProxyPassReverse balancer://app/
    </Location>
    <Location /balancer-manager>
        ProxyPass !
        SetHandler balancer-manager
    </Location>
    <Proxy balancer://app/>
        BalancerMember http://192.168.33.11
        BalancerMember http://192.168.33.12
    </Proxy>
</VirtualHost>
EOS

Apache を開始します。

systemctl start httpd.service

この状態でリバースプロキシ(rev)にアクセスすると sv1 と sv2 とに分散されているのがわかります。

Vagrant のホスト側から sv2 を強制終了させます。

vagrant halt -f sv2

もう一度 rev を開くと最初の1回目か2回目で超待たされると思います。

これはリバースプロキシが sv2 にリクエストしてタイムアウトを待っているためです。

一度タイムアウトすると、それ以降はしばらく sv1 にのみ振り分けられますが、60 秒ごとに sv2 にリクエストするので、その時にまたタイムアウトを待たされます。sv2 の復帰を確認する必要があるためです。

sv2 を再起動します。

vagrant up sv2
vagrant ssh sv2

sv2 の Apache を開始します。

systemctl start httpd.service

しばらく(最大で 60 秒ぐらい)すると、sv2 にもバランスされるように戻ります。

mod_heartbeat を使ってバランス

すべてのサーバ(rev/sv1/sv2)で、次の通りルーティングを設定します。

ip route add 239.0.0.0/24 dev enp0s8 proto kernel scope link

mod_heartbeat はマルチキャストでハートビートを送るのですが、送信先の設定で I/F を指定することができないっぽいので、ルーティングでどの I/F から出ていくかを指定する必要があります(普通はこういうときは I/F も指定するもののような気がするけど)。

I/F が一つしかないなら指定する必要はありませんが、Vagrant なので NAT と PrivateNetwork で2つあります。NAT の方から出て行ってもゲスト間で通信できないので、PrivateNetwork から出て行くようにルーティングを設定しています。

リアルサーバ(sv1/sv2)の設定

リアルサーバ(sv1/sv2)で mod_watchdogmod_heartbeat を有効にします。

vim /etc/httpd/conf.modules.d/00-base.conf

次のようにコメントアウトを解除します。

 #LoadModule buffer_module modules/mod_buffer.so
-#LoadModule watchdog_module modules/mod_watchdog.so
+LoadModule watchdog_module modules/mod_watchdog.so
-#LoadModule heartbeat_module modules/mod_heartbeat.so
+LoadModule heartbeat_module modules/mod_heartbeat.so
 #LoadModule heartmonitor_module modules/mod_heartmonitor.so
 #LoadModule usertrack_module modules/mod_usertrack.so

ハートビートのマルチキャストアドレスを指定します(ここで I/F 名を指定できても良さそうな気がするのですが・・・)。

cat <<EOS> /etc/httpd/conf.d/heartbeat.conf
HeartbeatAddress 239.0.0.1:27999
EOS

Apache を再起動します。

systemctl restart httpd.service

tcpdump するとマルチキャストパケットが流れているのが判ります。

tcpdump -nn -i enp0s8 port 27999

リバースプロキシ(rev)の設定

リバースプロキシ(rev)で mod_watchdogmod_heartmonitor を有効にします。

vim /etc/httpd/conf.modules.d/00-base.conf

次のようにコメントアウトを解除します。

 #LoadModule buffer_module modules/mod_buffer.so
-#LoadModule watchdog_module modules/mod_watchdog.so
+LoadModule watchdog_module modules/mod_watchdog.so
 #LoadModule heartbeat_module modules/mod_heartbeat.so
-#LoadModule heartmonitor_module modules/mod_heartmonitor.so
+LoadModule heartmonitor_module modules/mod_heartmonitor.so
 #LoadModule usertrack_module modules/mod_usertrack.so

マルチキャストの受信の設定と、状態を保存するファイル名を設定します。

cat <<EOS> /etc/httpd/conf.d/heartbeat.conf
HeartbeatListen 239.0.0.1:27999
HeartbeatStorage /tmp/hb.dat
EOS

プロキシの設定で lbmethod=heartbeat を追記します。

cat <<'EOS'> /etc/httpd/conf.d/rev.conf
<VirtualHost *:80>
    ServerName localhost
    <Location />
        ProxyPass balancer://app/ lbmethod=heartbeat
        ProxyPassReverse balancer://app/
    </Location>
    <Location /balancer-manager>
        ProxyPass !
        SetHandler balancer-manager
    </Location>
    <Proxy balancer://app/>
        BalancerMember http://192.168.33.11
        BalancerMember http://192.168.33.12
    </Proxy>
</VirtualHost>
EOS

Apache を再起動します。

systemctl restart httpd.service

リバースプロキシ(rev)にアクセスして sv1 と sv2 に分散されていることを確認しておきます。

確認できたら、おもむろに sv2 を停止します。

vagrant halt -f sv2

少し待ってからもう一度リバースプロキシを開くと、先ほどのようにタイムアウトを待たされることはありません。

sv2 からのハートビートが切れたことで、バランス先から取り外されたからです(多分)。

もう一度 sv2 を再起動します。

vagrant up sv2
vagrant ssh sv2

ルーティングを設定して Apache を起動します(本来なら自動で設定されるようにしておくべきです)。

ip route add 239.0.0.0/24 dev enp0s8 proto kernel scope link
systemctl start httpd.service

10 秒ぐらいで sv2 にもバランスされるようになりました。

さいごに

L7 ロードバランサとか、別に Apache でやる必要は全くないと思うし、HAProxy とかでいいと思うし、というか AWS に乗っけて ELB でいいんじゃないって思うので、実際に運用で使うことはないと思います。

3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6