Dockerのrsyslogでコンテナ間や他サーバから転送されるログを集約した


はじめに

dockerでいろいろコンテナを立てたら、ログを集約したくなったので、rsyslogでつくりました。

対象機器および環境

検証環境

  • CentOS8(8.1.1911)
  • Docker(19.03.5)
  • rsyslog

ログの保管方法

リモートから飛んできたログたちは、syslogフォーマットの %hostname% で個別ファイルに振り分けます。
/var/log/remotelog/ 配下に ホスト名ごとにログファイルとして保管します。

/var/log/remotelog/
|-- dhcp.log
|-- esxi01.prosper2.net.log
|-- FWdc01.prosper2.net.log
|-- proxy.log
|-- radius.log
`-- ....

送出側のsyslogフォーマットの設定によって、FQDNだったり、ホスト名だけだったり、ちょっとバラバラ。
ちゃんとすればいいんだけれど、やりかたがまだ調べられてません。。。

別のエントリで作成した infraserv-network に所属させた他のDockerコンテナから飛んできたログは、ちゃんと %hostname% フィールドにマッチしているみたいで、ホスト名で分けてくれてます。

作業内容

firewallでmasqueradeを設定

firewall-cmd --add-masquerade --zone=public --permanent
firewall-cmd --reload

Dockerイメージの準備

再利用できるようにイメージをつくっておきます。
Dockerfileと設定ファイルを置くための適当なディレクトリを作成しておきます

mkdir -p /opt/docker/syslog
cd /opt/docker/syslog

Dockerfileを作成

/opt/docker/syslog/syslog.df
FROM centos:centos8
ENV TZ='Asia/Tokyo'
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime ; \
    dnf -y update ; dnf install -y rsyslog cronie logrotate ; \
    mkdir /var/log/remotelog
COPY rsyslog.conf /etc/rsyslog.conf
COPY remotelog /etc/logrotate.d
CMD [ "/usr/sbin/init" ]

リモートからのログを受け付ける

bridge経由になっているため、コンテナはホスト(172.20.0.1/32)からのみ受け付けとしています

/opt/docker/syslog/rsyslog.conf
$template logfile_hostname,      "/var/log/remotelog/%hostname%.log"
$template logformat_verbose,     "%timegenerated%,%timereported%,%hostname%,%syslogtag%,%syslogseverity%,%syslogfacility%,%msg%\n"

$ModLoad imudp
$UDPServerRun 514
:fromhost-ip, ereregex, "172.20.0.1" -?logfile_hostname;logformat_verbose
& stop

logrotateの設定

ログは圧縮して40世代分保管します。

/opt/docker/syslog/remotelog
/var/log/remotelog/*.log {
        daily
        rotate 40
        compress
        missingok
        notifempty
        postrotate
          /bin/systemctl restart rsyslog
        endscript
}

Dockerfileからイメージをビルドしてコンテナ作成

Dockerfileが作成できたら、ビルドします。
--privileges はなんか評判悪そう(?)なので、推奨されてるぽい方法でコンテナ生成します。

docker build --force-rm -t infraserv:syslog . -f ./syslog.df && \
docker run --cap-add sys_admin --security-opt seccomp:unconfined  -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
  --network infraserv-network -it -d --name syslog --hostname syslog  -p 514:514/udp infraserv:syslog
docker exec -it syslog /bin/bash

接続テスト

コンテナ起動後、しばらく置いてからログディレクトリを確認します。

$ sudo docker exec -it syslog /bin/bash
[syslog]# ls -1sh /var/log/remotelog/
total 18M
 12K dhcp.log
704K esxi01.prosper2.net.log
 16M FWdc01.prosper2.net.log
4.0K _gateway.log
576K proxy.log
4.0K radius.log
256K VMinfraserv05.log

ファイルの中身

# tail -n 1 *
==> dhcp.log <==
Feb 11 21:37:20,Feb 11 21:37:20,dhcp,pseudolog_kea_dhcp4_log,5,16, 2020-02-11 21:37:15.253 INFO  [kea-dhcp4.dhcpsrv/26] DHCPSRV_MEMFILE_LFC_EXECUTE executing Lease File Cleanup using: /usr/sbin/kea-lfc -4 -x /var/lib/kea/dhcp4.leases.2 -i /var/lib/kea/dhcp4.leases.1 -o /var/lib/kea/dhcp4.leases.output -f /var/lib/kea/dhcp4.leases.completed -p /var/lib/kea/dhcp4.leases.pid -c ignored-path

==> esxi01.prosper2.net.log <==
Feb 11 21:56:05,Feb 11 12:55:58,esxi01.prosper2.net,snmpd:,6,3, send_env_notifications: sent 0 of 0 SEL entries as notifications, 0 already sent

==> FWdc01.prosper2.net.log <==
Feb 11 21:56:27,Feb 11 21:56:27,FWdc01.prosper2.net,1,2020/02/11,6,1, 21:56:27,001606007877,TRAFFIC,end,2049,2020/02/11 21:56:27,10.254.11.65,10.254.10.241,0.0.0.0,0.0.0.0,any_to_DNS,,,dns,vsys1,zTrust,zTrust,ethernet1/2.11,ethernet1/2.252,LFP_default,2020/02/11 21:56:27,3327,1,54264,53,0,0,0x19,udp,allow,290,78,212,2,2020/02/11 21:55:55,0,any,0,6764778,0x0,10.0.0.0-10.255.255.255,10.0.0.0-10.255.255.255,0,1,1,aged-out,0,0,0,0,,FWdc01,from-policy,,,0,,0,,N/A,0,0,0,0

==> _gateway.log <==
Feb 11 21:06:05,Feb 11 21:06:05,_gateway,VMwlc01:,3,16, *Dot1x_NW_MsgTask_1: Feb 11 21:06:05.056: %DOT1X-3-INVALID_REPLAY_CTR: 1x_eapkey.c:449 Invalid replay counter from client ac:63:be:92:9d:f9 - got 00 00 00 00 00 00 00 1d, expected 00 00 00 00 00 00 00 1e

==> proxy.log <==
Feb 11 21:55:57,Feb 11 21:55:57,proxy,pseudolog_squid_access_log,5,16, 1581425757.416 284915 172.20.0.1 TCP_TUNNEL/200 2563 CONNECT www.google-analytics.com:443 - HIER_DIRECT/216.58.197.174 -

==> radius.log <==
Feb 11 20:52:12,Feb 11 20:52:12,radius,pseudolog_radius_log,5,16, Tue Feb 11 20:52:12 2020 : Auth: (3) Login OK: [admin] (from client radius_clients port 34)

==> VMinfraserv05.log <==
Feb 11 21:55:11,Feb 11 21:55:11,VMinfraserv05,pseudolog_cacti_log,5,16, 2020/02/11 21:55:08 - SNMPAGENT WARNING: No notification receivers configured for event: cactiNotifyDeviceFailedPoll (CACTI-MIB), severity: medium

取得できてますね。

さいごに

syslog転送時に hostname フィールドを追加しない機器はホスト名が _gateway になってしまう。Cisco機器とか。
CiscoIOSで logging origin-id hostname とやっても、メッセージそのものにホスト名が記載されるだけみたいなので、ちょっと使いにくい。
↓こんな感じになってしまう。

Feb 11 20:22:16,Feb 11 20:22:16,_gateway,844:,5,23, Rhq01: Feb 11 20:22:16: %IKEV2-5-SA_UP: SA UP

出典

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/s1-basic_configuration_of_rsyslog
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/s1-using_rsyslog_modules