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の設定

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

```:/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