b-shock. Fortress

Sensuサーバの構築

長い間監視はNagiosでやってたが、重い腰を上げて乗り換えようと思い立った話。
この記事から何回かに分けて、Sensuによる監視環境の構築で行ったことについて述べていく。 サーバはFreeBSD、クライアント(被監視ノード)はFreeBSDとUbuntu。

  1. サーバ構築編
  2. クライアント構築編(FreeBSD)
  3. クライアント構築編(Ubuntu)
  4. 監視プラグイン実装編
  5. 通知プラグイン実装編

全5回予定。(2017/10/03更新)

乗り換えの理由

負荷

外部から直接監視できない監視項目(ディスク容量やCPU負荷等)は、一般的な監視系では エージェントを通じて行われる。Nagiosにも、この用途で使用するNRPEというエージェントがある。
Nagiosを使っていた頃は、このNRPEの導入が煩わしいという理由で、またNRPEとの通信が どうやら暗号化されていないように見えたこともあって、積極的に利用すべき機能とは思えず、 NRPEに代わるものとしてSSHを使用することにした。 とは言っても、SSHでトンネルするのではなく、SSHでリモートのコマンドを叩き、 そのレスポンスを監視する単純な仕組み。

追記(2017/10/06)
NRPEに暗号化の機能は、どうやらあった模様。

結果は上々で、こりゃいいやと監視項目を黙々と増やしていた。 そうしたら、この仕様ではメモリ1GBの極小VPSには負荷が大きかったらしく、監視項目が 数百を超えたあたりで悲鳴をあげ始めた。具体的には、仮想コア2個に対してロードアベレージが 常時4.0〜5.0ぐらい出るようになっていた。こりゃいかんぞと。

また、このNagiosをホスティングしていたさくらVPSでは、外向きのSSHセッション数に上限が あった模様。一度、SSHのセッションが多くなりすぎて、外向きのSSHを全て遮断されるという シャレにならない事態になったことあった。
監視の為にやってることであって、別にやましいことじゃないっすよ!とさくらインターネットに 納得してもらい、SSHセッション数の上限を特別に引き上げてもらってた。
一旦は解決した問題だけど、これを許してもらえたのも、当時は負荷が大したことなかった 為だと思われ、高負荷が続けばさくらインターネットから出入り禁止にされてしまう可能性も 考えられたw

PHP

Nagiosの管理コンソールはPHPのWebアプリとして実装され、Apacheを通して実行される。
このPHP、何年もリファクタリング等を行っていないことが明らかで(出力されるHTML、なんと frameを利用したものだし)、一応PHP7.1で無修正で運用はできていたものの、レガシー記述の オンパレードと予想された。(怖くて読んでないけどw)
なまじおれがPHPerである故か、そうしたアプリを運用していくことに耐えられなくなっていた。

追記(2017/10/06)
HTMLがframeを使ったレガシーなものだったという件、おれがずっと使っていたNagiosが3.xという 古いものだったせいである可能性もある。(現行バージョンは4.x)
3.xのリリースは2008年で、最終のアップデートは2013年。 (Nagios Core 3.x Version History) こんなに古いものを使い続けていたほうがどう考えても悪いって話。
但し、2008年時点でも「frame使ってるのはどうよ?」という話ではあったと思う。

サーバ構築の実際

Sensuは、公式にはChef等を利用した構築が推奨されるようだ。
しかし、Chefで運用してゆく(レシピ等をメンテナンスする)にはChefを使わないセットアップ手順を 知る必要があるはずで、ここでは手作業で構築する手順について述べる。
余談だが、Sensuには公式のChefレシピもあるのだが、個人的にはレシピは手書きしたほうが よいと考えている。構築手順を知っているのは運用している自分自身のはずであり、安易に ブラックボックスにしたくない部分ではないか?
従って、公式のレシピを利用する手順を書くつもりはないので、申し訳ないけど、知る必要がある人は ググってください。

Rubyは当然入ってるよねw?Ruby環境の構築は他に譲るので割愛。
あと、ここ以降全て、suしてroot権限で実行。

rsyslogの設定

ログは極力syslogに流し、rsyslogで処理する方針で。rsyslogの導入に関して割愛。
もし /usr/local/etc/rsyslog.conf に以下の様な記述がなかったら、追記。

修正したら、rsyslogdをリロード。

1
service rsyslogd restart

Redisの設定

パッケージ導入

1
2
pkg install redis
sysrc redis_enable="YES"

/usr/local/etc/redis.conf

このファイル、実際にはMastodonインスタンスで使用しているものと全く同じ。
デフォルトの設定ファイルに対して、ログの出力先をsyslogに変更し、冗長なコメントを 全て削除しただけしたもの。

/usr/local/etc/rsyslog.d/redis.conf

/usr/local/etc/newsyslog.d/redis

毎日ログをローテーション、9世代まで、gzip圧縮という設定。newsyslogの詳細は割愛。(以降も同様)

起動

rsyslogもリロード。

1
2
service rsyslogd restart
service redis start

RabbitMQの設定

パッケージ導入

1
2
pkg install rabbitmq
sysrc rabbitmq_enable="YES"

/usr/local/etc/rabbitmq/rabbitmq.config

のちのちTLS対応したいと考えているが、一旦保留。(後述)
ipfwを設定してるだろうから、5672ポートを開けるのを忘れずに。

起動

1
service rabbitmq start

なんか、RabbitMQの起動、めっちゃ時間かかるんですけど。

アカウントの登録

ここで入力したパスワードはもちろん後で使うので、Evernoteなどに控えておくこと。

1
2
3
rabbitmqctl add_vhost /sensu
rabbitmqctl add_user sensu your_password
rabbitmqctl set_permissions -p /sensu sensu ".*" ".*" ".*"

RabbitMQをsyslog対応にする方法はまだわかっていないので、残念ながらここまで。
あと、syslog対応してないならローテーション設定も行いたいけど、これも保留。 但し、現状はローテーションが必要なほどログを吐いていない様だ。

Uchiwaの設定

Uchiwaは、Sensuの管理コンソール。最近はみんなこれを使ってるらしい。

パッケージ導入

1
2
pkg install uchiwa
sysrc uchiwa_enable="YES"

/usr/local/uchiwa/config.json

ポート3000で待機する設定なので、ipfwでポートを開けるのを忘れずに。

/usr/local/etc/rc.d/uchiwa

が既にあるはずだが、これをちょっといじる。(以下)

何をしているかというと、Uchiwaのログもsyslogに流したいが、実現するなら起動スクリプトを 直接修正するしかないって話。
ちょっと行儀悪いけど、仕方ないので勘弁してください。

/usr/local/etc/rsyslog.d/sensu.conf

/usr/local/etc/newsyslog.d/sensu

先の作業に関連する設定内容が含まれるけど、気にしないでw
Uchiwaの起動は、この時点ではまだしない。

Let’s Encryptの設定

引続き、Uchiwaをhttps化する。
本題から外れるので、詳細は割愛。Let’s Encryptを導入済みならcertbot renewとかは当然設定してるよね。

1
2
pkg install py27-letsencrypt
certbot certonly --webroot -w /path/to/document_root -d uchiwa.example.com -m admin@example.com --agree-tos

Uchiwaは通常はuchiwaユーザーから実行する設定になってて、uchiwaの実行権限から証明書を読める様に、 権限を調整する必要があった。(以下)

1
2
3
4
5
pw groupmod uchiwa -M daemon
chown root:daemon /usr/loal/etc/letsencrypt/archive
chown root:daemon /usr/loal/etc/letsencrypt/live
chmod 750 /usr/loal/etc/letsencrypt/archive
chmod 750 /usr/loal/etc/letsencrypt/live

ここまでやれば、Uchiwaが起動できる。

1
2
service rsyslogd restart
service uchiwa start

この時点ではSensuサーバが起動してないので、ブラウザから開いても(https://サーバのホスト名:3000/) エラーが出るはず。
また、本来はRabbitMQでもこの証明書を使いたいところだが、まだ実現できていない。

Sensuサーバの設定

パッケージ導入

1
2
3
4
5
gem install sensu
sensu-install --plugin mailer
sysrc sensu_server="YES"
mkdir /usr/local/etc/sensu
ln -s /usr/local/etc/sensu /etc/sensu

このあと、以下のファイルを一気に作っていく。

/usr/local/etc/sensu/conf.d/redis.json

/usr/local/etc/sensu/conf.d/rabbitmq.json

パスワードはさっき控えておいたやつ。

/usr/local/etc/sensu/conf.d/transport.json

/usr/local/etc/sensu/conf.d/mailer.json

/usr/local/etc/sensu/conf.d/handlers/mailer.json

/usr/local/etc/rc.d/sensu_server

起動

rsyslogも再起動。

1
2
service rsyslogd restart
service sensu_server start

この時点でUchiwaのほうに反応があるはずなので、 ブラウザから https://サーバのホスト名:3000/ を開く。
但し、この時点ではなんの監視も設定していないので、監視項目も監視対象もからっぽのはず。

起動・再起動

サービスの登録を行っているので、サーバリブート時に適切に起動されるはず。
何らかの理由で手動で起動する必要がある時は、以下。

1
service sensu_server restart

初回起動でもrestartでよし。細かいことは気にしない。
監視項目の編集を行った後も、同様にSensuサーバの再起動を行う必要がある。

問題点

RabbitMQのセキュリティ

証明書の適用がうまくいかなくて、現状はTLS化せずに運用している。
被監視ノードと監視サーバの間で、平文のメッセージが飛び交っているものと思われ、 パスワードだけに守られた脆弱な状況だ。
以前はSSHを使用していた為、セキュリティ的には大きく後退している。なんとかしたい。

証明書の適用自体は調べれば何とかなると思うが、監視サーバと被監視ノードに同じ証明書の ファイルを設置する必要がある様だ。
Let’s Encryptの場合、certbotで証明書を作成した後に各被監視ノードにrsyncで配布する等の 仕組みを構築する必要があるはず。

以上の事情から、監視プラグインの実装ではセキュリティに留意すべき。
詳しくは後日述べるが、監視プラグインにパスワードの類いを読ませるとき、コマンドラインから 指定する様な実装にするのは絶対禁止。

また、RabbitMQのポート(5672)を全開にしているが、被監視ノードとの間だけ通すよう、 ipfwに設定したほうがいいかもしれない。

以上。なんか書き漏らしがないか心配だw
もしあったら追記します。