doc.dev1x.org

fluent-bitでdocker composeのログを収集する

目的

課題

解決策

サンプル

ディレクトリ構造

.
├── 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