電話を使った異常通知

岩石です。前回私のブログでは、名前を名乗ることを忘れていました。
そのため、ブログの最初にgravatarのアイコンが表示されるようになり、寄稿者がわかり易くなるようにデザインが変更となりました。 ま、怪我の功名ということで。

システム管理

弊社が提供しているプロジェクト管理SaaS「My Redmine」をはじめとしたサービスをお客様に安心してご利用いただくためには、サービス提供に使用する機器の安定した動作を管理する必要があります。また、情報共有ツールなど社内向けのサービスもあり、これらも同様の管理が必要です。

しかしながら、機器は常に同じように動作することはありません。

などにより、システムの負荷やシステムリソースは常に変化しています。

このため、リソースの状況や、サービスが問題なく提供されているかを監視する必要があります。

システム監視ツール

弊社ではこれらの対策に、 MuninZABBIX という二つのツールを使用しています。 Munin はシステムリソースの監視に、 ZABBIX はリソース変動の記録と稼働監視に使用しています。
どちらも優れたツールで、互いに重複する機能も多いのですが、あえて弊社では2つのツールに分けて管理をしています。




今年中にZABBIXは最新版にアップグレード予定です。

監視システムもサーバ機器上で稼働するサービスですので、停止する可能性があります。よって 監視システムを監視するシステム も必要になってきます。

これに対しては、弊社ではZABBIXを複数使用して相互監視をしたり、OSのコマンドで監視システムのプロセスが動作しているかなどをチェックしたりすることで監視の停止を防ぐようにしています。

通知

常時稼働するシステムの監視は24時間365日行う必要がありますが、常時すべての情報の取得や動作状況について人間が凝視し続けることは、普通に考えて実現不可能です。
このため異常発生時にはなんらかの手段で(「常で無いこと」という意味としての)異常を人に認識させるための通知を行うことが必要になります。一般的には電子メールでの通知が行われます。

電子メールが連絡手段として一般に普及し基盤として成立していること、また携帯電話(の電子メール)の普及で通知をいつどこでも受け取れるようになったこと、などから電子メールでの通知は最も利用しやすいです。
インターネットの電子メールは、配送完了通知の仕組みが定義されていなかったこともあって、10年ぐらい前までは電子メールの配送遅延などが普通に起きていましたが、最近はトラブルが起きてない限り、ほとんど違和感なく直ちにメールが届くようになりました。

電子メールだけの通知では、電子メール側のシステム異常などが起きていた場合、通知が行われませんので、その他の手段も併用して利用されることが多いです。
たとえば、

などがよく利用されていて、事例も多いです。

電話の呼び出し


Photo by Tim G. Photography

弊社では上記のような手段も試したりしたのですが、根本的に違った仕組みで 確実に 通知を行いたいと考えました。
検討の結果、緊急性の高い通知については、電子メールやSNSなどの通知に比べて、より確実に気を付かせることができると判断し、関係者の電話を呼び出すことにしました。

システムで何かを検出した際に、何かを実行する処理というのは、それほど難しいことではありません。しかし電話を呼び出すとなると仕組みが難しいのです。

気づかせることが目的なので、通話は不要で呼び出しさえ実現できれば良いのかもしれません。電話回線を監視機器にモデム(アナログ回線で通信を行う機器、最近はあまり使用しないよね?)を経由して接続し、モデムへ発信のコマンドを送れば実現できそうな気もします。
しかし、インターネット上のクラウド上のサーバでは、物理的にその場へ電話回線を引くことが出来ないので、その方法は実現できません。

AsteriskというLinux上で動作するオープンソースソフトウェアの電子交換機があるのですが、これを使用すると連携は簡単に出来そうです。
しかし、一般の電話機に発信するための電話回線サービスを利用する必要があり、これもなかなか適したサービスが無く、またAsteriskサーバの構築や維持管理、サービス自体の監視なども必要になってきます。しかもこのサーバって、ほとんど発生しない異常時のみ使用するのでコスト効率もよくありません。

そこで当社では Twilio という電話サービスを連携して通知を行うことにしました。

Twilio

Twilio

Twilioは、詳細を簡単に説明するのがとても難しいのですが、上記サイトの言葉を借りると クラウド電話APIサービス ということになります。 電話の設備を持っていなくても、発信者・受信者ともにパソコン上で通話を行ったり、音声合成やチャットなどの基盤を利用して自社のサービスなどに組み込むことができるサービスです。
基盤を提供してもらい、利用者がAPIを自由に使うことができるサービスなので、どのように使うかは利用者次第です。

ZABBIXとの連携

ZABBIXとの連携と書きましたが、ZABBIXとしては通知が必要という条件にマッチした時にコマンドを実行するように設定するだけです。

当初電話に異常の対象や状況など様々な内容を通知することを考えましたが、通知を受けた者は直ちに監視システムへアクセスし、対象のシステムへログインをおこなうため、電話で詳しい情報を伝える必要は無いと判断しました。

現在は下記のスクリプト(実際に使用しているものは少し違います)を実行し関係者に発呼しています。
普段はRubyでスクリプトを書くのですが、ZABBIXをインストールしているので、PHPで書いています。

<?php
require '/var/lib/zabbix/twilio-php-latest/Services/Twilio.php';
$unixtime = time();
$callnum = $argv[1];
$fh = fopen("/var/lib/zabbix/event_time" . $callnum, "r");
$event_time = fgets($fh, 4096);
fclose($fh);

if($unixtime - $event_time > (60 * 5)) {
  if (!function_exists('json_encode')) {
    require_once '/var/lib/zabbix/Services_JSON-1.0.3/JSON.php';
    function json_encode($value) {
      $service = new Services_JSON();
      return $service->encodeUnsafe($value);
    }
    function json_decode($json, $assoc = false) {
      $service = new Services_JSON($assoc ? SERVICES_JSON_LOOSE_TYPE : 0);
      return $service->decode($json);
    }
  }
  $sid = "<TwilioのID>"
  $url = "<音声合成用の通話文字が記載されたXMLファイルのURL>";

  $call = $client->account->calls->create(
      "<発信元電話番号>",
      $callnum,
      $url,
      array(
        'Method' => 'GET',
        'FallbackMethod' => 'GET',
        'StatusCallbackMethod' => 'GET',
        'Record' => 'false',
      )
  );
  echo $call->sid;
}
$fh = fopen("/var/lib/zabbix/event_time" . $callnum, "w");
fwrite($fh, $unixtime);
fclose($fh);
?>

Twilio提供のライブラリを読み込んだ後、発信先電話番号のファイルを作成し、その時点の時刻を保存しています。
そして、次の起動時にそのファイルの時刻と時刻の差が5分以内であれば、発呼を行わないようにしています。
これは同じ異常が発生したときに、既に障害対応しているはずなので続いて呼び出しを行うことを防ぐための処理です。

そしてTwilioからアクセス可能なWebサーバなどに、音声合成用のXMLファイルを配置してアクセスさせることで、電話がかかってきたらその音声が流れるようにしています。
仮に電話が掛かってきて、「大変な事になってます」という声を流すようにするには、

<Response>
<Say voice="alice" loop="0" language="ja-jp">大変な事になってます。</Say>
</Response>

というファイルをTwilioからもアクセス可能なWebサーバにおいて、そのURLを指定すればよいです。音声合成については、普通の日本語であれば、問題を感じたことはありません。

もしXMLファイルの内容が外部の方から閲覧されると困る場合は、ランダムな文字かつ長めのファイル名でXMLファイル作成し、上記の様にファイルを配置して、発呼の後ファイルを削除されるようにスクリプトを組まれると良いかと思います。それでも機密な内容は載せるべきでは無いと思われるので、別の手段で通知した方が良いです。
実際の運用で使われるには、発呼の失敗や時刻ファイルの作成などが上手くいかなかった時の処理などをふまえたエラー処理を追加されると良いのでは無いでしょうか。

最後に

システムは人間が指示したように正直に動く物なのですが、絶対的な安定や安心を望むことはできません。
よりよい運用を目指して、仕組みや連携を上手く使いこなしたいですね。

ファーエンドテクノロジーからのお知らせ(2024/04/24更新)
入門Redmine 第6版 出版記念企画セミナー「Redmineのアクセス制御」【2024/5/30開催】
入門Redmine 第6版(2024年3月23日発売)の書籍から「Redmineのアクセス制御」について解説します。
My Redmine 初回ご契約で「入門Redmine 第6版」プレゼントのお知らせ
Redmineのクラウドサービス「My Redmine」を初めてご契約いただいたお客様にRedmine解説書「入門Redmine 第6版」を進呈いたします。
2024年度ブランドパートナーに島根県在住のモデル ユイさんを継続起用
ユイさん(モデルスタジオミューズ所属)をファーエンドテクノロジーの2024年度ブランドパートナーとして継続して起用します。
My Redmine スタンダードプランおよびAdminサポートデスクプランの料金改定のお知らせ【2024年4月ご利用分より】
2024年4月ご利用分より、My Redmine スタンダードプラン(民間企業・個人向け及び官公庁向け)とAdminサポートデスクプランの料金を改定いたします。
Redmineの最新情報をメールでお知らせする「Redmine News」配信中
新バージョンやセキュリティ修正のリリース情報、そのほか最新情報を迅速にお届け