Scribeでログの集約・収集【後編】

いよいよWebサーバのログをScribeを通して処理してみます。examplesディレクトリに入っていた、scribe_catとscribe_ctrlはそのまま使えそうなのでこれを利用してみます。

# cp examples/{scribe_cat,scribe_ctrl} /usr/local/bin/

まず、ログサーバ(ログを集約するサーバ)の設定をします。このサーバに各Webサーバのログが書き込まれていきます。設定ファイルは/usr/local/etc/scribeの下に置くものとします。

# mkdir /usr/local/etc/scribe
# mkdir /var/log/scribe
# touch /usr/local/etc/scribe/scribed.conf

ログサーバの設定ファイル(scribed.conf)の内容は下記になります。

port=1463 # 待ち受けポート
max_msg_per_second=2000000 # 一秒間に受け取るメッセージ数
check_interval=3 # チェックする間隔(Store)
# Web server
<store>
category=www* # wwwではじまるカテゴリを処理
type=buffer # buffer storeを利用
target_write_size=20480 # バッファサイズ(これ以上溜まると書き出す)
max_write_interval=1 # 書き出す間隔(バッファサイズに依存せずに一定期間で処理する間隔)
buffer_send_rate=2 # 処理する間隔
retry_interval=30 # primaryに失敗してからのリトライ間隔
retry_interval_range=10 # リトライ間隔の幅(この幅でランダムに試行する)
<primary>
type=file # file storeを利用
fs_type=std # stdのみサポート
file_path=/home/www/logs # ログを書き出す場所
base_filename=access_log # ログファイル名
max_size=100000000 # ローテート最大サイズ
rotate_period=daily # ローテート間隔(daily=日ごと)
rotate_hour=0 # 何時にローテートするか(0時)
rotate_minute=5 # 何分にローテートするか(5分)
add_newlines=1 # 改行するか(1=する)
create_symlink=true # 最新ファイルへのシンボリックリンクを設定
</primary>
# primaryの書き込みに失敗した場合の予備
<secondary>
type=file
fs_type=std
file_path=/tmp
base_filename=access_log
max_size=3000000
</secondary>
</store>
# 処理されなかったメッセージの保存先
<store>
category=default # defaultにすると処理されなかったものがくる
type=buffer
target_write_size=20480
max_write_interval=1
buffer_send_rate=2
retry_interval=30
retry_interval_range=10
<primary>
type=file
fs_type=std
file_path=/var/log/scribe
base_filename=scribed.log
max_size=1000000
</primary>
<secondary>
type=file
fs_type=std
file_path=/tmp
base_filename=scribed.log
max_size=3000000
</secondary>
</store>

scribedの起動スクリプトは下記のようなものを作りました。

#!/bin/sh
#
# Scribed     Startup script for the scribe daemon
#
# chkconfig: - 83 13
# description: Scribed.
#
# processname: scribed
# config: /usr/local/etc/scribe/scribed.conf
# pidfile: /var/run/scribed.pid
#
# Source function library
. /etc/rc.d/init.d/functions
if [ -f /etc/sysconfig/scribed ]; then
. /etc/sysconfig/scribed
fi
if [ -z "$SCRIBED_CONF_PATH" ]; then
SCRIBED_CONF_PATH="/usr/local/etc/scribe/scribed.conf"
fi
prog="scribed"
lockfile="/var/lock/subsys/$prog"
scribed="/usr/local/bin/scribed"
scribe_ctrl="/usr/local/bin/scribe_ctrl"
RETVAL=0
start() {
echo -n $"Starting $prog: "
$scribed -c $SCRIBED_CONF_PATH > /dev/null 2>&1 &
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
success
touch $lockfile
fi
echo
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc $scribed
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f $lockfile
return $RETVAL
}
status() {
$scribe_ctrl status
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
RETVAL=1
esac
exit $RETVAL

次にWebサーバ(ログの送信元サーバ)の設定をします。設定ファイルの保存先や起動スクリプトなどはログサーバと同じです。今回は念のためにログをネットワーク先(ログサーバ)とローカル二つに保存することにします。

port=1463
max_msg_per_second=2000000
check_interval=3
# Web server
<store>
category=www*
type=multi # multi storeネットワークとローカルで保存
target_write_size=20480
max_write_interval=1
# ネットワーク保存
<store0>
type=network # ネットワーク転送する
remote_host=192.168.1.2 # 転送先ホスト
remote_port=1463 # 転送先ポート
</store0>
# ローカル保存
<store1>
type=file
fs_type=std
file_path=/home/www/logs
base_filename=access_log
max_size=100000000
rotate_period=daily
rotate_hour=0
rotate_minute=5
add_newlines=0
create_symlink=true
</store1>
</store>
<store>
category=default
type=buffer
target_write_size=20480
max_write_interval=1
buffer_send_rate=2
retry_interval=30
retry_interval_range=10
<primary>
type=file
fs_type=std
file_path=/var/log/scribe
base_filename=scribed.log
max_size=1000000
</primary>
<secondary>
type=file
fs_type=std
file_path=/tmp
base_filename=scribed.log
max_size=3000000
</secondary>
</store>

設定は以上です。両方のサーバでscribedが正常に起動できるか確認してください。次にWebサーバとなるApacheのログ出力をファイルから、Scribeへの出力に切り替えます。とりあえず、エラーログはそのままファイルへと出力、アクセスログをScribeに出力することにします。

パイプを使いScribeに渡すことになりますが、scribe_catにそのまま渡すだけではうまく動きませんでした。どうやらパイプを渡す先のプログラムをプロセス上にあげておく必要があるようです。(おそらくログ出力の負荷を減らすため?)
scribe_httpdというシェルプログラムを作り、その中で標準出力を受けながらループすることにしました。

## /usr/local/bin/scribe_httpd
## このシェルプログラムからscribe_catへ渡す
#!/bin/sh
while /bin/true
do read line
echo $line | /usr/local/bin/scribe_cat $1
usleep 100000
done

上記のシェルプログラムを使い、パイプ経由でログを出力します。

# httpd.confまたはextra/httpd-vhosts.confなど
<VirtualHost *:80>
ServerName www.example.com
DocumentRoot "/home/www.example.com/public_html"
# ErrorLogはファイルに出力
ErrorLog "/home/www/logs/www.example.com/error_log"
# CustomLogはパイプを使ってScribeに出力
CustomLog "| /usr/local/bin/scribe_httpd www.example.com" combined
</VirtualHost>

ちゃんとScribe経由で出力されたのですが一つ問題が・・・。負荷がけっこう高いようです。scribe_httpdがログ出力の個数分プロセスに立ち上がるようなので、バーチャルホストの数やアクセスが増えたらたいへんそうです。CPUの負荷が高いようなので適当に作ったシェルスクリプトがやばいんでしょうか?毎回scribe_catを呼び出すというようなことをせずに、直接Scribeにログを渡すような形にしてやれば、負荷もけっこう下がりそうです。

無事に成功?ということでこれで終わりにしたいと思います。いまさらですが、ScribeでWebサーバのログを集約するのはあまり向かないような気も・・・。しばらく運用してみて問題がおきたら報告していきたいと思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です