rsyslogで信頼性のあるログ転送について調べたメモ
事の発端は fluentd を使ってみようかと思って fluentd(td-agent)のインストールと設定 を読んだことで す。fluentd のデメリットのところを読んで、ちょっと気になりました。
Goで書かれたmoriyoshi/ikも気になったのですが、最近話聞かないし最終コミットも3ヶ月前だったので、今回は見送りました。
そこで、rsyslogでのログ転送について調査してみようと思いました。
rsyslog自体についてはこちらのスライド#logstudy 01 rsyslog入門が分かりやすかったです。
syslog形式での出力サポート
nginx
Apache HTTP server
- Sending our web logs to syslog
- ErrorLogやCustomLogに以下の様な感じで書く。
CustomLog "|/usr/bin/tee -a /var/log/www/access.log | /usr/bin/logger -thttpd -plocal6.notice" combined
- teeでファイルに出力しつつloggerコマンドでsyslogにも出力。
- syslogで複数のapacheサーバのログを集積する - orattaの日記
- こちらもCustomLogでloggerコマンドを呼び出す方式。
- DSAS開発者の部屋:Apacheのアクセスログをsyslog経由で出力するためのモジュールを作りました
- Apache 2.2以降で使えるカスタムモジュール
- Cのsyslog関数を使っている
- mod_syslog - Apache HTTP Server Version 2.5
- Apache 2.5からは標準モジュールになったらしい
Apache Traffic Server
Cのsyslog出力関数
Goのsyslogクライアントライブラリ
loggerコマンド (シェルスクリプトから出力したい時に使用)
信頼性のあるログ転送のためのRELPプロトコル
UDPで転送するとパケットロスしてログが消失する恐れがあります。
#logstudy 01 rsyslog入門の81枚目のスライドによると、TCPで転送しておけば、転送先のsyslogサーバがダウンしたら、キューイングして、復活したら再送するそうです。
これで十分そうな気もしたのですが、syslog forwardでググっていると[SOLVED] Rsyslog forward log to other syslog serverというページからリンクされているRainer’s Blog: On the (un)reliability of plain tcp syslog…という記事を見つけました。
さらにそこからリンクされているRainer’s Blog: why you can’t build a reliable TCP protocol without app-level acks…という記事も読んでみました。
一言で言うと、信頼性の有るログ転送を実現するためには、TCPレベルでACKがあってもだめで、アプリケーションレベルのACKが必要ということです。
アプリケーションレベルのACKが無いと、サーバのバッファスペースが溢れてもクライアントが気づけないというのが問題の本質のようです。
これを解決するために作られたのが、Rainer’s Blog: RELP - the reliable event logging protocolです。
librelp - a reliable logging libraryというのがCの実装で、ソースを見るとライセンスはGPLv3でした。
RELPはrsyslogdにすでに取り込まれていました。
- Reliable Forwarding of syslog Messages with Rsyslog — rsyslog 8.14.0 documentation
- imrelp: RELP Input Module — rsyslog 8.14.0 documentation
- omrelp: RELP Output Module — rsyslog 8.14.0 documentation
ただし、imrelpの Ruleset
パラメータはrsyslogdのバージョン7.5.0以降が必要らしいです。CentOS 7のrsyslogdは yum info rsyslogd
によると 7.4.7 なのでこれは使えないようです。
CentOS 7では rsyslog-relp.x86_64 : RELP protocol support for rsyslog
というパッケージをインストールすればRELPが使えるようです (まだ試してないです)。
参考: goで書かれたrsyslogサーバ
mcuadros/go-syslogというgoで書かれたrsyslogサーバも見つけました。
UDP、TCP、Unixソケットでの受信が出来るそうです。READMEに"using RFC3164, RFC6587 or RFC5424"とありますが、どこまで対応しているかは未調査です。
RELPは非対応のようです。ソースコードで大文字小文字無視でrelpで検索してヒットしなかったので。
軽く試してみた結果をgistに貼りました。 https://gist.github.com/hnakamur/75385e5572262b5ce9f6