LoginSignup
48
52

More than 5 years have passed since last update.

systemdからFluentdにデータを流し込む

Last updated at Posted at 2014-12-22

時代はsystemd

…だそうです。巷ではinit v. systemd論争が続いていますが、Fluentdのモットーは「世の中の全ての開発者がデータを手軽に正しく集められる」ことですので、systemdだろうが頭文字Dだろうが、拘りはありません。

td-agentもCentos7版が昨日リリースされましたので、満を持してsystemdで管理されているサービスのログをどうやってFluentdで集められるのか、現状をシェアしたいと思います。

journalctl -o

ご存知の方も多いでしょうが、systemd環境では、journalctlがデフォルトのログのビューワとなります。例えばauditdのログをtailしたい場合は

$ journalctl -u auditd -f
-- Logs begin at Mon 2014-12-22 13:36:30 EST. --
Dec 22 13:36:31 systemd-fluentd auditd[264]: Started dispatcher: /sbin/audispd p...3
Dec 22 13:36:31 systemd-fluentd audispd[273]: priority_boost_parser called with: 4
Dec 22 13:36:31 systemd-fluentd audispd[273]: max_restarts_parser called with: 10
Dec 22 13:36:31 systemd-fluentd audispd[273]: No plugins found, exiting
Dec 22 13:36:31 systemd-fluentd augenrules[265]: /sbin/augenrules: No change
Dec 22 13:36:31 systemd-fluentd auditd[264]: Init complete, auditd 2.3.3 listeni...)
Dec 22 13:36:31 systemd-fluentd augenrules[265]: No rules
Dec 22 13:36:31 systemd-fluentd augenrules[265]: AUDIT_STATUS: enabled=1 flag=1 ...1
Dec 22 13:36:31 systemd-fluentd systemd[1]: Started Security Auditing Service.
Dec 22 15:09:10 systemd-fluentd auditd[264]: Audit daemon rotating log files

みたいな感じになります。-ftailのオプションと同じで、-uでサービス名のフィルタリングができます。他にも--since--untilで時間を区切れたりして、結構万能です。

機能が豊富なjournalctlですが、Fluentd的にもっともオイシイのは-oオプションです。これはアウトプットのフォーマッターオプションであり、-o jsonと指定することで、一行一JSONの形式で出力してくれます。

$ journalctl -u auditd -f -o json
{ "__CURSOR" : "s=09186fb5df0c4f1ba9a259995faefc2b;i=26b;b=3b8f00a5c3c7428aabec902ecdbce64e;m=1b6eef;t=50ad256595cd2;x=9cb8e91012839fc6", "__REALTIME_TIMESTAMP" : "1419273391660242", "__MONOTONIC_TIMESTAMP" : "1797871", "_BOOT_ID" : "3b8f00a5c3c7428aabec902ecdbce64e", "PRIORITY" : "6", "_UID" : "0", "_GID" : "0", "_MACHINE_ID" : "fd8cf26e06e411e4a9d004010897bd01", "SYSLOG_IDENTIFIER" : "systemd", "SYSLOG_FACILITY" : "3", "_TRANSPORT" : "journal", "_PID" : "1", "_COMM" : "systemd", "_EXE" : "/usr/lib/systemd/systemd", "_CAP_EFFECTIVE" : "1fffffffff", "_SYSTEMD_CGROUP" : "/", "CODE_FILE" : "src/core/job.c", "CODE_LINE" : "732", "CODE_FUNCTION" : "job_log_status_message", "MESSAGE_ID" : "39f53479d3a045ac8e11786248231fbf", "RESULT" : "done", "_HOSTNAME" : "systemd-fluentd", "_CMDLINE" : "/usr/lib/systemd/systemd --switched-root --system --deserialize 23", "UNIT" : "auditd.service", "MESSAGE" : "Started Security Auditing Service.", "_SOURCE_REALTIME_TIMESTAMP" : "1419273391658951" }
...

うわ、なんかいろいろ出てきましたね!Fluentd的にはin_tcpformat jsonが使えるので、これは非常にありがたいですが、人間的にはツラいので、一先ず-o json-prettyで中身を確認してみましょう。

$ journalctl -u auditd -f -o json-pretty
{
        "__CURSOR" : "s=09186fb5df0c4f1ba9a259995faefc2b;i=a3b;b=3b8f00a5c3c7428aabec902ecdbce64e;m=14b71339a;t=50ad3a1af217d;x=e37f04158d5689d0",
        "__REALTIME_TIMESTAMP" : "1419278950539645",
        "__MONOTONIC_TIMESTAMP" : "5560677274",
        "_BOOT_ID" : "3b8f00a5c3c7428aabec902ecdbce64e",
        "_UID" : "0",
        "_GID" : "0",
        "_SYSTEMD_SLICE" : "system.slice",
        "_MACHINE_ID" : "fd8cf26e06e411e4a9d004010897bd01",
        "PRIORITY" : "5",
        "SYSLOG_FACILITY" : "3",
        "_CAP_EFFECTIVE" : "1fffffffff",
        "_HOSTNAME" : "systemd-fluentd",
        "_TRANSPORT" : "syslog",
        "SYSLOG_IDENTIFIER" : "auditd",
        "SYSLOG_PID" : "264",
        "_PID" : "264",
        "_COMM" : "auditd",
        "_EXE" : "/usr/sbin/auditd",
        "_CMDLINE" : "/sbin/auditd -n",
        "_SYSTEMD_CGROUP" : "/system.slice/auditd.service",
        "_SYSTEMD_UNIT" : "auditd.service",
        "MESSAGE" : "Audit daemon rotating log files",
        "_SOURCE_REALTIME_TIMESTAMP" : "1419278950538648"
}
...

"PRIORITY", "SYSLOG_FACILITY", "MESSAGE"といった従来のsyslog的なフィールドに加え、Hostnameが変わっても永続的にサーバーを特定できる"_MACHINE_ID"など、役に立ちそうなフィールドがたくさんあります。

Fluentd的にはどのフィールドをtimestampにするのかが重要ですが、ここでは"__SOURCE_REALTIME_TIMESTAMP"を使います(注:単位がマイクロ秒です)。

systemd側としては、journalctl -f -o json | nc localhost <FLUENTD_PORT>でデータを流すだけです。

Fluentd側の設定

Fluentd側の設定はこんな感じになります。

<source>
  type tcp
  port 24225
  format json
  time_key _SOURCE_REALTIME_TIMESTAMP
  time_format %S
  tag systemd
</source>
<match systemd>
  type stdout
</match>

この設定でFluentdを起動します。

$ fluentd -c fluent.conf

そしてjournatlctlからnc経由でデータを送りつけると…

$ journalctl -f -o json | nc localhost 24225
2014-12-22 18:34:14 -0500 systemd: {"__CURSOR":"s=09186fb5df0c4f1ba9a259995faefc2b;i=4a0c;b=3b8f00a5c3c7428aabec902ecdbce64e;m=42b5c334d;t=50ad6819a2130;x=3e03baaff28f6db5","__REALTIME_TIMESTAMP":"1419291297194288","__MONOTONIC_TIMESTAMP":"17907331917","_BOOT_ID":"3b8f00a5c3c7428aabec902ecdbce64e","_TRANSPORT":"syslog","PRIORITY":"6","SYSLOG_FACILITY":"10","SYSLOG_IDENTIFIER":"sshd","_UID":"0","_GID":"0","_COMM":"sshd","_EXE":"/usr/sbin/sshd","_CMDLINE":"sshd: root [priv]   ","_CAP_EFFECTIVE":"1fffffffff","_SYSTEMD_CGROUP":"/system.slice/sshd.service","_SYSTEMD_UNIT":"sshd.service","_SYSTEMD_SLICE":"system.slice","_MACHINE_ID":"fd8cf26e06e411e4a9d004010897bd01","_HOSTNAME":"systemd-fluentd","MESSAGE":"pam_succeed_if(sshd:auth): requirement \"uid >= 1000\" not met by user \"root\"","SYSLOG_PID":"8331","_PID":"8331"}

ちゃんとデータが流れてきました!

これから先の話

将来的には外部プログラムに頼らずに、Fluentdから直接sd_journal APIを叩きたいところです。今のところ一応Rubyのバインディングはあるのですが、少しまだ挙動が把握しきれてなかったので、今回はjournalctlを使うアプローチを紹介しました>_<

それではMerry systemd + Happy Fluentd!

48
52
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
48
52