Monitを導入

Monitとは

タイトルの通りですが、キュアスタ!にMonitというツールを導入しました。
サーバ上でMastodonプロセスがダウンした場合に、それを自動で検知し、再起動したりできるツールです。

「はて?それはそもそも、systemdの標準機能なのでは?」と思った人もいたかも。
ご指摘自体は間違いではないのですが、キュアスタ!のサーバはわたしの思い入れからFreeBSDで動作しており、systemdの機能を利用することができません。

systemdの代替というわけでもないですが、最近まではgodという、少し古いが枯れたツールを使っていました。
このgod、しばらくメンテナンスされておらず、使いづらいところも出てきていて、そろそろ後継の環境をと思っていたところだったのです。

rcNGとは

ところでFreeBSDでのデーモン起動は、一般的にはrcNGというNetBSD由来の機能により行われます。
rcNG準拠の起動スクリプトを書けば、サーバ機自体が起動した時のデーモン各々の起動を自動化できるだけでなく、例えば拙作モロヘイヤであれば service mulukhiya start 等のコマンドで手動起動を行うこともできる様になります。

話が逸れましたが、Mastodon等をMonit対応にする為には、それぞれをrcNG対応にするのが近道と感じました。(理由はのちほど)
例えばMastodonは、ざっくり以下の3つのプロセスで構成されますが、(各々の正しい呼び方があるわけではない様ですが、一般にもこれらの名前で呼ばれることが多い様です)

  • Mastodon Web
  • Sidekiq
  • ストリーミングAPI

それぞれについて起動スクリプトを書く必要があります。
今まではgodによる起動を行っていた為、rcNGの一般的な起動スクリプトは必ずしも必要ではありませんでした。

rcNG対応起動スクリプト

今回書いたのが、以下の様なもの。慣例に従って書いた、あまり技巧的な記述もないないベタなものですw /usr/local/www/mastodon にMastodonがインストールされ、Mastodonの実行ユーザーmastodonが既に作成されているとして。
また、それをふまえて/etc/rc.confに以下のような記述が必要です。(最近はsysrcというコマンドもある為、自動化は容易)

1
2
3
mastodon_enable="YES"
mastodon_path="/usr/local/www/mastodon"
mastodon_user="mastodon"

/usr/local/etc/rc.d/mastodon-web

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/bin/sh

# PROVIDE: mastodon_web
# REQUIRE: LOGIN

# Add the following line to /etc/rc.conf to enable `mastodon_web':
#
#mastodon_enable="YES"

. /etc/rc.subr

name="mastodon_web"
rcvar="mastodon_enable"

load_rc_config "mastodon"
: ${mastodon_enable="NO"}
: ${mastodon_path=""}
: ${mastodon_user=""}

export PATH=${PATH}:/usr/local/bin:/usr/local/sbin
export LANG=ja_JP.UTF-8
export LC_ALL=ja_JP.UTF-8

start_cmd=${name}_start
stop_cmd=${name}_stop

mastodon_web_start() {
cd $mastodon_path
sudo -u $mastodon_user zsh -c 'RAILS_ENV=production bundle exec rails server puma | logger -t mastodon_web &'
}

mastodon_web_stop() {
pkill -U $mastodon_user -f puma
}

run_rc_command "$1"
  • zshから起動しているのは、rbenv環境が.zshenvで初期化されている為。起動スクリプトにzshを使うのは、あまり一般的ではないかもしれません。
  • 本当は、環境変数RAILS_ENVの大元は/etc/rc.confに書きたいところですね。実現にはちょっと工夫が必要なので一旦は保留でベタ書き。
  • 私自身は、この起動スクリプトをChefで設置しています。環境変数RAILS_ENVは実際には、ほんとにベタ書きしているわけではないです。

/usr/local/etc/rc.d/mastodon-sidekiq

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/bin/sh

# PROVIDE: mastodon_sidekiq
# REQUIRE: LOGIN

# Add the following line to /etc/rc.conf to enable `mastodon_sidekiq':
#
#mastodon_enable="YES"

. /etc/rc.subr

name="mastodon_sidekiq"
rcvar="mastodon_enable"

load_rc_config "mastodon"
: ${mastodon_enable="NO"}
: ${mastodon_path=""}
: ${mastodon_user=""}

export PATH=${PATH}:/usr/local/bin:/usr/local/sbin
export LANG=ja_JP.UTF-8
export LC_ALL=ja_JP.UTF-8

start_cmd=${name}_start
stop_cmd=${name}_stop

mastodon_sidekiq_start() {
cd $mastodon_path
sudo -u $mastodon_user zsh -c 'RAILS_ENV=production bundle exec sidekiq -C config/sidekiq.yml | logger -t mastodon_sidekiq &'
}

mastodon_sidekiq_stop() {
pkill -U $mastodon_user -f sidekiq
}

run_rc_command "$1"
  • Mastodon Webの起動スクリプトとそれほど違いがあるわけではありません。説明割愛。

/usr/local/etc/mastodon-streaming

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/bin/sh

# PROVIDE: mastodon_streaming
# REQUIRE: LOGIN

# Add the following line to /etc/rc.conf to enable `mastodon_streaming':
#
#mastodon_enable="YES"

. /etc/rc.subr

name="mastodon_streaming"
rcvar="mastodon_enable"

load_rc_config "mastodon"
: ${mastodon_enable="NO"}
: ${mastodon_path=""}
: ${mastodon_user=""}

export PATH=${PATH}:/usr/local/bin:/usr/local/sbin
export LANG=ja_JP.UTF-8
export LC_ALL=ja_JP.UTF-8

start_cmd=${name}_start
stop_cmd=${name}_stop

mastodon_streaming_start() {
cd $mastodon_path
sudo -u $mastodon_user sh -c 'NODE_ENV=production BIND=0.0.0.0 npm start | logger -t mastodon_streaming &'
}

mastodon_streaming_stop() {
pkill -U $mastodon_user -f streaming
}

run_rc_command "$1"
  • こちらもあまり違いはありませんが、環境変数BINDも設定しています。これはMastodonとnginxが別のホストで動いている場合に必要な記述で、大抵の環境では必要ありません。
  • これまで同様loggerコマンドにより、標準出力をsyslogに送っています。MastodonのストリーミングAPIは、npmlogモジュールでログの出力を行っていますが、デフォルトの出力先は標準エラー出力である為、標準出力にログを出力する(最終的にログをsyslogに送る)為には、ストリーミングAPIへの改造が必要となります。(手前味噌ですが、拙作パッチ

Monit自体の導入

パッケージのインストール

実はここまで、試行錯誤にけっこう時間を使ってしまいましたが、あとは流れ作業でさくさくと。以下実行。

1
2
sudo pkg install monit
sudo sysrc monit_enable=YES

/etc/rc.confmonit_enable="YES"の記述があることを確認。

/usr/local/etc/monitrc

/usr/local/etc/monitrcに以下記述。
/usr/local/etc/monitrc.sampleのコピーから修正するのでも可。

1
2
3
4
5
6
set daemon 30
set log syslog
set httpd port 2812 and
allow 127.0.0.1
allow 203.xxx.xxx.xxx # 管理人自宅の固定IPアドレス
include /usr/local/etc/monit.d/*
  • パーミッションは600じゃないとエラーがでる様です。
  • 一般的にはメールを送る機能も併せて設定するようですが、Sensuによる監視系が別途構築されていることもあり、不要なのでわたしは省いています。
  • ここで重要な設定は、 監視を30秒周期で行う というところ。

プロセス個別の設定

キュアスタ!ではMastodonだけでなく、モロヘイヤや真琴さん含め、多くのプロセスが動いています。
ここではMastodonを例にして。

/usr/local/etc/monit.d/mastodon

1
2
3
4
5
6
7
8
9
10
11
check process mastodon-puma with matching "puma .* \[mastodon\]"
start program = "/usr/sbin/service mastodon-web restart" with timeout 60 seconds
stop program = "/usr/sbin/service mastodon-web stop"

check process mastodon-sidekiq with matching "sidekiq .* mastodon"
start program = "/usr/sbin/service mastodon-sidekiq restart" with timeout 60 seconds
stop program = "/usr/sbin/service mastodon-sidekiq stop"

check process mastodon-streaming with matching "mastodon/streaming/index.js"
start program = "/usr/sbin/service mastodon-streaming restart"
stop program = "/usr/sbin/service mastodon-streaming stop"
  • プロセス名の正規表現マッチングを行い、先ほど設定した30秒ごとに生死を確認します。
  • start programstop programに、実際に実行するコマンドを記述。ここにあまり複雑なコマンド列は指定できない為、こまかな動作はコマンド(スクリプト)側に記述する必要があります。rcNG準拠の起動スクリプトを用意しなければいけなかった理由はこれ。
  • 通常はここに、プロセス起動の失敗回数などに関連した記述も行われるようですが、おいおい詰めていきたいです。

Monitの起動

以下実行。

1
sudo service monit start

実行後に2812ポートをWebブラウザで叩くと、以下の様な管理画面が。
Monit管理画面

ここまで到達すれば、キラやば☆と言うほかはありません。