Mackerelのgo-check-pluginsを利用する際に注意すること

皆さま、ご機嫌いかがでしょうか。 最近新しい日本語を学びつつ、すぐ学んだ単語や表現を使ってみる楽しさにハマっているコンサルティング部のキムです!:D 弊社のメンバーに直近教えてもらったのは **バザールでござーる** です。こういうのばかり教えて貰えば **困るでこざる** でしょう(笑) さて、本日はMackerelのカスタムスクリプトに関してお話したいと思います。 お客様の案件でMackerelのカスタムスクリプトを使うようになりましたが、作業時に注意点について気づきましたのでその内容をまとめました。
2019.09.27

皆さま、ご機嫌いかがでしょうか。

最近新しい日本語を学びつつ、すぐ学んだ単語や表現を使ってみる楽しさにハマっているコンサルティング部のキムです!:D

弊社のメンバーに直近教えてもらったのは バザールでござーるYoutube動画ござる の使い方でした。こういうのばかり教えて貰えば 困るでこざる でしょう(笑)

さて、本日は Mackerel の go-check-plugins に関してお話したいと思います。 お客様の案件で Mackerel の go-check-plugins を使うようになりましたが、作業時に注意点について気づきましたのでその内容をまとめました。

目次

go-check-plugins とは

Mackerelにはチェック監視 ということがあります。Mackerel エージェントがインストールされてあるインスタンスの上、mackerel-agent.conf ファイルに希望のチェック項目を追加しておくことで、Mackerel エージェントがそのチェック項目のチェックを定期的に実行します。実行の結果は Mackerel のマネコンで確認することができます。

プラグインの種類は go-check-plugins の Github リポジトリ を見るとすぐ分かります。

本記事では、私が案件として作業した check-http, check-tcp, check-procs プラグインを例として説明させて頂きます。

検証のため Amazon Linux 2基盤のEC2にmackerel agentとgo-check-pluginsをインストールします。(Mackerel用の監視タグはついてます)

$ sudo curl -fsSL https://mackerel.io/file/script/amznlinux/setup-all-yum-v2.sh | MACKEREL_APIKEY='kTucXPzkrhUh2Harne2bd56aeYbfHVZy78GjL9mt6RRc' sh
$ sudo yum install mackerel-check-plugins

OSバージョンによってインストールスクリプトが異なりますので、上記のコマンドを実行する前に対象インスタンスの環境を必ずチェックしましょう。 go-check-plugin を試してみる準備は以上になります。すぐ試してみます。

/etc/mackerel-agent/mackerel-agent.conf ファイルを vi 等で開きますと、下記のような内容が見えます。

apikey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

# pidfile = "/var/run/mackerel-agent.pid"
# root = "/var/lib/mackerel-agent"
# verbose = false
# apikey = ""

# [host_status]
# on_start = "working"
# on_stop  = "poweroff"

# [filesystems]
# ignore = "/dev/ram.*"

...

一番上の apikey の下に下記の内容を追加します。

apikey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

[plugin.checks.proc_apache]
command = ['check-procs', '--pattern', 'httpd']

[plugin.checks.http_local_80]
command = ['check-http', '--url', 'http://localhost:80']

# pidfile = "/var/run/mackerel-agent.pid"
# root = "/var/lib/mackerel-agent"

...

内容を保存して以下のコマンドで Mackerel エージェントをリスタートします。

$ sudo systemctl restart mackerel-agent.service

Mackerelのマネコンで確認してみると以下のようなアラートが発生したことが分かります。 Mackerel-alert-1 Mackerel-alert-2

はい、httpd プロセスがまだ無いのでプロセスチェック監視も httpチェック監視もアラートステータスになりました。 今回は httpd をインストールして、プロセススタートしてみます。

$ sudo yum install httpd
$ sudo systemctl start httpd

Mackerelの go-check-plugins はCLIで実行することができますので確認してみます。

$ check-procs --pattern httpd

結果は当然OKでした。

Procs OK: Found 6 matching processes; cmd /httpd/

すると、Mackerelのマネコンのアラート数も減りました。

Mackerel-alert-3

http チェック結果は /var/www/html 経路で index.html ファイルが無いためですので index.html をサクッと作りました。

$ sudo touch /var/www/html/index.html

これで全てのチェック監視のアラートが消えました。

$ check-http --url http://localhost:80
HTTP OK: HTTP/1.1 200 OK - 13 bytes in 0.000954 second response time

Mackerel-alert-4

何が問題だったか

例えば、テスト環境でサーバーの変更がよくある場合や何かの理由でCritialではなく、Warningだけの結果が欲しい場合もあるかもしれません。(私の場合でした)その場合には下記のように go-check-plugins のオプションがつけられます。

[plugin.checks.proc_apache]
command = ['check-procs', '--pattern', 'httpd', '--warning-under', '1']

[plugin.checks.http_local_80]
command = ['check-http', '--url', 'http://localhost:80', '--status', '400-599=warning']

このように設定すると、おそらくCriticalにステータスが変われないんだろうと思ったのですが、実際にはそもそも httpd が実行されていない場合はステータスがCriticalになってしまいました。何が起こっているのかを調べたくてソースコード見てみると、さすがにデフォルト値がチェック監視ルールのステータスをCriticalに変更する犯人でした。

check_procs.go コードを見る

...
var opts struct {
	...
	CritUnder     int64    `short:"C" long:"critical-under" value-name:"N" default:"1" description:"Trigger a critial if under a number"`
	...
}

critical-under のデフォルト値が1に設定されてありました。

check_http.go コードを見る

...
if !found {
	switch st := resp.StatusCode; true {
	case st < 400:
		checkSt = checkers.OK
	case st < 500:
		checkSt = checkers.WARNING
	default:
		checkSt = checkers.CRITICAL
	}
}
...

checkSt のデフォルト値がCRITICALでした。

分かったこと

実際に go-check-plugin のコードを読むことで、http チェック監視の場合、デフォルト値が Critical になって、例えば httpd 等のプロセスが死んだ場合は Connection Refused になって ステータスが Critical になるしかない事が分かりました。

process チェック監視の場合、mergeStatus という関数を見ると --critical-under を0に設定する事で対応ができる事が分かりました。

check_procs.go コードを見る

...
func mergeStatus(count int64, current checkers.Status) checkers.Status {
	result := checkers.OK
	if opts.CritUnder != 0 && count < opts.CritUnder ||
		opts.CritOver != nil && count > *opts.CritOver {
		result = checkers.CRITICAL
	} else if opts.WarningUnder != 0 && count < opts.WarningUnder ||
		opts.WarningOver != nil && count > *opts.WarningOver {
		result = checkers.WARNING
	}

	if result > checkers.WARNING {
		return checkers.CRITICAL
	} else if result > checkers.OK {
		return checkers.WARNING
	} else {
		return checkers.OK
	}
}

まとめ

本記事の例はあまりよくあるパターンではないと思いますが、Mackerelの監視ルール設定とは違い、チェックプラグインを使う時はプラグイン毎の仕様が異なることが分かりました。Mackerelの導入時に go-check-plugins を使うならば、先ずREADME.md文書、もしくはコードで仕様を確認してから作業する方が良いのではないかという記事でした。