監視ツール × Redmineで実現する自動インシデント登録システム

# インシデント登録の重要性
システム運用管理をやっている皆さん、インシデント管理はどうやってますか？
Excel、商用ツールを使用、独自DBなど様々な手法があると思いますが、どの手法でもインシデントを登録するということは、共通の操作だと思います(当たり前ですが)。

システム管理であれ、サービスデスクであれ、インシデントを登録するのは、業務の品質をチェックし、改善に役立てるのに必須のことで、日々実践すべきことだと思います。

インシデント登録をより簡素化できれば、日常のインシデント登録業務を大幅に削減はできないでしょうか？
そのため、発生したインシデントは自動で登録し、対応していった場合を随時更新していくインシデント管理システムを構築する。ここでは、システム管理において、監視ツールから発生するアラートを"インシデント管理サーバ"へ送信し、インシデントの自動登録を実現する。

監視ツールはZabbixを使用した例を解説するが、他の監視ツールでも、メールの内容を合わせれば十分可能である。複数のシステムも、1つのインシデント登録システムに集約できる内容となっている。

# Redmineにインシデント登録用のプロジェクトを作成
Redmineのプロジェクトにインシデント管理用のプロジェクトを作成する(識別子：incident)。システムのプロジェクトにすることもできるが、発生したインシデントには、あらゆるタイプの人から検索できるようなビッグデータにしたいため(※)、インシデントを1つのプロジェクトに集約する。個別プロジェクトにインシデントを移動させたい場合(=ITIL的に問題管理に移行する場合)は、該当システムのプロジェクトにコピー＆関連付けを行い、インシデントのプロジェクトとしてはクローズするといいと思います。
※インシデント状況を担当外の方からも閲覧できるすることで、別システムにも同様の事象が起きた場合の参考にできるため。

以下はプロジェクトのサンプルです。

![6.png](https://qiita-image-store.s3.amazonaws.com/0/98996/21787ce3-3974-954f-a531-f99edc586abd.png)

インシデントプロジェクトのモジュールは、シンプルにチケットトラッキングのみとした。

## カスタムフィールド
カスタムフィールドの設定では、「システム名」「H/W」「OS」を作成します。なお、「システム名」は、カスタムクエリの条件とするため、「フィルタとして使用」のチェックを入れておいてください。

![１.png](https://qiita-image-store.s3.amazonaws.com/0/98996/d20f7092-4a2e-b5bd-803e-7d60888d57fb.png)

## カスタムクエリの作成
お好みではあるが、システム毎にカスタムクエリを作成するのをオススメで、担当してるシステムのチケットの抽出が楽である。一カ月毎やステータス毎にするのもいいだろう。
監視ツールから送信されてくるメールにシステム名を記載することを必須にしたので、「システム名にＸシステムを含む」のようなフィルタにしている。

![４.png](https://qiita-image-store.s3.amazonaws.com/0/98996/29cd7a0b-8396-ce2d-3d97-34cedc0494af.png)

## Postfixの設定
/etc/aliasesに以下を登録してください。
rdm-mailhandler.rbは、GitHub上に公開されておりますので、それをご活用ください。

https://github.com/redmine/redmine/blob/master/extra/mail_handler/rdm-mailhandler.rb

```
root: "| ${/path/to/redmine}/rdm-mailhandler.rb --url http://xxx.xxx.xxx.xxx --key xxxxxxxxxxxxx --project incident --allow-override all"
```
※記入後は、newaliasesで設定の反映も忘れずに。

Redmineサーバの設定は以上です。

# 監視ツール(Zabbix)側の設定
## アクションの設定
Zabbixでメール送信設定をします。メールの宛先はRedmineサーバとしてください。
メールの内容は以下とします。

```
名前：任意
デフォルトの件名：【{INVENTORY.TYPE}】 {HOST.NAME} {TRIGGER.NAME}
デフォルトのメッセージ：
[発生日時] {DATE}
[ホスト名] {HOST.NAME}　({HOST.IP})
[トリガー名] {TRIGGER.NAME}

[詳細内容]
{ITEM.VALUE1}

[概略コメント]
{TRIGGER.DESCRIPTION}

システム名: {INVENTORY.TYPE}
OS: {INVENTORY.OS}
H/W: {INVENTORY.HARDWARE}

リカバリメッセージ：チェックなし
```

![５.png](https://qiita-image-store.s3.amazonaws.com/0/98996/18de5f08-455b-ce75-35da-3e2ce482a660.png)

## グローバルマクロの設定
メール本文にグローバルマクロを入れてますので、ホストインベントリに以下を入力しておいてください。

「タイプ」：システム名
「名前」：サーバ名
「OS」：使用しているOS
「ハードウェア」：使用しているH/W

![２.png](https://qiita-image-store.s3.amazonaws.com/0/98996/dd9a6063-01f2-925e-3a92-e5ffac78eb29.png)

これで完成。

# テスト

それでは、テストをしてみます。何らかのアラートを監視サーバで発生させてください。
ここでは、messagesにエラーを出力させました。そうすると、Redmineサーバにメールが送信され、自動的にチケットが登録されているはずです。

![３.png](https://qiita-image-store.s3.amazonaws.com/0/98996/102cd262-6097-4dc0-f4fd-7853f748e3e9.png)

OS、H/Wの情報もインシデントとして登録されます。同じOSやH/Wを他システム使用していることは大いにあるので、他システムの担当者にもインシデント情報が共有できるメリットがあります。

また、インシデント画面は以下のようになっています。

![７.png](https://qiita-image-store.s3.amazonaws.com/0/98996/e6ce7581-c2ed-3e2d-90f5-1f4e75fdb85d.png)

先ほど作成したカスタムクエリを使うと、システム毎にフィルタができます。1か月単位で抽出し、月1回の定例会でインシデント状況の確認するなどに便利です。

![８.png](https://qiita-image-store.s3.amazonaws.com/0/98996/e7dfc3ee-6618-33d8-c596-6f180274251e.png)

●失敗例
失敗のパターンはいくつかあり、Redmineの公式サイトにも記載があるが、私の場合は、メール送信するFromのユーザのアカウントをRedmineに登録していなかった。

```
Jan 18 08:40:38 xxx.xxx.xxx.xxx postfix/local[15830]: 82791BF91B: to=<hogehoge@hogehoge>, orig_to=<hogehoge@hogehoge>, relay=local, delay=1.8, delays=0.4/0.01/0/1.4, dsn=5.7.0, status=bounced (permission denied. Command output: Request was denied by your Redmine server. Possible reasons: email is sent from an invalid email address or is missing some information. )
```


●成功例
```
Jan 18 08:47:38 xxx.xxx.xxx.xxx postfix/local[16064]: DDC01BF91B: to=<hogehoge@hogehoge>, orig_to=<hogehoge@hogehoge>, relay=local, delay=0.82, delays=0.29/0.01/0/0.53, dsn=2.0.0, status=sent (delivered to command:  /var/lib/redmine/extra/mail_handler/rdm-mailhandler.rb --url http://xxx.xxx.xxx.xxx--key xxxxxxxxxxxxxxxxx --project incident)
```

# 大量アラート発生時の制御
大量アラートが発生した際は、できるだけ、監視サーバ側でメールがたくさん飛ばないように制御してください。大量アラートを全てRedmineサーバに飛ばすと、サーバの負荷が増大します。大量アラートの場合は、それ自体を1つのインシデントとして登録し、必要な内容を手動で書き込んでください。こういった場合にのみ、人手が登場します(※)。
※全てインシデント登録しても構いませんが、1つの原因に対して大量にアラートが発生しているのであれば、大量アラートは1インシデントとして、扱うべきだと考えます。

Zabbixの場合は、メールスクリプトを作成し、スクリプトが多重起動しないようにします。これは別の機会で紹介します。

今回は、監視サーバ側で制御ができない場合、Redmineサーバ側で自動登録を抑えるスクリプトを紹介します。ただし、たまたま同時に複数のシステムで自動登録メールを受けた場合、登録が漏れる可能性があります。登録できなかった場合は、その旨、ログに記録します(テストしたところ、ログに記録するだけなら、Redmineに大量にチケットを登録するより、システム負荷は低いです。メールを飛ばすのもありかもしれませんが、ログ出力とどちらが負荷が高いかは要確認です)。

以下のスクリプトを作成しましたので、rdm-mailhandler.rbの最初と最後に入れましょう。スクリプト内に日本語で解説も入れました。

```overlap-privension.rb
# スクリプトの最初に
require "date"

x = File.exist?("/tmp/lockfile")
d = DateTime.now

# lockfileが存在する場合は、前のスクリプト中が起動中のため、
# 重複起動させないために、exitします。
if x == true then
  log = File.open("/root/Tools/log/redmine_ticket.log","a")
  log.print d
  log.puts " The lockfile exists. So this script finish."
  log.close
  exit!
end

# 空ファイル作成
File.open("/tmp/lockfile","w").close()

# スクリプトの最後に
File.unlink("/tmp/lockfile")
```

GitHub上にもスクリプトを置きました。
https://github.com/domonjo01/overlap-prevension

Redmineは対応する人間が必ず確認をするので(監視のアラートを止めたオペレータやアラート連絡を受けた担当者)、自分が連絡を受けたインシンデントが登録されていない場合は、(本人が対応をサボらなければ)ほぼ間違いなく気づきます。

アラートを鳴らさず、自動メール送信＆インシデント登録のみの事象がある場合は、漏れる可能性があるので、記録されたログを、
①監視ツールにて監視(ただし、30分置きなど間隔をあげて)
②目視にて定期的に確認(1日1回ぐらい？)
③cronなどで30分おきにチェックして、ひっかかったらメール送信
するなどして、登録漏れがないように確認しましょう。万が一、登録漏れがあった場合は、maillogを確認して、どこのシステムからのインシデントとかを確認してください。