ブログ

ryuzeeによるブログ記事。不定期更新

Sensuを使って自由度の高い監視システムの構築を行う方法

Sensuとは

Sensuはhttp://sensuapp.org/で公開されているオープンソース(MITライセンス)のモニタリングフレームワークです。

特徴

以下のような特徴があります(公式サイトの記述を整理)

  • シンプルで融通が効き拡張性があるモニタリングフレームワーク
  • エージェント、メッセージバス、イベントプロセッサーの機能を提供
  • 要件にあわせて他のツールとの組み合わせが可能
  • クラウドを意識して開発
  • 自動でクライアント(監視対象)を登録
  • コミュニティが活発
  • RubyのEventMachineを使って作られている
  • コードはGitHubでホストされ、テストコードは高いカバレージ。TravisCIで継続的インテグレーションを実施
  • Nagiosのプラグインを再利用可能
  • 設定はすべてJSONファイルで行う
  • RabbitMQを使ったメッセージ型のアーキテクチャー
  • オムニバスインストーラーを提供

個人的な見解としては、Sensuは自由に監視システムを構築したい人には向いていると思います。 一方でZabbixなどのようなオールインワンを好む方には向いていません。 その他の内容については、http://slides.sensuapp.org/ で公開されているスライドを確認してください。

構造

Sensuの構造は単純です。 Sensuは各ノードでのCheckスクリプトの結果を受け取り、その結果が指定した条件にマッチした場合は、1つまたは複数のHandlerに結果を引き渡します。 Checkスクリプトでは例えば、Apacheのプロセスの死活監視を行ったり、ロードアベレージなどデータの収集を行うことが可能です。 Handlerはメールを送ったり、他のシステムにデータを送信したりといったアクションを実施するために使われます。 CheckスクリプトやHandlerはどんな言語でも記述することができます。

Sensuは4つのコンポーネントから構成されます。

  • Server:Checkを実行するにあたっての準備やCheckの結果の処理やイベントのハンドリングを行う。
  • Client:実際にCheckが行われる監視対象上にインストールする。Clientはチェック実行のリクエストを受けたり、Checkを実行したり、ServerにCheckの結果を送信。Client単体で定期的にチェックを実施するように制御することも可能。
  • API:Sensuのデータに対するRESTベースのAPIを提供。このAPIをコールすると登録済みのClientの情報や現在のイベントなどを取得可能。次に紹介するDashboardはAPIを使って実装されている
  • Dashboard:SensuのWebベースのダッシュボードで、Checkの結果NGだったものを表示したりすることが可能。ただし機能は少ない。

インストール

インストールはChefまたはPuppetを使って行うことが強く推奨されています。 Chefの場合は、https://github.com/sensu/sensu-chef でクックブックが公開されていますので、これを使います。 なお、筆者は分かりやすくするために、Server用とClient用のラッパークックブックを作成して使っています。Checkスクリプトの代表的なものをダウンロードして配置するようにしたり、serverspecでテストを少しだけ追加したりしています。(個人用なのでドキュメントとかないですw)

今回はテスト用に、Vagrantfileを用意しました。 https://github.com/ryuzee/vagrant-sensu-sample で公開していますので、これをチェックアウトして、vagrant up --provision を実施すれば、環境が一式作成され、Sensuの動作を試すことができます。

  • このVagrantfileを使うと合計で4台の仮想マシンを起動します。1台はServer、2台がClient、そしてGraphite用のマシンです
  • Vagrantのboxとして、https://github.com/opscode/bento で公開されているBentoのboxを使っています。初回起動時にboxのダウンロードが発生するため時間がかかる可能性があります
  • BentoのboxにはChef Client/Chef Soloが含まれていないため、起動時に自動でインストールが必要です。vagrant-omnibus プラグインをインストールしておいてください

このVagrantfileを使うとSensuのDashboardやGraphiteへのCheck結果の送信を見ることができます。

SensuのDashboardで警告が表示されているところ Warning

Sensuでロードアベレージデータを収集し、Graphiteに送信してグラフ化したもの LoadAverage

Checkスクリプトの仕様

Checkスクリプトは2通り存在。1つは状態を監視するもの、もう1つはデータを送信するものです。 状態を監視する場合のスクリプトは以下のような形の仕様になります。

  • exit 0 正常
  • exit 1 WARNING
  • exit 2 CRITIVAL
  • exit 3 不明またはカスタムエラー

このCheckスクリプトは監視対象となるClientに配置します。通常、/etc/sensu/plugins 以下です。 また多くのCheckスクリプトがGitHubで公開されています。https://github.com/sensu/sensu-community-plugins を確認してください。 データを収集・送信するものの例としては、ロードアベレージをチェックするスクリプトがhttps://github.com/sensu/sensu-community-plugins/blob/master/plugins/system/load-metrics.rb で公開されているのでこれを確認すると良いでしょう。

一方でこのCheckをどのClientで実施するか、どんな間隔で実施するか、そのCheckの結果をどのように処理するかについてはServer側で設定します。この設定はServer側の/etc/sensu/conf.d以下に配置します。

Server側、/etc/sensu/conf.d/check-cron.json

{
  "checks": {
    "cron_check": {
      "handlers": ["default"],
      "command": "/etc/sensu/plugins/check-procs.rb -p cron -C 1 ",
      "interval": 60,
      "subscribers": ["all"]
    }
  }
}

この例では、allをSubscribeすることを設定している全Clientにて、60秒間隔でcommandで指定された内容を実行し、結果についてはdefaultのHandlerで通知するという設定になっています。

Subscription

ClientでどのCheckを実施するかについては、サブスクリプションで決定します。 この定義はClient側の /etc/conf.d/client.json にて定義します。

{
  "client": {
    "name": "client01",
    "address": "192.168.33.200",
    "subscriptions": [
      "web",
      "all"
    ]
  }
}

この例では、client01というClientはwebおよびallに属するCheckを実施するようになります。 なお、ClientはServerがどこにあるかを知っている必要があります。この定義はClientの /etc/sensu/config.json で行います。 データはServer側のRabbitMQにあるため、これに対する接続の指定が必要です。またServer側でRabbitMQのポートが開いている必要があります。

{
  "rabbitmq": {
    "host": "192.168.33.10",
    "port": 5672,
    "vhost": "/sensu",
    "user": "admin",
    "password": "password"
  }
}

Handler

HandlerはCheck結果を受け取ったあとの処理を定義します。たとえばメールを送信するmailという名前のHandlerは以下のようになります。 このJSONファイルもServer側の/etc/sensu/conf.d 以下に配置します。

{
  "handlers": {
    "mail": {
      "type": "pipe",
      "command": "mail -s 'alert' webmaster@ryuzee.com"
    }
  }
}

たとえばGraphiteサーバにデータを引き渡したい場合は以下のような定義になります。この例では、Graphite用のサーバである192.168.33.101の2003番ポートにデータをTCPで送信しています。

{
  "handlers": {
    "graphite": {
      "type": "tcp",
      "socket": {
        "host": "192.168.33.101",
        "port": 2003
      },
      "mutator": "graphite"
    }
  }
}

ここでJSONの中にmutatorという記述がはじめて登場しました。mutatorは、データを送信する前にデータの加工を行う設定です。これを使うことで他のシステム合わせた形でデータを送信することができます。もちろん加工の必要がないのであれば特に記述は不要です。 mutatorの定義もJSONで行います。このgraphite用のmutatorの定義は以下のようになります。同じように/etc/sensu/conf.d/の中に適当な名前で配置します。

{
  "mutators": {
    "graphite": {
      "command": "ruby /etc/sensu/plugins/graphite.rb"
    }
  }
}

mutatorの中で行う実際の処理については適当なスクリプトを用意してcommandの箇所に指定します。こちらも使用言語は問いません。 今回は、https://raw2.github.com/sensu/sensu-community-plugins/master/mutators/graphite.rb を使っています。

まとめ

以上、Sensuについて簡単に紹介しました。 Sensuはかなり自由度が高いので、自分で監視システムを構築したい場合に最適です。 いろいろ試してみるとよいと思います。

アジャイルコーチングやトレーニングを提供しています

株式会社アトラクタでは、アジャイル開発に取り組むチーム向けのコーチングや、認定スクラムマスター研修などの各種トレーニングを提供しています。ぜひお気軽にご相談ください。

詳細はこちら