daemontoolsは設定が色々あり辛いのでSupervisord
を覚えることにした。
練習としてAirflowをデーモン化した。
簡単に説明するとSupervisordはUNIX likeなシステム上で複数のプロセスの起動を管理を提供するserver/clientシステムで
起動停止の他にイベント検知などもサポートしている。
完成イメージはこんな感じ。
Supervisordのインストール
1
2
3
4
|
$ yum install superviso
$ sudo systemctl start supervisord.service
$ sudo systemctl status supervisord.service
$ sudo systemctl enable supervisord.servicer
|
Supervisordの設定確認
systemd からSupervisordがどのように呼ばれるか確認する。
1
2
|
$ grep ExecStart /etc/systemd/system/multi-user.target.wants/supervisord.service
ExecStart=/usr/bin/supervisord -c /etc/supervisord.conf
|
Supervisordに渡される設定ファイルは*/etc/supervisord.conf* だった。
中を読むと_/etc/supervisord.d/*.ini_ を読み込んでいる事が想像できる。
1
2
3
|
$ grep -A 1 '^\[include\]' /etc/supervisord.conf
[include]
files = supervisord.d/*.ini
|
Airflowのインストールと設定
マニュアル通り入れてみる。
Airflowの設定ファイルは*$AIRFLOW_HOME/airflow.cfg* でコマンドは下の通り。
生成される設定ファイルについては今回は関与しない。
1
2
3
4
|
$ yum install python-devel
$ pip install airflow mysql
$ export AIRFLOW_HOME=/home/airflow
$ airflow initdb
|
AirflowをSupervisordで管理する
今回は自動リスタートによって1プロセス起動を維持させる。
vagrantユーザーで実行する。
またAirflowはフォアグラウンドで実行されるのでstdout,stderrをログファイルに出力させる。
Supervisordはファイルサイズによるログローテートを提供しているみたいだけど今回は日付でローテートさせたいのでlogrotateコマンドを利用する。
SupervisordにAirflowを登録する
設定ファイルは下のようになった。
Airflowでは*$AIRFLOW_HOME* が重要なのでenvironment で設定しておく(airflow initdb の出力先に合わせる)。
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
|
[program:airflow]
command=/usr/bin/airflow webserver -p 8080
process_name=%(program_name)s
user=vagrant
numprocs=1
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
stopsignal=QUIT
stdout_logfile=/var/log/airflow/airflow-stdout.log
stderr_logfile=/var/log/airflow/airflow-stderr.log
environment=HOME="/home/vagrant",AIRFLOW_HOME="/home/vagrant/airflow"
[program:airflowscheduler]
command=/bin/airflow scheduler
process_name=%(program_name)s
user=vagrant
numprocs=1
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
stopsignal=QUIT
stdout_logfile=/var/log/airflow/airflow-scheduler-stdout.log
stderr_logfile=/var/log/airflow/airflow-scheduler-stderr.log
environment=HOME="/home/vagrant",AIRFLOW_HOME="/home/vagrant/airflow"
|
logrotateにローテートの方針を設定する
Supervisordではサイズベースのログローテーションしかサポートされてない。
日時ベースで行うためにlogrotateコマンドを利用する。
日毎(daily)のローテートでファイル名の末尾に日付を含め(dateext)、過去ログが62ファイル(rotate)以上ある場合はアラートを出し
圧縮(compress)しローテートと圧縮のタイミングを分ける(delaycompress)様に設定してみた。
logrotateによってログが移動されても書き込みプロセスのファイルディスクリプタの向き先は同一ファイルに向いていて移動先ファイルに書き込まれ続ける。
そのためログを出力しているプロセスに開き直してもらうためにローテーとしたことを伝える必要がある。
前述の様にAirflow
は標準出力・標準エラー出力に出力していてログファイルに向けるのはSupervisordのためローテートを伝えるべきプロセスはSupervisordになる。
SupervisordはSIGUSR2を投げるとログファイルを開き直すので以下の様にpostrotateディレクティブを使えばいい。
またdelaycompressで圧縮するタイミングを分けるのはローテートした直後はログ出力元プロセスがファイルディスクリプタを握っていてファイルが壊れる可能性があるためである。
1
2
3
4
5
6
7
8
9
10
|
/var/log/airflow/airflow-*.log {
daily
dateext
rotate 62
compress
delaycompress
postrotate
/bin/kill -SIGUSR2 `cat /var/run/supervisord.pid` > /dev/null 2>/dev/null || true
endscript
}
|
下みたいにローテート実行すると実行されていることが確認できる。
1
2
3
4
5
6
7
8
9
10
11
12
|
$ cat /var/lib/logrotate.status | grep airflow
"/var/log/airflow/airflow-stderr.log" 2017-4-8-15:21:47
"/var/log/airflow/airflow-scheduler-stdout.log" 2017-4-8-15:21:47
"/var/log/airflow/airflow-scheduler-stderr.log" 2017-4-8-15:21:47
"/var/log/airflow/airflow-stdout.log" 2017-4-8-15:21:47
$ sudo /usr/sbin/logrotate -v /etc/logrotate.d/airflow
$ ls /var/log/airflow/airflow-s*
/var/log/airflow/airflow-scheduler-stderr.log /var/log/airflow/airflow-scheduler-stdout.log-20170408 /var/log/airflow/airflow-stdout.log
/var/log/airflow/airflow-scheduler-stderr.log-20170408 /var/log/airflow/airflow-stderr.log /var/log/airflow/airflow-stdout.log-20170408
/var/log/airflow/airflow-scheduler-stdout.log /var/log/airflow/airflow-stderr.log-20170408
|
ローテートが実現できたものの残念な事が2つある。
logrotateを定期実行する
logrotate を定期的に実行しないとログローテートされない。
crontab,anacron などに登録されているか確認する。
自分の環境ではanacron に登録されていた。
1
2
3
4
|
$ sudo cat /etc/anacrontab | grep daily
1 5 cron.daily nice run-parts /etc/cron.daily
$ ls /etc/cron.daily/
logrotate man-db.cron
|
サイズベースのログローテート
今回とは異なりログファイルをサイズベースでローテートするのはSupervisordがサポートしている。
以下の様に設定すれば良い(50MBごとにローテーション、最大バックアップ数:10)。
1
2
3
4
5
|
[program:x]
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10
stderr_logfile_maxbytes=50MB
stderr_logfile_backups=10
|