English

お問い合わせ

BLOG

Zabbix 3.2以降の新機能解説(Zabbix 4.0を見据えて) その16 - 「障害(Problem)」の導入

こんにちは。MIRACLE ZBX のサポートをやっている花島タケシです。 いよいよ、Zabbix 4.0 がリリースされました。 Zabbix 4.0.0 では新たに「障害 (Problem)」が導入されましたが、バースト時に「障害」のページの表示がとても遅くなるケースがありました。 どうやら、あるトリガーを無効にしたときに発生するようです。 今回は、この件について解説します。

復旧しないトリガーを作るな!

Zabbix 4.0.0 では、障害 (Problem) が導入されました。従来はトリガー判定によりイベントが生成されるだけでしたが、4.0.0 からはイベントに付随するデータとして障害が導入されています。

ちょっと訳があってログをバーストするテストを行っていたのですが、テストを続けていくとなにやら、「監視データ」->「障害」のページの表示がとても遅くなり、さらに進めていくと全く表示がされなくなりました。

トップのダッシュボードも障害に関するウィジェットの表示ができなくなりました。

調査をすると、どうもあるトリガーを無効にしたときに、それが起点となる障害 ( イベントかもしれませんが ) が大量にあるときに現象が発生します。

結論としては、復旧しないトリガーは作るべきではないということになりますが、今回はこの件について解説します。

ハウスキーパーで削除されないデータ

ということで、データの保存期間を短縮した後に強引に ( 正規の方法ですよ ) ハウスキーピングを行いましたが、なんか変です。

どうも、データが削除された形跡がありません。

関連するハウスキーピングのコードは下記となります。
src/zabbix_server/housekeeper/housekeeper.c

1080 zbx_setproctitle("%s [removing old problems]", get_process_type_string(process_type));
1081 d_problems = housekeeping_problems(now);
1082
1083 zbx_setproctitle("%s [removing old events]", get_process_type_string(process_type));
1084 d_events = housekeeping_events(now);

995 static int housekeeping_problems(int now)
996
...
1003 rc = DBexecute("delete from problem where r_clock<>0 and r_clock<%d", now - SEC_PER_DAY);

955 static int housekeeping_events(int now)
956 {
957 #define ZBX_HK_EVENT_RULE " and not exists (select null from problem where events.eventid=problem.eventid)" \
958 " and not exists (select null from problem where events.eventid=problem.r_eventid)"
959
960 static zbx_hk_rule_t rules[] = {
961 {"events", "eventid", "events.source=" ZBX_STR(EVENT_SOURCE_TRIGGERS)
962 " and events.object=" ZBX_STR(EVENT_OBJECT_TRIGGER)
963 ZBX_HK_EVENT_RULE, 0, &cfg.hk.events_trigger},
...
988 for (rule = rules; NULL != rule->table; rule++)
989 deleted += housekeeping_process_rule(now, rule);

ハウスキーピング処理において、events テーブルより先に problem テーブルの清掃を行うようになっています (ll.1080-1084)。
problem テーブルの処理 (housekeeping_problems) では、r_clock カラムが 0 でないデータの削除を行っています。

そして、events テーブルの処理では、新しく付与された条件 (l.957 の ZBX_HK_EVENT_RULE) により、「problem テーブルに関連するデータが残っているデータは削除されない」ようになっています。

ところで、何で events テーブルなのに problems テーブルではないのでしょう ?
housekeeping_problems() であるのに。

だれが problem テーブルの r_clock を更新するの ?

そもそも r_clock カラムは何のためにあるのでしょう ?

r_clock に関する処理は一ヶ所しかありません。
src/zabbix_server/events.c

1745 static int flush_events(void)
1746 {
...
1752 ret = save_events();
1753 save_problems();
1754 save_event_recovery();

433 static void save_event_recovery(void)
434 {
...
451 while (NULL != (recovery = (zbx_event_recovery_t *)zbx_hashset_iter_next(&iter)))
452 {
453 r_event = &events[recovery->r_event_index];
454
455 zbx_db_insert_add_values(&db_insert, recovery->eventid, r_event->eventid,
456 recovery->correlationid, recovery->c_eventid, recovery->userid);
457
458 zbx_snprintf_alloc(&sql, &sql_alloc, &sql_offset,
459 "update problem set"
460 " r_eventid=" ZBX_FS_UI64
461 ",r_clock=%d"
462 ",r_ns=%d"
463 ",userid=" ZBX_FS_UI64,
464 r_event->eventid,
465 r_event->clock,
466 r_event->ns,
467 recovery->userid);

flush_events() は、ソースコードのコメントにもありますが、キャッシュにあるイベント情報をデータベースへ追いやるための関数です。

save_events() にて、イベント情報をデータベースへ保存し、save_problems() にて、イベントに関する障害を生成してデータベースへ保存します。

save_event_recovery() では、復旧イベントを生成し ( データベースへの保存 )、元となる障害イベントの情報を更新します。この更新において、復旧イベントの生成された時刻 ( 秒単位 ) が、r_clock となります。

つまり、<bold> 復旧イベントが生成されていない障害は永遠に削除されません。
</bold>regexp(".") のような、復旧状態にならないトリガーを作成してはいけないということです。

これにより、延々と problem テーブルと events テーブルが肥大化していくというとです。

対策はないのか ?

復旧条件がないトリガーを作成した場合の対策はないのか ? ということになります。
一応あることはあります。

Zabbix 4.0.0 より、Web フロントエンドから障害をクローズできるようになりました。

参考

https://www.miraclelinux.com/product-service/zabbix/tech-lounge/zbx-tl-017-closing

https://www.zabbix.com/documentation/4.0/manual/acknowledges#updating_problems

上記で、「一応」と書いたのは今回の検証で問題が見つかったからです。
ログをバーストさせ、イベントが大量に生成され、さらに付随したアクションが実行される状況だと、まずトリガーを無効にしてこれ以上の負荷を掛けないようにします。

それはまさに障害ページの表示が遅延する状況です。
こうなると、Web フロントエンドから障害をクローズもできなくなってきてしまいます。

ということで、MIRACLE ZBX 4.0 リリースの頃には対策も考えておかないといけません。

さらなる MySQL の問題
上記に関連して MySQL の問題も露呈しました。

MySQL を File-Per-Table モード ( 当社の推奨です ) で起動すると、テーブルごとに保存ファイルが設定されます。

参考

https://dev.mysql.com/doc/refman/5.6/ja/innodb-multiple-tablespaces.html

MySQL のデータ保存アルゴリズムによりその必要領域が確保されるのですが、Zabbix のように追加・削除が頻繁にあるような、特にバーストしたような状況では、過大なスペースを取得してしまうことがあります。

しかしながら、データが削除されたとしても容易にそのスペースは削減されません。

それだけならまだしも、この過大なスペースを確保した状況だと、データベースの使用メモリ量も増大していました。

"alter table alerts engine innodb" のようにしてスペースのシュリンクを行うことはできるのですが、長期間ロックが発生するなどの問題があります。

この点では PostgreSQL の方が優れていると思います。

関連記事

Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 1
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 2
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 3
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 4
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 5
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 6
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 7
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 8
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 9
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 10
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 11
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 12
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 13
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 14
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 15
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 16
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 17
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 18
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 19
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 20
Zabbix 3.2 以降の新機能解説(Zabbix 4.0 を見据えて) その 21

注意事項

  • 本ドキュメントの内容は、予告なしに変更される場合があります。
  • 本ドキュメントは、限られた評価環境における検証結果をもとに作成しており、全ての環境での動作を保証するものではありません。
  • 本ドキュメントの内容に基づき、導入、設定、運用を行なったことにより損害が生じた場合でも、当社はその損害についての責任を負いません。あくまでお客さまのご判断にてご使用ください。
サイバートラストのテレワークソリューション
採用情報ページ リニューアル
組込み Linux にプラスして 長期間の製品ライフサイクルをサポート EM+PLS