2007年05月22日

知っていても損はしないkeepalivedの話 〜 MISC_CHECKの注意点

はてなブックマークに登録

 keepalived では様々なヘルスチェック方式がサポートされています。

  • HTTP_GET
  • SSL_GET
  • SMTP_CHECK
  • TCP_CHECK
これらの使い方はなんとなく想像がつくと思いますが、これら以外のサービスのヘルスチェックをするにはどうすればいいのでしょうか。
例えば DNS とか FTP とかあれとかこれとか・・・

 FTP は最悪 TCP_CHECK でお茶を濁すって手もありますが、FTP サーバがポートをオープンしたまま応答不能になることも考えられるので、あまりお勧めできません。また、DNS をチェックする機能は keepalived にはありません。

 そんな時に使うのが MISC_CHECK です。今回は MISC_CHECK を利用する上での注意点や設定のサンプルを紹介したいと思います。

■ MISC_CHECK とは
 指定したプログラムを実行して、その終了コードによってリアルサーバを UP したり DOWN させる機能です。

■使い方
 使い方はとっても簡単です(笑)

    MISC_CHECK {
      misc_path <実行コマンド>
      misc_timeout <タイムアウト(秒)>
    }

misc_path で指定されたコマンドを実行し、終了コードが0ならば成功、それ以外なら失敗と見なします。また、misc_timeout 以内にコマンドが終了しない場合も失敗になります。misc_dynamic という設定を追加すると、終了コードの値によってリアルサーバの weight を変える事ができるようになります。

# If set, exit code from healthchecker is used
# to dynamically adjust the weight as follows:
#   exit status 0: svc check success, weight
#     unchanged.
#   exit status 1: svc check failed.
#   exit status 2-255: svc check success, weight
#     changed to 2 less than exit status.
#   (for example: exit status of 255 would set
#     weight to 253)
misc_dynamic

■ 注意点など
 「これならヘルスチェック用のスクリプトをさくっと書いて misc_path に設定するだけで何でもできる!」と思うかもしれませんが、いくつか注意しなければならない点があります。

keepalived は MISC_CHECK で起動したプロセスを kill しません。
例えば以下のような設定をしてみます。

virtual_server 10.0.0.1 80 {
  delay_loop 5
  lb_algo rr
  lb_kind DR
  real_server 192.168.1.1 80 {
  MISC_CHECK {
    misc_path "/bin/sleep 3600"
    misc_timeout 10 
  }
}

この設定で keepalived を起動すると
  1. /bin/sleep 3600 を実行
  2. 10秒待つ(misc_timeout)
  3. 終了しないので(あたりまえですが・・・)リアルサーバのステータスをダウンにする
  4. 5秒待つ(delay_loop)
  5. /bin/sleep 3600 を実行
  6. (以下繰り返し)
となり、sleepプロセスが増殖し続けてしまいます。
つまり、MISC_CHECK から呼び出されるプログラムは、リアルサーバに何が起こっても確実に自分で終了できる必要があるわけです。

ヘルスチェックスクリプトを書く場合は、リアルサーバが応答不能になった場合でも正常に動作できるように、注意する必要があります。さもないと、

  1. どっかのリアルサーバに障害が発生する
  2. プロセスが増え続ける
  3. プロセス数がいっぱいになる
  4. 他のヘルスチェックを起動できなくなる
  5. 関係ないサービスまで停止する
なんて事が起こるかもしれません。


■そうならないためには
 それでは、MISC_CHECK で利用したいコマンドがきちんと終了できるかどうかを確認する方法をご紹介します。確認すべき事は大きくふたつ

  • TCP接続ができないときにエラーになること
  • TCP接続はできるけどサーバから応答が無いときにエラーになること

わかりやすい例として ssh クライアントを使ってみましょう。
2台のマシン(HOST1,HOST2)を用意して、以下のようなコマンドを実行してみて下さい。
host2 の8022番ポートではなんのサービスも動いてないので接続が拒否されます。

host1: $ ssh -o "ConnectTimeout=5" -p 8022 host2
ssh: connect to host host2 port 8022: Connection refused

次に、host2 のネットワークケーブルをはずして実行してみます。

host1: $ ssh -o "ConnectTimeout=5" -p 8022 host2
ssh: connect to host host2 port 8022: Connection timed out

TCP接続できない状況においては、最長でも5秒でコマンドが完了することが確認できると思います。

それでは以下のようにするとどうなるでしょうか。

host2: $ nc -l -p 8022
host1: $ ssh -o "ConnectTimeout=5" -p 8022 host2

host2 では nc コマンドの -l オプションを使って8022番ポートをオープンしておきます。そして host1 から ssh クライアントで接続してみます。どれだけ待っても ssh コマンドはエラーになりません。
というわけで、-o "ConnectTimeout=5" の指定はTCP接続のタイムアウトを指定するためのものなので、TCP接続が完了したあとでは意味を持たないのです。
つまりこれは、sshヘルスチェックのために

MISC_CHECK {
  misc_path "ssh 192.168.1.1 exit 0"
  misc_timeout 10 
}

と記述すると、サーバがフリーズした時にヘルスチェック用の ssh プロセスが増殖してしまう事を意味しています。
ssh コマンドをそのまま MISC_CHECK に利用するのは危険なのです。


■ 設定方法のサンプル
最後に、FTPとDNSをチェックするMISC_CHECKの使用例をご紹介します。

DNSヘルスチェック

MISC_CHECK {
  misc_path "/usr/bin/dig +time=001 +tries=2 @192.168.1.1 klab.org"
  misc_timeout 5
}


FTPヘルスチェック

MISC_CHECK {
  misc_path "echo -en 'NOOP\r\nQUIT\r\n' | nc -w 5 -n 192.168.1.1 21 | egrep '200 NOOP command successful'"
  misc_timeout 5
}

たいていのFTPサーバではNOOPコマンドが使えます。これはFTPサーバが稼働しているかどうかを調べる為のコマンドで、ログオンせずに利用可能ですので、ヘルスチェックの為のFTPアカウントを作る必要はありません。

この例ではncを使ってコマンドの送受信をしています。ncの-wオプションは、接続時のタイムアウトだけでなく、リードタイムアウトも兼ねているので、リアルサーバが応答不能になっても必ず終了してくれます。

$ nc -h 2>&1 | grep '\-w'
  -w secs  timeout for connects and final net reads
klab_gijutsu2 at 22:44│Comments(0)TrackBack(0)

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント