2007年06月01日
Keepalivedのヘルスチェックを強化するパッチ
keepalived は MISC_CHECK を利用すると、標準の機能でサポートされていないヘルスチェックをすることができますが、MISC_CHECKの注意点でご紹介したように、安全に運用するためには結構気を使わなければいけません。また、比較的短い周期で繰り返さなければならないヘルスチェックでは「チェックの度に別プロセスを起動する」というアプローチは、できるだけ避けたいと考えるかもしれません。
というわけで、それなりにニーズがあると思われるヘルスチェック機能を keepalived-1.1.13 に組み込んでみましたのでパッチを公開します。
ただしこのパッチ、まだDSASの本番環境には適用していません。
つまり稼働実績がありません。今は開発環境での試験運用中ですので、その点をご理解の上でご利用下さい。不具合報告などいただけると、とてもとても嬉しいです。
追加した機能
FTP_CHECK: FTPサーバがNOOPコマンドに応答できるかをチェックする
DNS_CHECK: DNSサーバがレスポンスを返すことができるかをチェックする
SSL_HELLO: サーバがSSLハンドシェイクに応答できるかをチェックする
というわけで、それなりにニーズがあると思われるヘルスチェック機能を keepalived-1.1.13 に組み込んでみましたのでパッチを公開します。
ただしこのパッチ、まだDSASの本番環境には適用していません。
つまり稼働実績がありません。今は開発環境での試験運用中ですので、その点をご理解の上でご利用下さい。不具合報告などいただけると、とてもとても嬉しいです。
$ wget http://www.keepalived.org/software/keepalived-1.1.13.tar.gz $ wget http://log.blog.klab.org/support/20070601/keepalived-extcheck.patch $ tar zxvf keepalived-1.1.13.tar.gz $ cd keepalived-1.1.13 $ patch -p 1 < ../keepalived-extcheck.patch $ ./configure $ make # make install
【書式】
virtual_server addr port { real_server addr port { FTP_CHECK { connect_port <PORT> bind_to <ADDR> connect_timeout <INT> retry <INT> delay_before_retry <INT> } } }
【設定項目】
名前 | 説明 | 初期値 |
---|---|---|
connect_port | FTP接続するポート番号を指定します | 21> |
bind_to | 送信元アドレスを指定します | なし> |
connect_timeout | タイムアウト時間を秒単位で指定します | 5> |
retry | 何回ヘルスチェックに失敗したらリアルサーバがダウンしたと見なすかを指定します | 3> |
delay_before_retry | リアルサーバダウン時のヘルスチェック再試行間隔を秒単位で指定します | 3> |
【書式】
virtual_server addr port { real_server addr port { DNS_CHECK { port <PORT> timeout <INT> retry <INT> type <STRING> name <STRING> } } }
【設定項目】
名前 | 説明 | 初期値 |
---|---|---|
port | DNS問い合わせをするポート番号を指定します | 53> |
timeout | タイムアウト時間を秒単位で指定します | 5> |
retry | 何回チェックに失敗したらリアルサーバがダウンしたと見なすかを指定します | 3> |
type | DNSに問い合わせるレコードタイプを指定します | A> |
name | DNSに問い合わせる名前を指定します | なし> |
【書式】
virtual_server addr port { real_server addr port { SSL_HELLO { connect_port <PORT> connect_timeout <INT> retry <INT> delay_before_retry <INT> common_name <STRING> } } }
【設定項目】
名前 | 説明 | 初期値 |
---|---|---|
connect_port | SSL接続するポート番号を指定します | 443> |
connect_timeout | タイムアウト時間を秒単位で指定します | 5> |
retry | 何回ヘルスチェックに失敗したらリアルサーバがダウンしたと見なすかを指定します | 3> |
delay_before_retry | リアルサーバダウン時のヘルスチェック再試行間隔を秒単位で指定します | 3> |
common_name | サーバ証明書のCNを指定します。指定しない場合はCNのチェックを行いません。 | なし> |
【SSL_GETとの違い】
keepalived にはすでに、「SSL_GET」というヘルスチェック機構がありますが、これはあくまで HTTPS に対するチェックなので、他のプロトコル (pop3s や smtps など) には対応できません。かといって TCP_CHECK では、サービスがフリーズしたり過負荷状態で応答できなくなったとしてもTCP接続が可能な限り、サーバがダウンしたと見なしません。また、HTTPS のサイトであっても、クライアント認証が必要な場合は SSL_GET を利用できないのも悩ましいところです。
SSL_HELLOでは、アプリケーション層のプロトコルを検査しません。対象サーバに対して SSL ハンドシェイクを試み、ServerHelloDoneが確認できればヘルスチェック成功とします。そのため、SSL の先が Webサーバだろうとメールサーバだろうとなんだろうと、ヘルスチェックすることができますし、クライアント認証が必要なサービスに対しても利用可能です。以下に、通常の SSL ハンドシェイクの流れと、SSL_HELLO の動作を示します。
「通常のSSLハンドシェイクの流れ」
C ->「こんにちは!こんにちは!」-> S # ClientHello C <-「こんにちは!こんにちは!」<- S # ServerHello C <-「サーバ証明書送ります!!」<- S # ServerCertificate C <-「ついでにこれもうけとって」<- S # CertificateRequest..(etc C <-「こんにちは!しおわったす」<- S # ServerHelloDone C ->「証明書必要ならおくるかも」-> S # Client Crtificate C ->「大事大事ですごにょごにょ」-> S # Client Key Exchange C ->「これが最後で最初のなのね」-> S # Finished (以下、アプリケーションプロトコルが暗号化されてごにょごにょ)
「SSL_HELLOの動作」
C ->「こんにちは!こんにちは!」-> S # ClientHello C <-「こんにちは!こんにちは!」<- S # ServerHello C <-「サーバ証明書送ります!!」<- S # ServerCertificate C <-「ついでにこれもうけとって」<- S # Certificate Request..(etc C <-「こんにちは!しおわったす」<- S # ServerHelloDone C ->「ごめん!ぼくおちるっす!」-> S # Alert(Fatal) (双方切断して完了)
SSL_HELLOは暗号化通信をしてないので、SSL_GETと比べてリアルサーバにかかる負荷は少ないと思います。そのかわり、SSLの先にあるサービス(WEBサーバやメールサーバ等)の機能が停止した場合、それを検出する事はできません。それでも TCP_CHECK に比べれば信頼性は高いと思いますし、SSL アクセラレータに対するチェックにも利用できると思うので、それなりに実用的なんじゃないかなあと考えています。