Apacheのmod_proxy_hcheckを利用してロードバランサーを構築してみる

Apacheの2.4.21から利用できるようになったmod_proxy_hcheckを利用してロードバランサーを構築してみます。ここではApache2.4.23 を利用していきます。このバージョンのmod_proxy_hcheckにはバグがありますので、その対応も記載します。

mod_proxy_hcheck

mod_proxy_hcheckロードバランサー配下のWEBサーバなどのヘルスチェックを柔軟に行ってくれるモジュールです。

何ができるかは以下のパラメータ見ればイメージできると思います。

AWS使っている人はELBのヘルスチェック思い浮かべると近いと思います。

パラメータ 内容
hcmethod GETとかHEADとか、TCPも指定可能
hcinterval ヘルスチェックの間隔(秒単位)
hcfails サーバを振り分け対象から切り離すまでのチェック回数
hcpasses サーバを振り分け対象として復帰させるまでのチェック回数
hcuri ヘルスチェックに利用するURIパス

詳しくは公式サイトを参照してください。

ソースからインストール

CentOSの場合、yumレポジトリに入っているApacheバージョンでは mod_proxy_hcheck を使えません。現時点のApache最新安定版の 2.4.23 をソースからビルドして利用します。

インストール方法は以下の記事の通りです。

yomon.hatenablog.com

上述の通り、Apache 2.4.23mod_proxy_hcheck にはバグがあるので、makeする前にパッチの適用が必要です。

バグはこちら。具体的には hcurihcexpr のパラメータ設定が機能しません。

60038 – params hcuri and hcexpr are ignored

このバグのパッチはこちらです。

https://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_hcheck.c?r1=1757662&r2=1757661&pathrev=1757662&view=patch

--- httpd/httpd/trunk/modules/proxy/mod_proxy_hcheck.c   2016/08/25 11:28:50 1757661
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_hcheck.c  2016/08/25 11:38:07 1757662
@@ -426,6 +426,8 @@
         PROXY_STRNCPY(hc->s->name,     wptr);
         PROXY_STRNCPY(hc->s->hostname, worker->s->hostname);
         PROXY_STRNCPY(hc->s->scheme,   worker->s->scheme);
+        PROXY_STRNCPY(hc->s->hcuri,    worker->s->hcuri);
+        PROXY_STRNCPY(hc->s->hcexpr,   worker->s->hcexpr);
         hc->hash.def = hc->s->hash.def = ap_proxy_hashfunc(hc->s->name, PROXY_HASHFUNC_DEFAULT);
         hc->hash.fnv = hc->s->hash.fnv = ap_proxy_hashfunc(hc->s->name, PROXY_HASHFUNC_FNV);
         hc->s->port = port;

上記のテキストを mod_proxy_hcheck.patch などのファイル名で保存してパッチ適用します。上記のリンクの手順に沿って作業するとすれば以下の通り。

#ソースのディレクトリに移動
$ cd /usr/local/src/httpd-2.4.23/modules/proxy

#上記のパッチをテキスト保存
$ vim mod_proxy_hcheck.patch

#パッチ適用
$ patch < mod_proxy_hcheck.patch
patching file mod_proxy_hcheck.c

パッチ適用したらmake make install してインストールしていきます。

モジュールのロード

上記手順でコンパイルすれば必要なモジュールは含まれているので、モジュールのロード設定をしていきます。

以下に直接関係するモジュールを抜粋します。

#Loadbalancer管理画面に必要
LoadModule status_module modules/mod_status.so

#Proxyモジュール
LoadModule proxy_module modules/mod_proxy.so

#LoadBalancer関連(lbmethodは必要に応じて)
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule lbmethod_bybusyness_module modules/mod_lbmethod_bybusyness.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so
LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
LoadModule lbmethod_heartbeat_module modules/mod_lbmethod_heartbeat.so
LoadModule proxy_http_module modules/mod_proxy_http.so

#hcheck関連
LoadModule watchdog_module modules/mod_watchdog.so
LoadModule proxy_hcheck_module modules/mod_proxy_hcheck.so

ロードバランサー設定(管理画面 balancer-manager)

Apacheのロードバランサには管理画面が用意されています。有効化のためには以下のように設定しておきます。

<Location "/balancer-manager">
    SetHandler balancer-manager
    Require host localhost
</Location>

ロードバランサー設定

細かい内容は公式ページを見るのが良いと思いますが、設定例を書いておきます。

hctemplate を上手く使うとシンプルに整理して書けます。

ProxyHCExpr gok2 {%{REQUEST_STATUS} =~ /^[234]/}
ProxyHCExpr gdown345 {%{REQUEST_STATUS} =~ /^[5]/}
ProxyHCTemplate default hcmethod=GET hcpasses=1 hcfails=3 hcexpr=gok2 hcinterval=10 hcuri=/health_check.php
<Proxy balancer://servicename >
  BalancerMember http://foo.local:80 hctemplate=default
  BalancerMember http://192.168.10.11:80 hctemplate=default
  BalancerMember http://192.168.10.12:80 hcmethod=GET hcpasses=1 hcfails=3 hcexpr=gok2 hcinterval=10 hcuri=/health_check.php
  ProxySet lbmethod=bytraffic
</Proxy>

上記のロードバランサーの設定に合わせて、リクエストをルーティングしていきます。 ProxyPass ディレクティブなどを利用する方法もありますが、RewriteRule を利用したい場合は以下のようにも書けます。 [P] フラグがProxyを表しています。

<VirtualHost *:80>
  RewriteEngine On
  RewriteCond %{REQUEST_URI} !^/balancer-manager
  RewriteCond %{REQUEST_URI} !^/server-(status|info)
  RewriteRule ^(.*) balancer://servicename$1 [P]
</VirtualHost>

動作確認

ロードバランサー管理画面に入ります。

http://<hostname or ip>/balancer-manager

Status の項目を確認して問題無ければ、ロードバランサー経由でバックエンドのサーバにアクセスできるはずです。

バックエンドのサーバのログなども合わせて確認しながら設定調整していきます。

(補足) Apache ログにバックエンドのWEBサーバを出力したい

Proxyでルーティングしたバックエンドサーバーをログで取得したい場合は BALANCER_WORKER_NAME の環境変数を使えます。

LogFormat "%h \"%{BALANCER_WORKER_NAME}e\" %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" custom

この記事の設定だとすると http://192.168.10.11:80 のような値が出力されます。

参考URL

管理画面の見方や、基本的な設定はこちらを見るとわかりやすいです。

Reverse Proxy Guide - Apache HTTP Server Version 2.4

関連するモジュールのページ

mod_proxy_hcheck - Apache HTTP Server Version 2.4

mod_proxy_balancer - Apache HTTP Server Version 2.4

パラメータ設定の参考になるURL

mod_proxy - ProxyPass、BalancerMemberのパラメータのdocumentを読んだのでまとめた - うまいぼうぶろぐ

mod_proxy_hcheck で BalancerMember の healthcheck - Qiita