fluent-bitでdocker composeのログを収集する
目的
- docker composeで複数のコンテナを動作させている時、fluent-bitで全てのコンテナのログを収集したい
- 収集したログはアプリケーションごとにフィルタ処理を挟んだり、保存先を変更したりしたい
課題
- Dockerのデフォルト設定で出力されるログにはコンテナ名が含まれていない
- したがって、全てのログを収集した時にどのコンテナのログか区別が付かない
解決策
- Composeファイルのloggingオプションにlabelを追加することでログにコンテナ名を付与できる
- 付与されたコンテナ名をfluent-bitで解析して、コンテナ名をタグとして扱う
サンプル
ディレクトリ構造
.
├── compose.yaml
└── fluent-bit.yaml
compose.yaml
services:
fluent-bit:
image: fluent/fluent-bit:latest-debug
container_name: fluent-bit
# バインドした設定ファイルを読み込むようコマンドラインオプションで指定
command: ["/fluent-bit/bin/fluent-bit", "-c", "/fluent-bit/etc/fluent-bit.yaml"]
# タイムゾーンを日本に指定
environment:
- TZ=Asia/Tokyo
# fluent-bitの設定ファイルとDockerのコンテナログディレクトリをリードオンリーでマウント
volumes:
- ./fluent-bit.yaml:/fluent-bit/etc/fluent-bit.yaml:ro
- /var/lib/docker/containers/:/var/lib/docker/containers/:ro
# fluent-bit自身のログが出力されるとログ収集時に無限ループに陥るのでログ出力を抑止(none)
logging:
driver: none
restart: always
web_app:
image: alpine/curl
container_name: web_app
# 適当に標準出力にメッセージを出力し続けるスクリプト
command: /bin/sh -c 'while true; do echo "Web App Log-> Request processed successfully"; sleep 1; done'
restart: always
# logging.optionsで参照するラベル
labels:
container_name: web_app
logging:
driver: "json-file"
options:
max-size: "64m"
max-file: "1"
# このように設定するとコンテナログにcontainer_nameフィールドが追加される
# e.g. {"date":xxxxxx,"log":"...","stream":"stdout","attrs":{"container_name":"web_app"}}
labels: "container_name"
db_logs:
image: alpine/curl
container_name: db_logs
command: /bin/sh -c 'while true; do echo "DB Log-> Connection established"; sleep 2; done'
labels:
container_name: db_logs
restart: always
logging:
driver: "json-file"
options:
max-size: "64m"
max-file: "1"
labels: "container_name"
fluent-bit.yaml
# fluent-bit自体の起動オプション
service:
flush: 1
daemon: false
log_level: info
# パーサ設定
parsers:
- name: json
format: json
time_key: time
time_format: "%Y-%m-%dT%H:%M:%S.%LZ"
pipeline:
# tailプラグインでDockerのコンテナログを丸ごと読み取り
inputs:
- name: tail
tag: docker.log
path: /var/lib/docker/containers/*/*-json.log
parser: json
mem_buf_limit: 5MB
skip_long_lines: false
refresh_interval: 10
rotate_wait: 30
filters:
# NestFilterでattrsフィールドのレベルを持ち上げる(LiftUp)
- name: nest
match: docker.*
nested_under: attrs
operation: lift
# attrsフィールドはトップレベルに移動(コピー)されたので、不要になった元のattrsフィールドを削除
- name: modify
match: docker.*
remove: attrs
# ログ中のcontainer_nameフィールドの値を利用してタグを置換する
# e.g. docker.log -> container.web_app
- name: rewrite_tag
match: docker.log
rule: $container_name ^(.+)$ container.$1 false
emitter_name: re_emitted
# タグによって出力先を変える(ここでは全て標準出力に出力)
outputs:
- name: stdout
match: 'container.*'
format: json_lines