技術者ブログ
クラウド型WAF「Scutum(スキュータム)」の開発者/エンジニアによるブログです。
金床“Kanatoko”をはじめとする株式会社ビットフォレストの技術チームが、“WAFを支える技術”をテーマに幅広く、不定期に更新中!
Dozensでウェブサーバの負荷分散・冗長化を実現するDozensHAをリリースしました
はじめに
Dozensはシンプルで使いやすいDNSサービスです。ウェブブラウザからログインして使用するという通常の使い方の他に、アプリケーションから直接APIを呼び出すことで各種のDNSの操作ができるようになっています。今回、ウェブサーバの死活監視とDozensによる動的なDNSレコード内容の変更を組み合わせ、負荷分散や冗長化を実現するソフトウェア『DozensHA』を開発し、オープンソースライセンスとしてリリースしました。非常にシンプルな設定ファイル1つだけで、簡単に広域負荷分散や冗長化を行うことができます。
何が可能なのか?
DozensHAは、設定ファイルに記述されているウェブサーバのIPアドレス(複数可)に対してHTTPリクエストを送信し、200や302等の正常なステータスコードが指定時間内に返ってくるかどうかをチェックします。正しく反応があったIPアドレスについては、Dozens側にAレコードが存在しているかどうかを確認し、存在していない場合にはAレコードを新規に作成して登録します。
ウェブサーバの反応がない場合には、サーバが落ちていると判断し、Dozens側にAレコードが存在していれば、それを削除します。この際、登録されているすべてのウェブサーバが落ちている場合には、ソーリーサーバのIPアドレスとして設定ファイルに記述されているIPアドレスについてAレコードを新規に作成し、登録します。なお、落ちているかどうかの判定には、チェック回数の閾値やタイムアウト値が指定可能です(後述)。
これによって、以下が実現されます。
- 複数のウェブサーバを同時並行的に監視し、障害が起こったウェブサーバのみを削除する
- 障害から回復したサーバには、またアクセスが行われるよう、Aレコードを追加し元の状態に戻す
- すべてのウェブサーバが落ちた場合には、ソーリーサーバへアクセスされる状態にする
- ソーリーサーバが使われている状態において、いずれかのウェブサーバが復旧したら、そちらにアクセスがされる状態に戻す
いわゆるDNSベースの負荷分散・冗長化を実現するものであり、ロードバランサーや仮想IPアドレス等を使う、ひとつのデータセンター内で閉じたものとは性質が異なります。そのため、東京において異なるクラウド間で負荷分散を実現したり、日本とシンガポール間のような広域で冗長化を行うことなどが可能です。また、シンプルなDNSベースなので、インターネット上ではなく、プライベートネットワーク内でのデータベースサーバやアプリケーションサーバの負荷分散や冗長化にも使用可能です。
アプリケーションの稼働形態
DozensHAはスタンドアローンなデーモンとして稼働するアプリケーションです。そのため、本運用の際にはDozensHAを稼働させるサーバをひとつ用意する必要があります。DozensHA自体の冗長化については考慮されていないため、このプロセスの死活自体は、別途監視をする必要があります。
ダウンロードと使用方法
ダウンロードはGitHubから行えるようになっています。開発に使用した言語はJavaであり、実行にはJREが必要になります。
ソースコードを展開したディレクトリでantコマンドを実行すると、『output』ディレクトリの中にコンパイルされたバイナリやシェルスクリプト、設定ファイルのサンプルなどが生成されます。antコマンドがインストールされていない環境では、javacでコンパイルを行ってください。メインのクラス名は『net.jumperz.app.MDozensHA.MDozensHA』です。起動の際には引数として設定ファイルのファイル名を渡します。
『output』ディレクトリにあるrun.shの内容は以下のようになっています。
java -cp lib/dozensHA.jar:lib/jumperz_util.jar:lib/jsonic-0.9.6.jar net.jumperz.app.MDozensHA.MDozensHA http-example.conf
設定ファイルのサンプル(http-example.conf)は次のようになります。
{ "zone" : "example.jp", "user" : "John", "apiKey" : "c59548c3c576228486a1f0037eb16a1b", "hosts" : [ { "class" : "HTTP", "ttl" : 60 "sorryServer" : "192.168.1.10", "failover" : { "interval" : 300, "timeout" : 15, "threshold" : 3 }, "failback" : { "interval" : 60, "timeout" : 15, "threshold" : 2 } "host" : "www.example.jp", "ipList" : [ "192.168.1.8", "192.168.1.9" ], "args" : { "httpHeader" : [ "Host: www.example.jp", "User-Agent: DozensHA Health Check Agent" ] } } ] }
このように設定ファイルはJSON形式となっています。上記の場合、簡単に内容を説明すると、次のようになります。
- ウェブサーバとして、192.168.1.8と192.168.1.9の2台を使用する
- ソーリーサーバとして、192.168.1.10を使用する
- 5分に一度監視を行い、3回連続でアクセスに失敗した場合には、サーバが落ちていると判定する
- フェイルオーバーした状態(ソーリーサーバが表示される状態)から復帰を試みる場合、1分に一度ウェブサーバへアクセスを試みる。2回連続で正常にアクセスできれば、ウェブサーバが復旧したと判断し、フェイルバックが行われる
設定ファイルの各項目について
各項目についての解説を行います。
zone
Dozens.jpに登録しているドメイン名です。
user
Dozens.jpのアカウント名です。
apiKey
DozensのAPI呼び出しに必要となるAPIキーです。Dozensの管理画面から取得できます。
hosts
監視対象のホスト(www.example.jpのように、FQDNで表現されるもの)をリストで扱う項目です。この例ではwww.example.jpの1つのみが記述されていますが、2つ以上のホストを監視することも可能です。
class
監視に使用されるプロトコルです。現在、HTTP/HTTPS/TCPの3種類が実装されています。HTTPとHTTPSはそれぞれ500よりも小さいステータスコードが返ってくることを正常な状態と判定します。TCPでは、TCP接続が可能であることが正常な状態と判定します。Javaを使って監視エージェントを実装することで、他のプロトコルにも簡単に拡張が可能です。独自に監視エージェントを実装する場合には、そのクラス名をパッケージ名を含む形でこの項目で指定してください。実装するクラスはnet.jumperz.app.MDozensHA.MAgentを継承する必要があります。
ttl
Aレコードを新規に登録する際に選択されるTTLです。選択可能な値についてはDozens.jpのサイトを参照してください。
sorryServer
ソーリーサーバのIPアドレスです。
failover
サーバの正常稼働時に使用される項目群です。ここに記述されている条件に従ってフェイルオーバーが行われます。
interval
各サーバの死活監視を行う間隔で、単位は秒です。複数のサーバが監視対象の場合、それぞれの監視は並行して行われます。
timeout
監視のタイムアウト値で、単位は秒です。この時間の間に正常にHTTPレスポンスが受信できなかったり、あるいはTCP接続が行えなかった場合には、その監視は失敗したと判定されます。
threshold
監視がこの値の回数、連続して失敗した場合に、サーバが落ちたと判定されます。
failback
フェイルオーバーした状態では、フェイルバックするための監視が行われます。そのため、設定項目のうち、『failover』ではなく、こちらの『failback』の項目群が使われます。interval/timeout/thresholdはほぼ同じ意味となり、条件が満たされればフェイルバックして正常な状態へと復帰します。
host
監視対象となるサーバのホスト名(FQDN)です。
ipList
監視対象となるサーバのIPアドレスのリストです。複数指定可能です。
args
監視のHTTPリクエストの中身(リクエストヘッダ)を追加したい場合に、例のようにhttpHeaderなどを記述することでコントロールが可能になります。また、『class』の値がTCPの場合には、後述するようにポート番号を指定するために使用されます。
httpHeader
追加したいHTTPヘッダフィールドを記述します。
port
サーバのポート番号を記述します。HTTPはデフォルトで80番、HTTPSではデフォルトで443番が使用されますが、これらとは異なるポートを監視したい場合に使用します。1234番ポートで稼働するTCPサーバを監視する場合の例は次のようになります。
"args" : { "port" : 1234 }
default
オプションとなる項目です。多数のホストを同時に監視する場合、各ホストの設定において重複する項目を一箇所に記述するために使うことができます。例として、次のような記述ができます。
{ "zone" : "example.jp", "user" : "John", "apiKey" : "c59548c3c576228486a1f0037eb16a1b", "default" : { "class" : "HTTP", "ttl" : 60, "failover" : { "interval" : 300, "timeout" : 15, "threshold" : 3 }, "failback" : { "interval" : 60, "timeout" : 15, "threshold" : 2 } }, "hosts" : [ { "sorryServer" : "192.168.1.10", "host" : "www.example.jp", "ipList" : [ "192.168.1.8", "192.168.1.9" ], "args" : { "httpHeader" : [ "Host: www.example.jp", "User-Agent: DozensHA Health Check Agent" ] } }, { "sorryServer" : "192.168.2.10", "host" : "www2.example.jp", "ipList" : [ "192.168.2.8", "192.168.2.9" ], "args" : { "httpHeader" : [ "Host: www2.example.jp", "User-Agent: DozensHA Health Check Agent" ] } } ] }
この例ではwww.example.jp及びwww2.example.jpの2つのホストが監視対象となっています。フェイルオーバーおよびフェイルバックの条件が同じ場合には、このように『default』の項目に設定項目を切り出すことで、各ホストの設定には記述しなくて済むようになります。Scutumでは実際にひとつのDozensHAインスタンスで20以上のFQDNを同時に監視しており、default項目を活用しています。
まとめ
今回は、SaaS型WAFサービス、Scutum(スキュータム)の技術チームで開発した、HA用のアプリケーション、DozensHAをご紹介しました。シンプルなJSON形式の設定ファイル1つだけで、DNSベースの負荷分散・冗長化を実現します。Amazon EC2の無料使用枠とDozensのフリーアカウントを組み合わせれば、なんと無料で遠距離冗長化も可能です。ぜひ使ってみてください。