2007年05月18日
知っていても損はしないkeepalivedの話 〜 notification_emailの罠
このブログではすでにお馴染みとなっている keepalived ですが、設定ファイルの書き方には少し癖があります。
今回は、keepalived を設定する上での注意点を紹介したいと思います。
なお、この内容は現在の最新バージョン(1.1.13)のものですのでご注意下さい。
keepalived.confのマニュアルを見ると、
と記述されています。
これは、ヘルスチェックが失敗してリアルサーバがダウンしたり、復旧したりしたときに、そのイベントをメールで通知するための送信先を指定する部分です。 これに従って設定ファイルを書いたところ、通知メールは正常に送信されているようですが、メールサーバが以下のようなバウンスメールを返していました。
なんと、"{@localhost" さんが見つからないっていってます!
でも設定にはそんなアドレス書いてません!
実はこれ、ブロックを開始する中括弧 "{" をメールアドレスだと思いこんでいるのです。
実際にSMTP接続をダンプしてみると、
こうなっていました。
どうやら、設定ファイルは以下のようにするのが良いようです。
こう書くことで、エラーはでなくなりました。(めでたしめでたし)
ここでちょっと気になったのですが、もし、すでに keepalived.conf(5) と同じ形式の記述で運用しているシステムがあった場合、notification_email_from で指定している送信元アドレスに、大量のバウンスメールが届いてしまっている可能性があります。普段利用しているアドレスを設定していれば構築時に気づいていることと思いますが、「通知メールの送信元なのでなんでもいいだろ」と思って設定をしている場合は要注意です。心当たりのある方は、念のためローカルメールボックスが膨大になっていないかなどを確認してみる事をお勧めします。
■なぜこうなるの?
この症状は、keepalivedがブロック開始の中括弧を認識していないことに起因しています。keepalivedのパーサは、設定ファイル中で特定のキーワードが見つかったら、キーワードに対応する処理関数を呼び出します。
notification_email の場合は keepalived/core/global_parser.c の email_handler() という関数が呼ばれます。この時点で keepalived.conf に対するファイルポインタは notification_email の次の行の先頭を指しています。
email_handler()では lib/parser.c の read_value_block() という関数でメールアドレスの一覧を取得します。このとき、read_value_block() は閉じ中括弧(EOB="}") が見つかるまで処理を続けますが、ブロックが "{" で開始されているかどうかの判別をしていません。
そのため、notification_email で改行してしまうと、"{" がメールアドレスとしてリストに追加されてしまうのです。つまり、keepalived.conf ではブロック開始の中括弧は意味をなしていません。まあ、特定のキーワードをブロック開始のサインとみることができるので必要ないとも言えますが・・・
つまり「notification_email が見つかったら、その次の行から "}" までの行を送信先メールアドレスのリストに追加する」という動作になるので "{" を書く必要はないんですね。
ただ、やはり見た感じ気持ち悪いので "notification_email {" と書きたくなってしまいますけど・・・・・
global_defs # Block id { notification_email # To: { admin@example1.com ... }
と記述されています。
これは、ヘルスチェックが失敗してリアルサーバがダウンしたり、復旧したりしたときに、そのイベントをメールで通知するための送信先を指定する部分です。 これに従って設定ファイルを書いたところ、通知メールは正常に送信されているようですが、メールサーバが以下のようなバウンスメールを返していました。
Subject: failure notice I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. {@localhost ... User unknown
なんと、"{@localhost" さんが見つからないっていってます!
でも設定にはそんなアドレス書いてません!
実はこれ、ブロックを開始する中括弧 "{" をメールアドレスだと思いこんでいるのです。
実際にSMTP接続をダンプしてみると、
RCPT TO: { RCPT TO: admin@example1.com
こうなっていました。
どうやら、設定ファイルは以下のようにするのが良いようです。
global_defs { notification_email { admin@example1.com ... }
こう書くことで、エラーはでなくなりました。(めでたしめでたし)
ここでちょっと気になったのですが、もし、すでに keepalived.conf(5) と同じ形式の記述で運用しているシステムがあった場合、notification_email_from で指定している送信元アドレスに、大量のバウンスメールが届いてしまっている可能性があります。普段利用しているアドレスを設定していれば構築時に気づいていることと思いますが、「通知メールの送信元なのでなんでもいいだろ」と思って設定をしている場合は要注意です。心当たりのある方は、念のためローカルメールボックスが膨大になっていないかなどを確認してみる事をお勧めします。
■なぜこうなるの?
この症状は、keepalivedがブロック開始の中括弧を認識していないことに起因しています。keepalivedのパーサは、設定ファイル中で特定のキーワードが見つかったら、キーワードに対応する処理関数を呼び出します。
notification_email の場合は keepalived/core/global_parser.c の email_handler() という関数が呼ばれます。この時点で keepalived.conf に対するファイルポインタは notification_email の次の行の先頭を指しています。
email_handler()では lib/parser.c の read_value_block() という関数でメールアドレスの一覧を取得します。このとき、read_value_block() は閉じ中括弧(EOB="}") が見つかるまで処理を続けますが、ブロックが "{" で開始されているかどうかの判別をしていません。
そのため、notification_email で改行してしまうと、"{" がメールアドレスとしてリストに追加されてしまうのです。つまり、keepalived.conf ではブロック開始の中括弧は意味をなしていません。まあ、特定のキーワードをブロック開始のサインとみることができるので必要ないとも言えますが・・・
つまり「notification_email が見つかったら、その次の行から "}" までの行を送信先メールアドレスのリストに追加する」という動作になるので "{" を書く必要はないんですね。
ただ、やはり見た感じ気持ち悪いので "notification_email {" と書きたくなってしまいますけど・・・・・