Elasticsearchがいくら盛り上がったところで既存の監視システムとの兼ね合いでアプリのログはsyslogに来ないと困っちゃうという事は良くある話でして。
filebeat使えれば良かったんですが、あれでsyslogに出力するのが結構難儀。
基本的には、Kubernetes上で動作するPodのコンテナ出力ログは、kubeletが「/var/log/containers/」ディレクトリ下に「pod名_namespace名_コンテナ名っぽい何か.log」のファイル名でリンクを張ってくれるので、それをtail -Fしてloggerコマンドでsyslogに送り付ければ良い。
# ! /bin/bash
MYNAME=logsys
LOGDIR=/var/log/containers
ACTIVE=/dev/shm/$MYNAME
mkdir -p $ACTIVE
watch () {
logger -t $MYNAME -- $MYNAME::start watching $l
echo $BASHPID > $ACTIVE/$1
# tail -F -c +0 $LOGDIR/$1 | while read m; do
tail -F $LOGDIR/$1 | while read m; do
logger -t $MYNAME -- $1::$m
done
rm $ACTIVE/$1
}
ls $LOGDIR | while read l; do
if [ ! -e $ACTIVE/$l ]; then
watch $l &
fi
done
上記はスクリプトを実行した後に出力されたログをsyslogに転送しますが、tailに-c +0オプションが付いたほうの行に変えればスクリプト実行時点で存在するログもすべてsyslogに送ります。まあ、気を付けて使用ください。
chmod +x /root/logsys してですね、新しいPodが作成された時も勝手にsyslogにも出力してくれるよう、それを crontab -e で1分に1回実行するように仕込みます。
* * * * * /root/logsys
停止したい場合は、crontab -eで上記行をコメントアウトして定期実行を止めたのち、以下のコマンドを実行してスクリプトのtailプロセスを全部止めます。
for i in $(ls /dev/shm/logsys); do kill $(ps --ppid $(cat /dev/shm/logsys/$i) -o pid=); done
場合によっては大量のログが出力されることになるので、「ls $LOGDIR | while read l; do」の直後ぐらいに、ファイル名からnamespace名等でsyslog転送するログをフィルタする処理を追加したほうが良いでしょう。ちなみにwhile文でそのループの処理を途中でスキップするにはcontinueを使います。