Sensuトラブルシュート


監視システムは登場人物が多くなるので、うまくいかないときにどこに問題があるのかパッと見わかりづらい.
どういう連携で監視システムが動いているのか全体構成を把握することと、サービス単体でチェックする方法、ログの見方などをおさえることが大事と思う.
curlでsensu-apiたたく、jqでjsonのsyntaxチェックするなどのテクニックも重要.

■サービス ポート

※自分の環境の情報です

|service|default port|
|:-------:|:-------:|
|sensu-client|3030|
|sensu-api|4567|
|uchiwa|3000|
|rabbitmq-server|5672|
|redis-server|6379|

■ログ

※自分の環境の情報です

|service|log path|
|:-------:|:-------|
|sensu-server|/var/log/sensu/sensu-server.log|
|sensu-client|/var/log/sensu/sensu-client.log|
|sensu-api|/var/log/sensu/sensu-api.log|
|uchiwa|/var/log/uchiwa.{log,err}|
|rabbitmq|/var/log/rabbitmq|

■sensu checkステータス

|status|description|
|:-------:|:-------|
|0|OK|
|1|WARNING|
|2|CRITICAL|
|3以上|UNKNOWN or CUSTOM|

■jq install

http://stedolan.github.io/jq/download/

```bash
## 
## RHEL系にインストールする
## 
cd /usr/local/src
wget "http://stedolan.github.io/jq/download/linux64/jq"
chmod +x jq

echo '{"test": "test"}' | ./jq .
  # json parse test
mv -i jq  /usr/bin/
```

■sensu server <=> sensu-clientの連携

sensu-clientとsensu-serverの監視業務の概要をつかんでおくといいと思う.
http://qiita.com/metheglin/items/edd332d577b6e167ac67

## sensu-server,sensu-client <=> rabbitmq通信に失敗する

rabbitmqと通信できないとsensuは稼働しない.
rabbitmqと疎通できないと以下のようなログが出る.

```json:/var/log/sensu/sensu-server.log
{"timestamp":"2015-04-23T00:27:23.907604+0900","level":"error","message":"[amqp] Detected TCP connection failure"}
```

```bash
@sensu-server
netstat -ln | grep 5672
  # rabbitmqプロセスが起動してport 5672をLISTENしているか確認する
```

rabbitmqデーモンが起動しているのに通信に失敗する場合、
* `/etc/sensu/config.json`に記述のrabbitmq設定が正しいか確認
* rabbitmqとsensu-serverが別サーバなら、awsのセキュリティグループ, iptables, firewallなどを疑う
* rabbitmq ACL設定が正しいか確認
	* https://sensuapp.org/docs/0.19/install-rabbitmq
	* Configure RabbitMQ

|protocol|daemon|port|description|
|:----:|:----:|:----:|:----:|
|tcp|rabbitmq|5672|開放必要(sensu-clientに向けて)|
|udp|rabbitmq|5672|開放不要っぽい(tcpdumpで確認した)|

## uchiwa/dashboardでclientが表示されない

1. sensu-apiがclientを認識しているか確認する
http://(sensu-apiのホスト名/IP):4567/clients

sensu-client起動できてはいるのに、sensu-apiでclientがとれない場合は、rabbitmqとの疎通に失敗している可能性が高い.
一つ前の手順にしたがって、rabbitmqのport開放やACLを確認する.
一回rabbitmqのvhost消してから作りなおしてもよさそう.

## uchiwa/dashboardでclientの情報が更新されない

sensu-clientのclient.json変更しただけではsensu-serverのredisの値が更新されない.
sensu-client再起動する必要がある.

```bash
# @sensu-client
sudo service sensu-client restart
```

## sensu clientがメッセージを受信しているか単体チェック

/dev/tcpへのリダイレクトかncコマンドのいずれかでsensu-clientへ直接メッセージを届けることができる.

参考):
http://sensuapp.org/docs/0.17/clients#what-are-sensu-clients

```bash
# @sensu-client

echo '{"name": "sensu-client-check", "output": "sensu-client-check", "status": 1}' > /dev/tcp/localhost/3030
echo '{"name": "sensu-client-check", "output": "sensu-client-check", "status": 1}' | nc localhost 3030

tail -F  /var/log/sensu/sensu-client.log
  # ログが出ることを確認
```

## 一度登録したsensu checkを削除する

redisにログインしてflushallする.
※sensu以外のデータストアとしてredisを使っていないか注意しておこなってください
※もっと正しいやりかたあると思いますが、知っているかたいたら教えてください！

## uchiwa/dashboardでsensu checkが認識されない

uchiwaやdashboardはsensu-apiから情報を取得しているので、sensu-apiがsensu checkの追加を認識できていない可能性がある.
sensu-apiはredisから情報をとってきているので、redisに追加されていない可能性がある.

1. sensu-apiがsensu checkを認識しているか確認する
http://(sensu-apiのホスト名/IP):4567/checks

1-2. sensu-serverを再起動する

```bash
# @sensu-server
sudo service sensu-server restart
# @sensu-api
sudo service sensu-api restart
```

1-3. 認識されないsensu checkのjsonにsyntax errorなどがないか確認する


```bash
@sensu-server
cat vmstat_metrics.json  | jq '.'
parse error: Expected separator between values at line 7, column 16
```

`/var/log/sensu/sensu-server.log`をよく見ると、sensu-server起動時にエラーメッセージが出ている.
sensu check jsonファイル名でgrepして、message枠にエラーが出ていないか確認する.

```json:/var/log/sensu/sensu-server.log
{"timestamp":"2015-04-19T16:41:27.241425+0900","level":"warn","message":"config file must be valid json","file":"/etc/sensu/conf.d/vmstat_metrics.json","error":"parse error: after key and value, inside map, I expect ',' or '}'\n          eme stats.:::name:::\"       \"interval\": 60,       \"subscribe\n                     (right here) ------^\n"}
```
json parse errorになっているときの`sensu-server.log`

## sensu checkプロセス監視が想定外の動き

こんな人はあまりいないと思うけど、滑稽なはまりかたをしたので共有.
sensu checkのプロセス監視でcronデーモンの監視をしかけた.
試しにcronデーモンを落としてアラートが上がるかチェックしていたが、アラートが来ない...
監視対象サーバにログインしてみて、checkコマンドを直接打つと、あるときはCRITICALになり、あるときはOKになり、全く予期できない動きをした.

原因は、デバッグのために別窓で実行していた`tail -F /var/log/sensu/sensu-client.log | grep cron`コマンドだったw `tail -F`は常駐するのでプロセス一覧出したときに`grep cron`のところにcron文字列がヒットするためcronプロセスが生きていると判断されてしまう.

プロセス名を含むバッチを動かすときも問題になるかも.

## handlerが機能していない気がする

1. handlerの文法確認する

https://sensuapp.org/docs/latest/checks
よくある問題だけど、`handlers`複数形の場合は配列形式で複数のハンドラを指定できるけど、`handler`単数形の場合は文字列形式で一つだけ指定できる.

1-2. 対応するhandlerが存在するか確認する

```
grep -r "graphite" /etc/sensu/conf.d/
  # "graphite"という名前になっているhandlerのjson設定があるか探す
  # 以下の形式のjsonが存在して、sensuユーザにread権限あれば問題なし.
  # {"handlers", {
  #   "graphite": {...
  # 
```
1-3. handlerを配列形式で複数指定した場合、一つでも無効なhandlerがあるとすべてのhandlerが認識されない

`handlers: ["debug", "graphite"]`
と書いていたが、debug handlerが存在しなかったためか、graphite handlerまでが無効となってしまっている.
debugを外すとうまくいって、以下のように`sensu-server.log`に出るようになる.

■修正前

`handlers: ["debug", "graphite"]`と設定したがdebug handlerが存在しない.

```json:sensu-server.log
{"timestamp":"2015-04-22T14:25:53.997086+0900","level":"warn","message":"loading config file","file":"/etc/sensu/conf.d/cpu_metrics.json"}
```
↑handlersがjsonに出てこないため設定がおかしい.

■修正後

`handlers: ["graphite"]`

```json:sensu-server.log
{"timestamp":"2015-04-22T14:25:53.997096+0900","level":"warn","message":"config file applied changes","file":"/etc/sensu/conf.d/cpu_metrics.json","changes":{"checks":{"cpu_metrics":[null,{"type":"metric","command":"/etc/sensu/plugins/cpu-metrics.rb","subscribers":["all"],"interval":10,"handlers":["graphite"]}]}}}
```
↑handlersが認識されていることがわかる

## 2回目以降のhandlerが実行されない？

1分間隔で死活監視していると、プロセス落としたときに1分間隔でアラートが来てかなりうるさい.
これを防ぐために、障害発生時のhandlerはいい感じに間隔をあけて実行してくれる機能がついている.

https://github.com/sensu-plugins/sensu-plugin/blob/master/lib/sensu-handler.rb

|      |default|memo|
|:----:|:-----:|:----:|
|refresh|1800|どの間隔でhandlerを実行するか調整できる|
|inteval|60|sensu check jsonに記述したcheck実行間隔|

イベント継続回数が`refresh / interval`で割り切れる数のときのみhandlerが実行される.

sensu handlerのテストをしているときはこの機能があると、長い時間待たなければいけないので逆に邪魔になる.
uchiwaでeventを選択して、resolvを押してイベント解決してしまえばイベント継続回数が0にリセットされるので、再度handlerを実行できる.
または、Events APIのresolveを実行してもよい.
https://sensuapp.org/docs/latest/api-events

## sensu eventsのresolveができない

1. uchiwaが機能しているか確認

uchiwaでresolve操作したときにresolve操作のログが出ることを確認

```
{"timestamp":"2015-04-23T12:23:23.585168+0900","level":"info","message":"POST /resolve","remote_address":"127.0.0.1","user_agent":"Go 1.1 package http","request_method":"POST","request_uri":"/resolve","request_body":"{\"check\":\"cron\",\"client\":\"stg-wsaneys201\"}\n\n"}
```

2. sensu-apiが機能しているか確認

sensu-apiでresolve実行するときのログ

```sensu-api.log
{"timestamp":"2015-04-23T14:10:50.937077+0900","level":"info","message":"publishing check result","payload":{"client":"stg-wsaneys201","check":{"command":"/etc/sensu/plugins/check-procs.rb -p cron","subscribers":["production"],"interval":60,"name":"cron","issued":1429765850,"executed":1429765850,"duration":0.051,"output":"Resolving on request of the API","status":0,"total_state_change":0,"force_resolve":true}}}
```

sensuの途中のバージョンから微妙にresolve apiのインタフェースかわってるので、最新のドキュメント（またはそのバージョンのドキュメント）を確認する.
https://sensuapp.org/docs/latest/api-events

resolve apiをcurlで確認する例.
`--dump-header -`をつけてレスポンスヘッダを確認したほうがいい.

```bash
curl --dump-header - -X POST -d '{"check":"cron","client":"sensu-client"}' http://(sensu-apiのホスト):4567/resolve

  # eventが存在しないとき
  # HTTP/1.1 404 Not Found

  # eventが存在するとき
  # HTTP/1.1 202 Accepted
  # {"issued":1433564961}
```

3. rabbitmqとの疎通を確認

sensu-apiも異常なさそうだったら、rabbitmqとの疎通を確認する.
resolveすると、sensu-apiがredisを直接操作すると思っていたが、rabbitmqにメッセージを送り、それを受信したsensu-serverがイベント解決処理をおこなう.
一番上記載のrabbitmq通信に失敗するケースを調査する.


# Environment

```
sensu version 0.17
```

```
$ cat /etc/issue
Amazon Linux AMI release 2015.03
Kernel \r on an \m

$ uname -a
Linux *** 3.14.35-28.38.amzn1.x86_64 #1 SMP Wed Mar 11 22:50:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
```