HAProxy1とは何か? から始まり、基本的な使い方までを調べました。
HAProxyとは
多機能なプロキシサーバです。ソフトウェアロードバランサの一種でもあります。古くから開発が続けられ、非常に高速かつ堅牢で信頼性が高いことを売りにしているようです。
HAProxyが何であって何でないかは、 ドキュメントに箇条書きで記載 されています。
ざっくりまとめると、こんな感じのことが書かれています。
- TCP接続のプロキシとして動作させ、アクセス経路を設定することができる
- HTTPリバースプロキシとしての機能を持ち、ルールに従ってリクエストを別のサーバに渡すことができる
- このとき、URLやヘッダの書き換えも行える
- SSLやHTTP圧縮を肩代わりできる
- TCP/HTTPの正規化器(normalizer)となる
- 不正なトラフィックからの防護を提供する
- 負荷分散機能を提供する
- ロギング機能を持つので、ネットワーク上の観測点(an observation point)として機能させることができる
- トラフィックのコントロールができる
- 例えば、同時接続数の制限
- 例えば、IPベースのフィルタリング
一方で以下のような機能を持たない、とされています2。
- HTTPプロキシではない。つまりインターネットへのアクセスするブラウザがアクセスするような性質のものではない
- キャッシュもしない
- bodyの書き換えもしない
- Webサーバではない
- IPやUDPといったパケットレベルのレイヤは見ない
インストール
CentOSの場合、yumで入れられます。ただし、CentOS7であっても、執筆時点での最新安定版である1.6は入らないので、最新版が欲しければソースからビルドする必要があるかもしれません。
$ sudo yum install -y haproxy
設定の方法
設定はhaproxy.cfg
に記述します。yumからインストールしたCentOSの場合は/etc/haproxy
にあります。
例として設定ファイルは以下のような構造になっています。この例は設定ドキュメントから転載しました。
# Simple configuration for an HTTP proxy listening on port 80 on all
# interfaces and forwarding requests to a single backend "servers" with a
# single server "server1" listening on 127.0.0.1:8000
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http-in
bind *:80
default_backend servers
backend servers
server server1 127.0.0.1:8000 maxconn 32
# The same configuration defined with a single listen block. Shorter but
# less expressive, especially in HTTP mode.
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
listen http-in
bind *:80
server server1 127.0.0.1:8000 maxconn 32
設定ファイルはいくつかのセクションに分かれています。大きく分けて、HAProxyのプロセスとしての動作や、各種チューニングパラメータについての設定をするglobal
セクションと、プロキシとしての動作の設定をするプロキシセクションがあります。
プロキシセクションはさらにdefaults
、frontend
、backend
、listen
に細分化されていることが分かると思います。次のような役割の違いがあるので、それに従って書き分けます。
-
frontend
には、プロキシとしてアクセスを受ける側についての設定をします -
backend
には、プロキシとしてアクセスを振り分ける先のサーバについての設定をします -
listen
には、フロントエンドとバックエンドを合わせて一つのプロキシ設定にしたものを、まとめ書きすることができます -
defaults
に書いた設定は、それに続くセクション全てで有効になります。つまり共通する設定をdefaults
にまとめることができます-
defaults
によって、そこまで有効だったデフォルトパラメータはリセットされます
-
とりあえずログを取れるようにする
yumでインストールした直後は、起動させることはできてもログが出ません。とりあえずログが見えるようにしました。
ロギングの方法は複数提供されていますが、一番シンプルなのはsyslogで渡す方法です。HAProxy側の設定項目としてlog
パラメータを設定します。
http://cbonte.github.io/haproxy-dconv/configuration-1.6.html#3.1-log
global
log 127.0.0.1 local2
これでローカルホストのUDPポート514を利用してログを送るようになります。2番目のパラメータであるファシリティは、ここではインストール時のテンプレートにならって、local2
をそのまま利用します。
ログを受け付けられるように、rsyslogの設定も変更してUDPを有効化しておきます。
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514
ファシリティlocal2
のログ出力を/var/log/haproxy.log
に向けます3。
$ sudo touch /etc/rsyslog.d/haproxy.conf
local2.info /var/log/haproxy.log
local2.* ~
設定を反映するために、rsyslogとhaproxyをrestartします。
$ sudo service rsyslog restart
$ sudo service haproxy restart
/var/log/haproxy.log
が作成されログが出始めたら成功です。
基本的なロードバランス機能の確認
ロードバランス機能を設定することで動作確認をします。ここでは、Sinatraを用いた簡易サーバを用意しました。ロードバランスの状況を分かりやすくするために、プロセスIDを出力するようにしてあります。
require 'sinatra'
get '/' do
"Hello HAProxy!! pid=#{Process.pid}\n"
end
HAProxy側の設定としては、以下のようなものを用意しました。デフォルトのテンプレートを軽く修正したものです。
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
defaults
mode http
log global
option httplog
timeout connect 10s
timeout client 1m
timeout server 1m
frontend main *:5000
default_backend app
backend app
balance roundrobin
server app1 127.0.0.1:5001 check
server app2 127.0.0.1:5002 check
この設定では、フロントエンドがポート5000での待ち受けをし、ラウンドロビンに基づいてローカルホストのポート5001と5002にアクセスを割り振ります。ちなみにtimeout
の3つを消してしまうとwarningが出てしまいました。理由はよく分かっていません……。
$ ruby serve.rb -p 5001 2>/dev/null &
[1] 15176
$ ruby serve.rb -p 5002 2>/dev/null &
[2] 15220
$ curl localhost:5000/
Hello HAProxy!! pid=15176
$ curl localhost:5000/
Hello HAProxy!! pid=15220
$ curl localhost:5000/
Hello HAProxy!! pid=15176
$ curl localhost:5000/
Hello HAProxy!! pid=15220
ラウンドロビンしていることが確認できます。片側を落としてさらにcurlで叩いてみます。
$ kill 15176
$ curl localhost:5000/
Hello HAProxy!! pid=15176
[1] - 15176 done ruby serve.rb -p 5001 2> /dev/null
$ curl localhost:5000/
Hello HAProxy!! pid=15220
$ curl localhost:5000/
<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>
$ curl localhost:5000/
Hello HAProxy!! pid=15220
$ curl localhost:5000/
Hello HAProxy!! pid=15220
何か見えてはいけないものが一瞬見えていますが、とはいえ、ちゃんと停止したサーバの切り離しができている様子です。この辺りの微妙な挙動は要検証でしょうか。パラメータもたくさんあるし……。
まとめ
HAProxyの概要・設定の書き方・基本的な設定と動作確認をしてみる所までを調べてまとめました。
HAProxyはものすごく多機能です。この記事でまとめた機能はほんの一部にすぎません。例えばACL、HTTPヘッダのrewrite、stick-tablesなどには折を見て触れてみたいところではあります。
参考資料
ドキュメント類は最新の1.6系のものを参照しました。記事で動作させてみたのは1.5系なのですが、基本機能ではそこまで違いはないだろうし……?