HAProxyのACLとCriteria
HAProxyのACLについて仕事で使う機会があったので、いくつか調べたものを復習としてメモします。(HAProxyはかなり設定可能な項目が多いので、主にCriteriaです。)
※バージョンは、1.4.8で確認しました。
nbsrv
現在稼働中のbackendのサーバー数を返します。
設定例:backend のサーバーの生存台数が2台であれば、それらに振り分ける。
frontend db_front bind :3306 acl is_db_backend nbsrv(db_backend) eq 2 use_backend db_backend if is_db_backend backend db_backend mode tcp balance roundrobin option mysql-check server db1 192.168.0.1:3306 check rise 1 fall 3 server db2 192.168.0.2:3306 check rise 1 fall 3
frontendブロックにて、aclキーワードを使用し、is_db_backendというACLを定義します。
acl is_db_backend nbsrv(db_backend) eq 2
このとき is_db_backendは、db_backendというbackendブロックの生きているサーバー数が"2"であるか?という意味を持ちます。nbsrvは数値を返すので、「eq 2」などとして数値で比較をする必要があります。
その次の行の、
use_backend db_backend if is_db_backend
で、どのbackendサーバーを使用するかという設定になります。※今回は、backendが一つしかないですが、複数定義することが可能となっています。
このときの使用条件で、is_db_backend の値を参照していて、if キーワードで is_db_backend が"2"であるかどうかを判定しています。db_backend のサーバーが全て生きていたら、db_backend のサーバーを使用します。もし、db_backend のサーバーが一つでも落ちていたら、db_backendは使用されません。
また条件を変えて、
nbsrv(db_backend) ge 1
とすれば、1つでも生きていたらという意味になるかと思います。
ちなみに、
acl is_db_backend nbsrv(db_backend) eq 2
use_backend db_backend if is_db_backend
を1行で書くとこうなります。
use_backend db_backend if { nbsrv(db_backend) eq 2 }
"{","}"を使用して記述します。※"{","}"の前後にスペースが必要です。
srv_is_up
指定されたサーバーが生きていたらTRUE、それ以外であればFALSEという結果を返します。
設定例:あるbackendのサーバーが生きていれば、そのサーバーを主系として振り分ける。
frontend db_front bind :3306 acl is_db1_up srv_is_up(db_backend1/db1) acl is_db2_up srv_is_up(db_backend2/db2) use_backend db_backend1 if is_db1_up use_backend db_backend2 if is_db2_up backend db_backend1 mode tcp option mysql-check server db1 192.168.0.1:3306 check rise 1 fall 3 backend db_backend2 mode tcp option mysql-check server db2 192.168.0.2:3306 check rise 1 fall 3
まず、frontend ブロックでの
acl is_db1_up srv_is_up(db_backend1/db1)
acl is_db2_up srv_is_up(db_backend2/db2)
の部分で2つのACLを定義しました。上の方は、db_backend1のdb1というサーバーがあがっているかどうかを定義し、下の方は、db_backend2のdb2というサーバーがあがっているかどうかを定義しています。
サーバーがあがっているかどうかの判定部分は、
srv_is_up(db_backend1/db1)
の部分になります。そして、次の2行で、
use_backend db_backend1 if is_db1_up
use_backend db_backend2 if is_db2_up
どのbackendサーバーを使用するかを定義しています。ここで2つuse_backendというキーワードを使っていて、どのbackendを利用するかという疑問があるかと思いますが、上に記述された方から先に評価をしていき、条件が満たされるものがあればそれを使用していくという動きになっています。
is_db1_upがTRUEであれば、db_backend1のサーバーを使います。もし、db_backendのdb1サーバーが落ちていた場合は、次の行のis_db2_upが評価され、db_backend2が使用されるか判定されます。
評価の方法は、nbsrvの記述部分と同じで、ifキーワードを利用しています。
src
HAProxyに接続してきているIPアドレスを意味する
設定例:特定のIPアドレス(192.168.0.1)からの接続は、サーバーAに振り分け、それ以外はサーバーBに振り分ける
rontend web_front bind :80 acl is_src src 192.168.0.1 use_backend web_a if is_src use_backend web_b unless is_src backend web_a mode http server web1 192.168.0.2:80 check rise 1 fall 1 option httpchk backend web_b mode http server web2 192.168.0.3:80 check rise 1 fall 1 option httpchk
接続してきたIPアドレスが、「192.168.0.1」であるかどうかを判定し、use_backend キーワードで振り分けを実現しています。unless は、if の反対の意味を持ちます。
acl is_src src 192.168.0.1
use_backend web_a if is_src
use_backend web_b unless is_src
src_port
src がIPアドレスに対し、こちらはポートによる設定が可能。
dst
HAProxy側のIPアドレスを意味する。
※使用するケースとして、HAProxyが稼働しているサーバーに複数のIPが割り当てられているときに使用するようなケースだと思ってます。
設定例:IPアドレスAで接続してきたリクエストは、サーバーAへ。IPアドレスBで接続してきたリクエストは、サーバーBへ振り分ける。
rontend web_front bind :80 acl is_dst dst 192.168.0.1 acl is_dst_local dst 127.0.0.1 use_backend web_a if is_dst use_backend web_b if is_dst_local backend web_a mode http server web1 192.168.0.2:80 check rise 1 fall 1 option httpchk backend web_b mode http server web2 192.168.0.3:80 check rise 1 fall 1 option httpchk
この設定の場合、「192.168.0.1」でリクエストした場合は、サーバーAへ振り分けられます。また、ローカルホストから「127.0.0.1」でリクエストした場合は、サーバーBへ振り分けられます。
srcもそうですが、違うネットワーク同士で振り分けを変えたいときに使えるか思います。
dst_port
dst がIPアドレスが対象なのに対し、こちらはポートによる設定が可能。
be_conn
backend で確立された(established)コネクションの接続数が適用されます。
設定例:一定の接続数を超えたら、エラーページにリダイレクトさせる。
backend web1
mode http
server web1 172.16.1.129:80 check rise 1 fall 3
acl is_be_conn be_conn gt 1 # テストのため"1"を設定
option httpchk
redirect location /error.html if is_be_conn
backendセクション内でaclキーワードで"1"を超える接続というACLを定義。超えたときの振る舞いとして、reirectキーワードでACLを評価するように定義しておく。
(サイズ重めの画像をWebサーバー上に配置しておき、それをブラウザで強制リロードをすばやく2度やると、リダイレクトされることを確認しました。)
他にも接続数、単位時間でのセッション作成数といったリクエスト数に応じたCriteriaもいくつかあるようです。
=>"fe_conn", "queue" , "be_sess_rate" , "fe_sess_rate"
ここまでのものは下位のレイヤーの話のものなので、上位のレイヤーになれば高度なことができるようです。
=>HTTPヘッダの内容でACLを定義、等。
ここに書いたことは本当に一部分にすぎないので、もっと有効な使い方があるかと思いますが、HAProxyはかなり高機能でお手軽に負荷分散や可用性を高めることが可能なのでおすすめです。