Docker Container内のログ(nginx)をSplunkにpush送信する方法

まとめの背景
---
- dockerコンテナ関連のログのSplunkへの出力方法は2015年からいくつか存在していた
    - [Docker Logging Driver](https://docs.docker.com/config/containers/logging/splunk/)
        - 元祖Dockerロギングドライバー
    - [Universal Forwarderコンテナイメージ](https://hub.docker.com/_/splunk-universal-forwarder)
        - みんな大好きUF
    - [Splunk Connect for Docker](https://github.com/splunk/docker-logging-plugin) **2018 brand new**
        - Docker Logging Driverの後継機
- コンテナのログの集め方はそれぞれ特性があり、調べた2019.09.28時点で感じたのは、日々コンテナ周りの技術進化のスピードが速く、取り込み方法もケースバイケースで使い分けする必要がありそう
- Docker単体でなく、k8sを経由してログを収集するモジュールもある（Splunk Connect for Kubernetes）
- とりあえず今回は**Splunk Connect for Docker**を使ってコンテナ内のデータをどのように収集できるのか検証を実施
  

Splunk Connect for Dockerのポイント
---
- Dockerからplugin経由でpushでログを飛ばす仕組みです。Splunk側はHECで受け取る。
- コンテナログはjson, inline(default), rawの3つのフォーマットで出力が可能

手順
---
### Docker環境の準備
- Amazon Linux release 2 (Karoo)で構築
- ※AWS Market Placeのdockerホストはいまいち。2017年公開のもののためkernelが古かったり、splunk containerが起動しなかったり。。
    
- 利用したdockerのversion

```shell-session
# docker version
Client version: 1.7.0-dev
Client API version: 1.19
Go version (client): go1.8.3
Git commit (client): 582db78
OS/Arch (client): freebsd/amd64
Server version: 1.7.0-dev
Server API version: 1.19
Go version (server): go1.8.3
Git commit (server): 582db78
OS/Arch (server): freebsd/amd64
```

- DockerイメージのDL（nginx）今回はnginxを利用。

```shell-session
# docker pull nginx
```

## Splunk Connect for Dockerの準備
<img width="1254" alt="スクリーンショット 2019-09-28 17.36.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/cbf282d3-5c65-1442-85b1-c113fc3a1bf3.png">

### pluginのインストール
```shell-session
# docker plugin install splunk/docker-logging-plugin:latest --alias splunk-logging-plugin
```

### pluginの有効化を確認
```shell-session
# docker plugin ls
ID                  NAME                           DESCRIPTION             ENABLED
35530a1a22e5        splunk-logging-plugin:latest   Splunk Logging Plugin   true
```

## Splunk設定（HTTP Event Collector(HEC）)
### HECのグローバル設定の有効化
- グローバル設定をクリック
<img width="959" alt="スクリーンショット 2019-09-28 16.20.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/c1cadc14-2f93-917b-d268-98bc3eeff1dc.png">

- 以下のようなパラメータを設定
<img width="885" alt="スクリーンショット 2019-09-28 16.19.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/5b5e1bff-5b2d-a4e1-38bf-03f971ffa4dc.png">

### HECトークンの新規作成
- 設定 - データ入力 - HTTPイベントコレクタの新規追加
<img width="1208" alt="スクリーンショット 2019-09-28 16.13.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/7d98d146-3bfc-2dd2-06ba-80e8a5435695.png">

- HTTPイベントコレクタの名前を入力し、次へ
<img width="1213" alt="スクリーンショット 2019-09-28 16.14.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/7a8ef9a0-ee86-960c-f76a-f6770901cd7e.png">

- とりあえずsourcetypeは自動でindexはdockerを作成
<img width="905" alt="スクリーンショット 2019-09-28 16.15.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/7794d757-8e5f-9d06-f4ca-459857a8002f.png">

### Dockerイメージの起動(nginx)
- splunk-logging-driverを読みこみながら、nginxを起動

```shell-session

# docker run -it -d -p 80:80 --log-driver=splunk-logging-plugin \
           --log-opt splunk-token=c7d0854b-b0d5-xxxx-xxxx-xxxxxxxxxxx \
           --log-opt splunk-url=https://13.xxx.xxx.xx:8088 \
           --log-opt splunk-insecureskipverify=true \
           --log-opt splunk-index=docker \
       nginx
```

**splunk-loggin-pluginをログドライバーにセット。オプション-dをつけることでバックグランドで動作します。-p 80:80とすることで、ホストのポート80がコンテナのポート80にマップ。**
`run -it -d -p 80:80 --log-driver=splunk-logging-plugin`
**HECのtokenをセット**
`--log-opt splunk-token=c7d0854b-b0d5-xxxx-xxxx-xxxxxxxxxxx`
**HECのURLをセット**
`--log-opt splunk-url=https://13.xxx.xxx.xx:8088`
**SSL証明書チェックを無視**
`--log-opt splunk-insecureskipverify=true`
**index=dockerに保存**
`--log-opt splunk-index=docker`
**nginxイメージを起動**
`nginx`


- Docker のログ出力先として、splunk-logging-pluginが読み込まれていることを確認

```shell-session
# docker inspect  0ab8e00dccd4 |grep log
                "Type": "splunk-logging-plugin”,
```

- dockerコンテナのSTATUS正常に起動していることを確認

```shell-session
# docker ps -a
CONTAINER ID        IMAGE                                 COMMAND                  CREATED             STATUS                PORTS                                   NAMES
44fb61ee4ed3        nginx                                 "nginx -g 'daemon of…"   2 hours ago         Up About an hour      0.0.0.0:80->80/tcp                      compassionate_jones
```
*Exited(1)などは何かしら正常に動いていないことをしめす

`About a minute ago   Exited (1) About a minute ago`

*そんなときは下記コマンドで原因のログを調査

```shell-session
# docker logs (コンテナID) 
Error response from daemon: configured logging driver does not support reading
```

### ログの取得を確認
- **http://(GlobalIP)**でWebアクセス
<img width="653" alt="スクリーンショット 2019-09-28 17.35.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/5eab6673-27a8-5f06-1889-fa723cb950ac.png">

- Splunkにログが届くことを確認
<img width="1095" alt="スクリーンショット 2019-09-28 17.15.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/bba1706f-f0d9-2363-a01a-3422b57b31d3.png">

- nginxのコンテナイメージの場合、標準でaccess_logとerror_logをコンテナのログ出力対象(/dev/stdout, /dev/stderr)に設定されている模様

```shell-session
root@44fb61ee4ed3:/var/log/nginx# ls -la
total 0
drwxr-xr-x 1 root root 41 Sep 12 14:37 .
drwxr-xr-x 1 root root 63 Sep 28 06:32 ..
lrwxrwxrwx 1 root root 11 Sep 12 14:37 access.log -> /dev/stdout
lrwxrwxrwx 1 root root 11 Sep 12 14:37 error.log -> /dev/stderr
```

### フィールドの抽出
- はい、ただ残念ながら1ラインのログの場合、よくあるapacheのTAを使って自動的にフィールド抽出がされません。これがlogging-driverの制限かな。json形式のアプリケーションログだったらおそらくsplunkに入るときにキレイにパーシングされるとは思います。
<img width="1095" alt="スクリーンショット 2019-09-28 17.15.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/2c5c50ce-4149-fb91-e0b7-cbcecde64cc2.png">

- でも、必要なフィールド抽出はsplunkが得意なところ。
<img width="1351" alt="スクリーンショット 2019-09-28 17.22.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/e5dbfbd5-2e8a-77a4-f2d3-fa790df266aa.png">

- Scheme on the Fly!
<img width="1341" alt="スクリーンショット 2019-09-28 17.22.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/03e480a1-ec35-6e36-4cb7-a31906b9a57d.png">

- はい、webアクセスログは楽な方。フィールド抽出できました。
<img width="1350" alt="スクリーンショット 2019-09-28 17.24.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/2cd78c01-497c-8376-072a-1879364004fd.png">


注意点
---
- 1コンテナ内で生成されるデータに対して1種類のsourcetypeの指定まではできる。とはいえコンテナ内に複数種類のログソースがある場合、もうちょっとスマートに取りたいところ

``--log-opt splunk-sourcetype=access_combined ``

まとめ
---
- とりあえずコンテナのデータをsyslogサーバに飛ばしておく感覚でSplunkに飛ばすことは簡単に可能
- あとはスキーマオンザフライの力を使って必要なフィールドを後から抽出していく
- もう一周くらいまでばコンテナ関連のデータをもっと効率的に集める仕組みが確立されるかもしれないと期待して、.conf2019に期待


参照リンク
---
[SplunkでDocker運用監視](https://qiita.com/kikeyama/items/f07cb571691f82ca8927)
[Dockerコンテナ内のログをSplunkに入れてみた](https://qiita.com/kikeyama/items/515d65906537239e04d2)
[SplunkでKubernetesのログとメトリクスを監視してみよう](https://qiita.com/kikeyama/items/447c7126a5c454a558f0)