そもそもなぜログを転送・集約するのか
冗長構成の Web サーバーにおいて、アクセスログやエラーログといった各種ログファイルが複数サーバーに分散してしまうことへの対策。
また、オートスケーリング環境だとスケールイン時にサーバーそのものが消えてしまうといった事情より。
ログ集約先
用途によって様々。
監査目的で単純に一定期間ファイル保管するだけだったり、分析するために DB へ投入したり。
ログ収集ツール (エージェント)
ログ集約のために、主に下記のようなツールが存在する。
大体、サーバー内でデーモンとして動くタイプかと。
やってみた
Fluentd を使ってログファイルを、とりあえず Amazon S3 へ転送してみた。
ちなみに、設定を変えれば、他のログファイルも転送できるし、転送先も自由自在。
- Amazon Linux 2
- Auto Scaling グループ配下
- ゴールデンイメージ方式で、すでに Auto Scaling 構成済み
- Fluentd (v1.2系) でログファイルを S3 へ転送
- Apache のログ (アクセスログ、エラーログ)
- syslog
- インスタンス単位かつ 1 時間単位でファイル化
Fluentd のインストール
上記手順にも記載されているが、RPM インストール前にNTP デーモンの確認やファイルディスクリプタ数の増加等の事前準備 を行うべし。
また、Apache のログファイルを読み取る関係上 Fluentd を root
権限で起動する必要があるので、systemd のドロップインを作成して起動設定を変更。
# mkdir /etc/systemd/system/td-agent.service.d
# vim /etc/systemd/system/td-agent.service.d/10-td-agent.service.conf [Service] User=root Group=root Environment="TD_AGENT_OPTIONS=--user root --group root --config /etc/td-agent/td-agent.conf"
# systemctl daemon-reload # systemctl enable td-agent # systemctl restart td-agent
Fluentd の設定
とりあえず、作成した設定。
/etc/td-agent/td-agent.conf
字面から大体読み取れるが、Input の設定 (<source>
) と Output の設定 (<match>
) をどう繋ぐ (ルーティングする) かを設定しているだけ。
syslog 読み取り設定
<source> @type syslog @label @META tag system.local port 5140 bind 127.0.0.1 priority_key priority facility_key facility </source>
/var/log/messages
のファイルなどを tail するわけではなく、syslog デーモンへ UDP 接続しに行くので、syslog デーモン側でも UDP ソケットの待受設定を行っておく必要がある。
Amazon Linux 2 は rsyslog
なので、/etc/rsyslog.conf
末尾に下記を追記して systemctl restart rsyslog
すれば良い。
/etc/rsyslog.conf
. . . # Send log messages to Fluentd *.* @127.0.0.1:5140
Apache ログ読み取り設定
<source> @type tail @label @META tag httpd.access path /var/log/httpd/access_log pos_file /var/log/td-agent/httpd-access.log.pos <parse> @type ltsv time_key time time_format %d/%b/%Y:%H:%M:%S %z </parse> </source> <source> @type tail @label @META tag httpd.error path /var/log/httpd/error_log pos_file /var/log/td-agent/httpd-error.log.pos <parse> @type apache_error </parse> </source>
こっちは普通にログファイルを tail する設定。
アクセスログに関しては、標準では conbined 形式のログをパースできる。
しかし、ログ形式をカスタマイズした場合に対応が難しいので、こちらの記事を参考に LTSV (Labeled Tab-separated Values) 形式でアクセスログを出力するように Apache の設定を変更した。
/etc/httpd/conf/httpd.conf
LogFormat "domain:%V\thost:%h\tserver:%A\tident:%l\tuser:%u\ttime:%{%d/%b/%Y:%H:%M:%S %z}t\tmethod:%m\tpath:%U%q\tprotocol:%H\tstatus:%>s\tsize:%b\treferer:%{Referer}i\tagent:%{User-Agent}i\tresponse_time:%D\tcookie:%{cookie}i\tset_cookie:%{Set-Cookie}o" ltsv CustomLog "logs/access_log" ltsv
ログ行に EC2 メタデータを付与
<label @META> <match **> @type ec2_metadata @label @S3 output_tag ${tag_parts[0]}.${tag_parts[1]} <record> instance_id ${instance_id} private_ip ${private_ip} </record> </match> </label>
ドキュメントから読み取れる通り、Fluentd はプラグインアーキテクチャを採用しており、入出力やログの加工といった様々な機能がプラグインとして実装されていて、サードパーティ製のプラグインも多数公開されている。
今回は、オートスケーリンググループ配下の EC2 インスタンスに保存されているログを集約するので、fluent-plugin-ec2-metadata というプラグインを使用して、どのインスタンスのログか識別できるように EC2 のメタデータ (インスタンス ID、プライベート IP) をログに含めてみた。
なお、サードパーティ製のプラグインを使用する場合は、プラグインのインストールが必要。
# /opt/td-agent/embedded/bin/fluent-gem install fluent-plugin-ec2-metadata
S3 へ転送
<label @S3> <match **> @type s3 s3_bucket logs.example.com s3_region ap-northeast-1 <shared_credentials> path /root/.aws/credentials profile_name logs </shared_credentials> store_as json # gzip, json, txt, lzo <format> @type json # json, csv, msgpack... </format> path ${tag[0]}-${tag[1]}/${instance_id}_ time_slice_format %Y%m%d%H <buffer tag,time,instance_id> @type file path /var/log/td-agent/buffer/${tag[0]} timekey 3600 timekey_wait 10m chunk_limit_size 256m </buffer> </match> </label>
これも見りゃ大体わかりますが…… S3 へ転送する際の諸々の設定。
IAM の認証情報は <shared_credentials>
で ~/.aws/credentials
に記載されたプロファイルを使えたり、<instance_profile_credentials>
でインスタンスに割り当てられた IAM ロールを使えるらしい (参考)。
権限的には当然ながら、対象S3バケットへの読み書き権限が必要になる。
また、S3 なので当然ファイル単位での転送となる。よって、バッファを設けてファイルに書き込むべきログを一定期間ためておく仕組みが必要になる。
今回は 1 時間ごとにファイルを生成して S3 へ転送するようにした。
後編へ続く……
(余談)
新しいバージョンの Fluentd では、設定ファイル内に path ${tag[0]}-${tag[1]}/${instance_id}_
のようなプレースホルダが用いてログの内容を設定値として使えるようになった。
しかし、これを使うためにはプレースホルダとして使うキーを <buffer tag,time,instance_id>
のように <buffer>
のところに列挙する必要がある (数時間ハマった)。
The important point is if you want to refer time, tag or record keys on path, you need to list keys in
(See also v0.14 Plugin API slide).
Fluentd v0.14.9 has been released | Fluentd