動機
弊社では一部の開発基盤に Gitlab および Gitlab Runner を利用しています。
Gitlab CE は定期的にアップデートされており、今のところウチの Gitlab は最新版に追従している。実際、公開 Web に開いているので、重要なセキュリティアップデートはすぐにアップデートしたいところです。
しかし Gitlab 君、アップデートを確認するには Admin 権限を持ったユーザーで管理画面にアクセスしてバージョンを確認しなければなりません。
だるい。
Mackerelで監視しよう
それ、Mackerel で監視すればええやん!
Gitlab のバージョンを監視
さっそく作っていきます。
完成品は=> https://gist.github.com/watahani/526a6cdb98dbc27a4c961cea4cbde2ba
Check Plugin の追加
まずは Mackerel公式の Check Plugin を追加します。これにより、あらかじめ定義されたサービスごとのプラグイン(ex. postgress, apache, linux, ....) などを利用してサービスを監視したり、自分で定義したチェックプログラムをもとにメトリクスを追加したりできます。
追加するには
sudo apt-get install mackerel-check-plugins
おー、簡単。
自作 Plugin の作成
Mackerel では自作のコマンドを登録して、その実行結果を監視することができます。
公式の例
[plugin.checks.ssh]
command = "ruby /path/to/check-ssh.rb"
notification_interval = 60
max_check_attempts = 1
check_interval = 5
timeout_seconds = 45
prevent_alert_auto_close = true
env = { HOST = "hostname", PORT = "port" }
action = { command = "ruby /path/to/notify_something.rb", env = { NOTIFY_API_KEY = "API_KEY" } }
memo = "This check monitor is ..."
plugin.checks.xxxx
という名前で監視項目を追加すると、定期的に command を実行し、その実行結果(終了コード)をもとにノーマル(0)・アラート(1)・クリティカル(2) ・不明(3) のアラートを上げてくれます。
今回は Gitlab のバージョンを取得したうえで、そのバージョンをバージョンチェックサーバー(https://version.gitlab.com) に投げて、その結果返ってくる SVG ファイルを解析するプログラムを書くことにしました。
まずは Chrome のデバッグモードでネットワーク監視をして、SVG ファイルをどのようにしてとってきているかをチェックします。
Builderscon で curl に変換できることを聞いていたので、 curl に変換します。
curl 'https://version.gitlab.com/check.svg?gitlab_info=eyJ2ZXJzaW9uIjoiMTEuMy40In0=' -H 'Referer: https://gitlab.example.com/' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36' --compressed
注意点として Header の Referer は必須らしく、なしでは情報が取れませんでした。ただし、URL自体はなんでもいいっぽいです。一応存在する URL にしておきます。
何か統計とかとって分析してるだろうしね。頑張れ Gitlab。
curl 'https://version.gitlab.com/check.svg?gitlab_info=eyJ2ZXJzaW9uIjoiMTEuMy40In0=' -H 'Referer: https://gitlab.example.com/'
バージョンはどう見ても Base64 でエンコードされているので、デコードして中身を見てみると
> echo eyJ2ZXJzaW9uIjoiMTEuMy40In0= | base64 -d
{"version":"11.3.4"}
ということで、
- バージョンとってきて
- json にして
- base64 エンコードしたうえで
- HTTP GET リクエストを version.gitlab.com に投げて
- 返ってきた svg を結果を解析する
ということをすれよさそうです。
コーディング
大したことないしシェル芸でいく(と思っていた時期が私にもありました
gitlab のバージョンは stack overflow に sudo gitlab-rake gitlab:env:info
で見れるって書いてあったけど、クッソ遅いので manifest ファイルから取得することにします。
cat /opt/gitlab/version-manifest.txt | grep gitlab-ce | awk '{printf "{\"version\":\"%s\"}", $2}'
{"version":"11.3.4"}
base64 で base64 に
cat /opt/gitlab/version-manifest.txt | grep gitlab-ce | awk '{printf "{\"version\":\"%s\"}", $2}' | base64
eyJ2ZXJzaW9uIjoiMTEuMy40In0K
curl で情報を取得
curl $(cat /opt/gitlab/version-manifest.txt | grep gitlab-ce | awk '{printf "{\"version\":\"%s\"}", $2}' | base64 | sed -e 's/^/https:\/\/version.gitlab.com\/check.svg?gitlab_info=/') -H 'Referer: https://gitlab.example.com/'
<!-- Generated automatically via `rake generate_svg` -->
<svg xmlns="http://www.w3.org/2000/svg" width="134" height="25">
<g shape-rendering="crispEdges">
<path fill="#D0021B" d="M0 0h134v25H0z"/>
</g>
<text x="67" y="16" fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="13">update asap</text>
</svg>
なんとなくワンライナーでやってるけど魔境になってきた。
後はこの SVG から、`update asap 部分を抜き出して判定すればよさそうなのですが、 Linux の sed には、最小一致での検索がなく抜き出し方法が分かりません。
検索すると、クラスを使ってsedで最短一致をする - Qiita という記事が見つかりました。
...いみがわからないよ
30分ほど sed と格闘したすえに python スクリプトにすることにします(笑)
無駄な時間をかけるより簡単なツールで作成したほうが良いです。
ということで完成品はこちらです。: https://gist.github.com/watahani/526a6cdb98dbc27a4c961cea4cbde2ba
ポイントとしては単に exit ではなく、 sys.exit で終了することぐらいです。
あとは設定ファイル /etc/mackerel-agent/mackerel-agent.conf
に
[plugin.checks.gitlab_version]
command = "python /etc/mackerel-agent/check-gitlab-version.py"
env = { HOST = "https://gitlab.example.com" }
max_check_attempts = 3
check_interval = 240
memo = "gitlab ce version check"
を追加して、agent を再起動します。
sudo systemctl restart mackerel-agent.service
アップデートが必要だと Slack にメンションが飛びます
メンションが飛んだら、本文に含まれる https://about.gitlab.com/update/#ubuntu を参考に gitlab のアップデートをします。
それでは良いサーバー監視ライフを。