1年ぐらい前に諸事情により調べたメモ。
監視ツールでリソース情報とかのメトリクスに対して、○○を超えたら、みたいな閾値のチェックを設ける場合、元の値がディスク使用率とかロードアベレージのようなそのままの値が取れるものなら良いのですが(いわゆる GAUGE 値)、CPU 使用率や Traffic などは普通はカウンター値として取れるので(いわゆる COUNTER 値)、前回値からの差分に対して閾値のチェックをかける必要があります。
Nagios
そういう機能は無い。というかプラグイン自体がアラートを判断するので Nagios 的にはメトリクスに対する閾値チェックという概念がない。そういうのはプラグイン側で実装する。
プラグインで COUNTER 値をチェックするのはちょっと工夫が必要。
例えば、vmstat
を 1 秒間実行してその結果をチェックするとか、/proc/stat
をどこかに保存しておいて前回値との差分値をチェックする、とかです。
Sensu
チェックプラグインは Nagios と同じ仕様なので、基本は Nagios と同じ。
がしかし、Sensu で取得したメトリクスを時系列データベースに保存し、チェックプラグインで時系列データベースに問い合わせてチェックすることができます(Nagios でも eventhandler でパフォーマンスデータを時系列データベースに保存しておけば同じことはできると思うけど)。
Munin
少し前のバージョンでは Perl の Storable モジュール?でホストごとに記録されているステートファイルに、前回値と今回値が記録されています。
https://github.com/munin-monitoring/munin/blob/2.0.25/master/lib/Munin/Master/LimitsOld.pm#L319-L321
my $state_file = sprintf ('%s/state-%s-%s.storable', $config->{dbdir}, $hash->{group}, $host); DEBUG "[DEBUG] state_file: $state_file"; my $state = munin_read_storable($state_file) || {};
https://github.com/munin-monitoring/munin/blob/2.0.25/master/lib/Munin/Master/LimitsOld.pm#L350-L351
my $rrd_filename = munin_get_rrd_filename($field); my ($current_updated_timestamp, $current_updated_value) = @{ $state->{value}{"$rrd_filename:42"}{current} || [ ] }; my ($previous_updated_timestamp, $previous_updated_value) = @{ $state->{value}{"$rrd_filename:42"}{previous} || [ ] };
このステートファイルは RRA ファイルを更新するときに一緒に更新されます。
https://github.com/munin-monitoring/munin/blob/2.0.25/master/lib/Munin/Master/UpdateWorker.pm#L52
my $state_file = sprintf ('%s/state-%s.storable', $config->{dbdir}, $path); DEBUG "[DEBUG] Reading state for $path in $state_file"; $self->{state} = munin_read_storable($state_file) || {}; : my $last_updated_timestamp = $self->_update_rrd_files(\%service_config, \%service_data); : DEBUG "[DEBUG] Writing state for $path in $state_file"; munin_write_storable($state_file, $self->{state});
最新版だと SQLite に変わっていました。
https://github.com/munin-monitoring/munin/commit/ba5306d148f04269b3b6bcb61c43e2f1fb34375e
Cacti
Cacti 単体にそういう機能はなくて thold プラグインを使う必要があります。ので thold-v0.5.0 を見てみました。
DB の thold_data
テーブルの lastread,lasttime,oldvalue
辺りが前回値を持っています。
select lastread, lasttime, oldvalue from thold_data \G /* lastread: 5.4033 lasttime: 2017-04-26 12:55:13 oldvalue: 3309610 */
oldvalue
が生の値、lastread
が計算によって求められたチェック対象の値です。
この値は Cacti の poller_output
というフックポイントの処理で更新されます。たぶん RRA ファイルを更新するときに呼ばれるフックポイントです。
# setup.php api_plugin_register_hook('thold', 'poller_output', 'thold_poller_output', 'includes/polling.php'); # polling.php function thold_poller_output ($rrd_update_array) { // ..snip.. db_execute("UPDATE thold_data SET tcheck=1, lastread='$currentval', lasttime='" . date("Y-m-d H:i:s", $currenttime) . "', oldvalue='" . $item[$t_item['name']] . "' WHERE rra_id = " . $t_item['rra_id'] . " AND data_id = " . $t_item['data_id']); }
それにしてもアレなコードだわ・・・
Prometheus
コードを見るまでもなく、アラートに PromQL(Prometheus の時系列データベースに問い合わせる DSL)が使える時点で、都度時系列データベースに問い合わせているのは確定的に明らか。
また、データの取得の間隔とアラートのチェックの間隔が別々に設定できるので、メトリクスの取得とアラートの取得は独立して動いている、たぶん。
Zabbix
わからん。
まとめ
Munin や Cacti は RRA ファイルを読んでいるのかと思ったけどそんなことはなかった。パフォーマンス的にそれだと辛いのだと思う。
Graphite や InfluxDB のようなそれっぽい時系列データベースを使っていれば、アラートのチェックの都度、時系列データベースに問い合わせるのでも良いのかもしれない。
ただ、データの取得と、アラートのチェックと、可視化のための時系列データの保存、はなるべく疎な方がきれいな気がするので、Cacti や Munin 風の方法が良い気もする。