次世代監視ツール Sensu リファレンス

  • 422
    Like
  • 0
    Comment
More than 1 year has passed since last update.

バージョン 0.9 くらいのときの公式ドキュメントのざっくり訳+個人のメモ
情報が古い+理解が間違ってるとこあるかもなので注意して欲しいけど、需要がありそうなので出してみる

Overview

Sensu は監視ツールの一つ。Sensu はよく "monitoring router" と記述される。もっと平たく言うと、Sensu は多くのノードに対して "check" スクリプトを実行し、1 つまたは複数の Sensu サーバーにて "handler" スクリプトを実行する。

例えば、Apaache の死活チェックをするとしよう。チェックスクリプトにより死活だけでなくメトリクスも収集する。そしてそのアウトプットは 1 つまたは複数の Handlers にルーティングされる。Handlers はチェック結果によって何をするのか定義するものだ。Handlers は今のところ E メール、IRC、Twitter にアラートを送ったり、Graphite, Librato などにメトリクスを渡すことができる。またチェックスクリプトやハンドラースクリプトはどんな言語で書いてもよい。

# router のイメージ
# 色々な監視結果を sensu が適切なハンドラーにルーティング
checks -> sensu -> handlers

作者 Sean Porter によるイントロダクション

Key details

  • Ruby (EventMachine, Sinatra, AMQP), RabbitMQ, Redis
  • travis-ci を通した CI と、高いテストカバレッジ率
  • メッセージ志向アーキテクチャ。メッセージは JSON オブジェクト
  • 既存の Nagios プラグインを再利用できる
  • プラグイン、ハンドラー、チェックスクリプトはどんな言語で書いてもよい
  • メトリクスを送るバックエンドは様々なものをサポート (Graphite, Librato, etc)
  • Chef や Puppet のようなモダンな CM ツールを考慮した設計
  • クラウド環境のための設計
  • 1200 行程度で軽い
  • "オムニバス"(多くの項目を扱う)スタイルパッケージ

Event Data とは

Event Data は

  • Client info
  • Check info
  • いくつかの metadata

から構成される JSON データ。言語の縛りがなく人間にも読みやすい

Example

{
  "client":{
    "name": "host01",
    "address": "10.2.1.11"
    "subscriptions": [
      "all",
      "frontend",
      "proxy"
    ],
    "timestamp": 1326390159
  },
  "check":{
    "name": "frontend_http_check",
    "issued": 1326390169,
    "output": "HTTP CRITICAL: HTTP/1.1 503 Service Temporarily Unavaliable",
    "status": 2,
    "command": "check_http -I 127.0.0.1 -u http://web.example.com/healthcheck.html -R 'pageok'",
    "subscribers":[
      "frontend"
    ],
    "interval": 60,
    "handler": "campfire",
    "history": [
      "0",
      "2"
    ],
    "flapping": false
  },
  "occurrences": 1,
  "action": "create"
}

コンポーネント

Sensu Server

Sensu server は sensu client のチェック開始のトリガーとなります。そしてチェック結果の出力を受け取ると handlers にフィードします。(バージョン 0.9.2 では client は server が知らないチェックも行います)

Sensu server は persistent データの保持に Redis インスタンスを使います。また自分自身と sensu client のデータのやりとりにおいて RabbitMQ もヘビーに利用します。

Sensu client

Sensu client は監視したいサーバー上で実行する。Sensu client はチェックスクリプト (check_http, check_load etc) を実行し RabbitMQ を通して Sensu server に結果を返します。

Sensu API

Sensu server (Redis) 上の色々なデータへアクセスするための REST API 。普通は Sensu Server または Redis インスタンスと同じサーバーで実行します。

Sensu dashboard

現在の Sensu インフラとアラートなどのアクションの状態を表示する Web ダッシュボード

インストール

一般的には Sensu 環境には 2 種類のノードが必要になる。Sensu-Server にも Sensu-Client をインストールすることに注意

  • Sensu Server
    • RabbitMQ
    • Redis
    • Sensu-Server / Sensu-Client / Sensu-API / Sensu-Dashboard
  • Sensu Client
    • Sensu-Client

Chef (または Puppet ) を使っているなら既に recipe が用意されている。

Sensu Server の構築

Install Guide

Chef で構築する場合は、sensu / sensu-chef - Github を利用する。

sensu-chef をそのまま使うのではなくて、sensu-chef の recipe を include した wrapper cookbook を別に用意する。
Sensu Server の recipe。default handler がないと server が起動しないので適当に定義しておく

include_recipe "sensu"
include_recipe "sensu::rabbitmq"
include_recipe "sensu::redis"

sensu_handler "default" do
  type "pipe"
  command "ls"
end

include_recipe "sensu::api_service"
include_recipe "sensu::client_service"
include_recipe "sensu::dashboard_service"
include_recipe "sensu::server_service"

自分は chef-monitor という作者が作ってる wrapper cookbook のさらに wrapper cookbook を作って使っている

Chef なしで構築

Amazon Linux 上に sensu-server を構築する(1) 参考

起動方法

Sensu Server の起動

Sensu サービスを enable にして、

CentOS/REHL

sudo chkconfig sensu-server on
sudo chkconfig sensu-api on
sudo chkconfig sensu-client on
sudo chkconfig sensu-dashboard on

Debian/Ubuntu

update-rc.d sensu-server defaults
update-rc.d sensu-api defaults
update-rc.d sensu-clent defaults
update-rc.d sensu-dashboard defaults

起動

sudo /etc/init.d/sensu-server start
sudo /etc/init.d/sensu-api start
sudo /etc/init.d/sensu-client start
sudo /etc/init.d/sensu-dashboard start

Sensu Server WebUI は 8080 番ポート

設定

Configuration

設定ファイル

主な設定ファイルは

/etc/sensu/config.json

また、

/etc/sensu/conf.d/

以下に置いたファイルも設定ファイルとして読み込まれる。

設定項目は

  • Client 情報
  • Handler 定義
  • Mutator 定義
  • Checks 定義

Sensu Server に必須の設定

Sensu Server は default handler が必ず必要になる。/etc/sensu/config.json/etc/sensu/conf.d/default_handler.json

"handlers": {
  "default": {
    "type": "pipe",
    "command": "PATH/default"
  }
}

を追加する。(default handler の中身は適宜変える)

Client Info

Client Info とは

  • 各 Client はある定義、 Client Info を必要とする。
  • Client info は監視サービスが起動された際に publish される
    • これがどのように Sensu に client が登録されるかの仕組みとなる

必須 Client Info

Client info にはいくつかの指定必須 key-value がある。

  • name - クライアント名
  • address - クライアントの IP アドレス
  • subscriptions - Roles のリストまたは Role 同等のもの
    • 監視内容はこれに基づく

Example

{
  "client": {
    "name": "web00",
    "address": "127.0.0.1",
    "subscriptions": [
      "production",
      "webserver",
      "mysql"
    ]
  }
}

カスタム Client Info

Client info にはカスタム key-value を追加できる

{
  "client": {
    "name": "web00",
    "address": "127.0.0.1",
    "subscriptions": [
      "production",
      "webserver",
      "mysql"
    ],
    "mysql": {
      "host": "localhost",
      "port": 3306,
      "user": "foo",
      "password": "bar"
    }
  }
}

Handlers

Handlers とは

Event Data に基づくハンドリング。

  • アラートメールの送信
  • PagerDuty(クラウド通知・警報サービス) のインシデントの作成
  • Graphite へのメトリクスの保存

といったことを行う。

/etc/sensu/config.json/etc/sensu/conf.d/default_handler.json といったファイルに記述する

Handlers のタイプ

Pipe

Pipe は STDIN を通して Event Data を渡し、あるコマンドやスクリプトを実行する

Example

Handler スクリプト(/etc/sensu/handlers/file.rb)

#!/usr/bin/env ruby

require "rubygems"
require "json"

# Read event data
event = JSON.parse(STDIN.read, :symbolize_names => true)
# Write the event data to a file
file_name = "/tmp/sensu_#{event[:client][:name]}_#{event[:check][:name]}"
File.open(file_name, "w") do |file|
  file.write(JSON.pretty_generate(event))
end

Handler 定義

{
  "handlers": {
    "file": {
      "type": "pipe",
      "command" : "/etc/sensu/handlers/file.rb"
    }
  }
}

コマンドを実行するのではなくメールを送信するように修正してみる

{
  "handlers": {
    "mail": {
      "type": "pipe",
      "command" : "mail -s 'sensu event' email@address.com"
    }
  }
}

TCP

TCP handlers は TCP socket に Event data を書き込む

(この具体的な利用例として Sean Porter が言ってたのが、例えば application のあるポートに監視のステータスを送ることで、メンテナンスモードにサーバーが自律的に変わるとかができるようになるとか。色々広がりそう。)

Example

localhost:4242 の TCP socket へ event data を書き込む

{
  "handlers": {
    "tcp_socket": {
      "type": "tcp",
      "socket": {
        "host": "127.0.0.1",
        "port": 4242
      }
    }
  }
}

UDP

UDP Handlers は UDP socket に Event data を書き込む

Example

localhost:2424 の UDP socket へ event data を書き込む

{
  "handlers": {
    "udp_socket": {
      "type": "udp",
      "socket": {
        "host": "127.0.0.1",
        "port": 2424
      }
    }
  }
}

AMQP

AMQP handlers は AMQP exchange へ event data を publishing する

Example

{
  "handlers": {
    "amqp_exchange": {
      "type": "amqp",
      "exchange": {
        "type": "topic",
        "name": "events"
      }
    }
  }
}

Ruby AMQP ライブラリについてはここを

Set

Handlers Sets は handler のグルーピングを行う。

  • 1 つの event data を複数の handlers に渡す
  • または単純にある handler の alias を作る

Example

{
  "handlers": {
    "default": {
      "type": "set",
      "handlers": [
        "file",
        "tcp_socket"
      ]
    }
  }
}

Handler 設定

Example

my_handler1 では、settings["handlers"]["my_handler1"]["custom_setting"] という設定値を利用している。おそらく /etc/sensu/handlers/file.rb にてその値を使う。

my_handler2 では、トップレベルのネームスペースにある settings["my_handler2"]["another_custome_setting"] という設定値を利用している。おそらく /etc/sensu/handlers/file.rb にてその値を使う。

handlers 定義(設定)

{
  "handlers": {
    "my_handler1": {
      "type": "pipe",
      "command": "/etc/sensu/handlers/file.rb",
      "custom_setting": "custom_val"
    },
    "my_handler2": {
      "type": "pipe",
      "command": "/etc/sensu/handlers/file.rb",
      "custom_setting": "custom_val"
    }
  },
  "my_handler2": {
    "conventional_configuration": "true",
    "another_custome_setting": "some_custom_value"
  }
}

深刻度のフィルタリング

Handlers はある深刻度のときだけ実行する、といった事が可能だ。

Example

PagerDuty handler は Event が check の結果が 2 である CRITICAL または OK の時だけ実行する定義(設定)

{
  "handlers": {
    "pagerduty": {
      "type": "pipe",
      "command": "/etc/sensu/handlers/pagerduty.rb",
      "severities": [
        "critical",
        "ok"
      ]
    }
  }
}

Mutators

Mutators とは

特定の handler に渡す前に event data を mutate(= 変異させる) もの。

cat event.json | mutator.rb | handler.rb

Mutators の例

event data (JSON データ) に、:mutated => true, :its_a_tumor => true という key-value をマージさせる。(mutate 済みというタグを付ける例)

Event mutator (/etc/sensu/mutators/tag.rb)

#!/usr/bin/env ruby

require "rubygems"
require "json"

# Read event data
event = JSON.parse(STDIN.read, :symbolize_names => true)
# Add a 'tag' to prove it has been mutated
event.merge!(:mutated => true, :its_a_tumor => true)
# Output mutated event data to STDOUT
puts event.to_json

Mutator 定義 (設定)

{
  "mutators": {
    "tag": {
      "command": "/etc/sensu/mutators/tag.rb"
    }
  }
}

特定の Handler に mutator を使う

{
  "handlers": {
    "file": {
      "type": "pipe",
      "mutator": "tag",
      "command": "/etc/sensu/handlers/file.rb"
    }
  }
}

ビルトイン mutators

mutator 定義をしなくても利用できるビルトイン mutators がいくつかある。

  • Only check output

Checks

Checks とは

  • Checks とはサービス状態をモニタリング・メトリクスの収集する Check スクリプトのこと。
  • Checks は Sensu-Client によって実行される。
    • 実行タイミングは Sensu-Server が握っている(設定ファイルに記述)
    • Sensu-Server が定期的に Check 定義に紐づく Subscriptions を持つ client へ publish する(Check スクリプト実行の指示)
  • Checks はコマンドまたはスクリプト
    • STDOUT / ERR に出力する
    • 終了コードを持つ
      • 0 : OK
      • 1 : WARNING
      • 2 : CRITICAL
      • 3 : UNKNOWN or CUSTOM

この仕様は Nagios と互換性があるので、Nagios plugins をそのまま利用できる。

Checks Example

Check plugin (/etc/sensu/plugins/check-chef-client.rb)

procs = `ps aux`
running = false
procs.each_line do |proc|
  running = true if proc.include?('chef-client')
end
if running
  puts 'OK - Chef client daemon is runnig'
  exit 0
end
else
  puts 'WARNING - Chef client daemon is NOT running'
  exit 1
end

Check 定義 (設定)

{
  "checks": {
    "chef_client": {
      "command": "check-chef-client.rb"
      "subscribers": [
        "production"
      ],
      "interval": 60
    }
  }
}

定義内容

  • chef_client: 一意な Check 名
  • command: 実行する Check スクリプト
  • subscribers: どの subscriptions で Check を実行するか
  • interval: Check スクリプトを実行する間隔(秒)

どのように Check 結果が Event を生成するか

  • デフォルトでは Check スクリプトの終了コードが 0 以外のとき、event が生成される

Handler ルーティング

  • handler の指定がなければデフォルトで default handler へルーティングされる
  • handler は "handler": "foo" のように指定する
    • 複数ある場合は、"handlers": ["foo", "bar"] とする

Example

Check 定義(設定)

{
  "checks": {
    "chef_client": {
      "command": "check-chef-client.rb",
      "subscribers": [
        "production"
      ],
      "interval": 60,
      "handlers": [
        "pagerduty",
        "irc"
      ]
    }
  }
}

メトリクス Checks

Sensu の Checks における決まりとして構造データの出力先を STDOUT にする、というのがある。なのでメトリクス収集エージェントも利用できる。

  • 終了コード 0 にて event を発生させるため、"type": "metric" を checks 定義に追加する

Example

Check 定義 (/etc/sensu/plugins/cpu-usage-metrics.sh)

#!/bin/bash

SCHEME=`hostname`

usage()
{
  cat <<EOF
usage: $0 options

This plugin produces CPU usage (%) using /proc/stat

OPTIONS:
   -h      Show this message
   -s      Metric naming scheme, text to prepend to cpu.usage
EOF
}

while getopts "hs:" OPTION
  do
    case $OPTION in
      h)
        usage
        exit 1
        ;;
      s)
        SCHEME="$OPTARG"
        ;;
      ?)
        usage
        exit 1
        ;;
    esac
done

get_idle_total()
{
  CPU=(`cat /proc/stat | grep '^cpu '`)
  unset CPU[0]
  IDLE=${CPU[4]}
  TOTAL=0
  for VALUE in "${CPU[@]}"; do
    let "TOTAL=$TOTAL+$VALUE"
  done
}

get_idle_total
PREV_TOTAL="$TOTAL"
PREV_IDLE="$IDLE"

sleep 1

get_idle_total

let "DIFF_IDLE=$IDLE-$PREV_IDLE"
let "DIFF_TOTAL=$TOTAL-$PREV_TOTAL"
let "DIFF_USAGE=(1000*($DIFF_TOTAL-$DIFF_IDLE)/$DIFF_TOTAL+5)/10"

echo "$SCHEME.cpu.usage $DIFF_USAGE `date +%s`"

check スクリプトはこんな出力をする

foo.cpu.usage 4 1350486269

Check 定義(設定)

{
  "checks": {
    "cpu_usage_metrics": {
      "type": "metric",
      "command": "cpu-usage-metrics.sh"
      "subscribers": [
        "production"
      ],
      "interval": 10
    }
  }
}

Standalone Checks

Standalone Checks は Sensu-Client 自身によってスケジューリングされる Check 。

  • 定義された client ではどの client でもスケジューリングされ実行される
    • つまり subscriptions と無関係に実行されるということ
  • "standalone": true を Check 定義に追加し、"subscribers" を取り除く

Examples

Check 定義(設定)

{
  "checks": {
    "cpu_usage_metrics": {
      "type": "metric",
      "command": "cpu-usage-metrics.sh",
      "standalone": true
      "interval": 10
    }
  }
}

Check コマンドへ引数を渡す

client 情報のカスタム key-value を利用する

Example
カスタム key-value mysql.usermysql.password を利用する

Check 定義(設定)

{
  "checks": {
    "chef_client": {
      "command": "check-mysql-replication.rb --user :::mysql.user::: --password :::mysql.password:::",
      "subscribers": [
        "mysql"
      ],
      "interval": 60
    }
  }
}

カスタム Check 定義 key-value

Check 定義にもカスタム key-value を追加することができる。これにより、handler をよりクリエイティブにできる。

よくやるのは、"occurrences" という、「何度発生したら handler が動くようにするかの最低回数」を追加する

Example

Check 定義(設定)

{
  "checks": {
    "chef_client": {
      "command": "check-chef-client.rb",
      "subscribers": [
        "production"
      ],
      "interval": 60,
      "occurrences": 2
    }
  }
}

Flap 検知

Check の結果が "頻繁に" 変化しすぎるとき(監視設定が悪かったりネットワークの問題だったり)、"flapping": true を Event Data に追加することができる。

flapping マークが着いた Event は flapping が解消するまでマークは消えない。

Example

Check 定義(設定)

{
  "checks": {
    "chef_client": {
      "command": "check-chef-client.rb",
      "subscribers": [
        "production"
      ],
      "interval": 60,
      "low_flap_threshold": "5",
      "high_flap_threshold": "25"
    }
  }
}

Extensions

大量のトラフィックに対して handling, mutating を行うときに有効

コミュニティプラグイン

sensu-community-plugins

コミュニティにて開発されている handlers / plugins (check script) が置いてある。

Tips

Sensu Admin

モバイル対応済みの WebUI

Uchiwa

uchiwa
Node.js ベースのリアルタイム WebUI 。データベースいらずで気軽。


デバッグ

ログ一覧

/var/log/sensu/
  sensu-api.log
  sensu-client.log
  sensu-dashboard.log
  sensu-server.log

〜が立ち上がらない

  1. Redis, RabbitMQ
  2. Sensu-Server
  3. Sensu-API
  4. Sensh-Dashboard

の順で起動するので、先に起動しておくべきものが起動してなかったり、
起動してるけど接続出来てなかったり。

/etc/sensu/config.json の rabbitmq や redis への接続先や iptables など

AWS だと、Redis, RabbitMQ, API のポートを空けておかないといけない

monitor cookbook メモ

  • checks
    • plugin は cookbook file
    • config は data bag (sensu_checks)
  • hanlers
    • script は cookbook file
    • config は recipe (Ex.) _graphite_handler.rb
    • set config は attributes (Ex.) metrics set を作りたい時は sensu.handlers.metrics = ["a", "b"]
  • chef-monitor の _graphite_handler.rb の bug

関連リンク / 参照