본문 바로가기

기타

[로그 모니터링] Fluent Bit 설치와 시스템 연동

반응형

이전 글들에서 Grafana 와 Loki 까지 구성을 완료했다.

이번 글에서는 Fluent Bit 를 설치하고 로그를 출력할 샘플 app 과 연동해서 Grafana 대시보드에 로그가 출력되는 것까지 완료해보겠다.

1. Fluent Bit 설치

Fluent Bit 공식 문서의 Docker 설치 방법을 참고하여 Docker 컨테이너로 Fluent Bit 서비스를 실행시켜 보겠다.

installation > download and install fluent bit > docker

 

Download and install Fluent Bit | Fluent Bit: Official Manual

 

docs.fluentbit.io

- docker-compose.yaml

공식 문서에서 docker run 명령어로 Fluent Bit 를 실행시키고 있는데, 이를 참고하여 docker-compose.yaml 을 작성했다.

 

services:
  ...
  fluentbit:
    image: fluent/fluent-bit
    container_name: fluentbit
    restart: unless-stopped
    volumes:
      - ./fluent-bit/fluent-bit.yaml:/fluent-bit/etc/fluent-bit.yaml

 

- fluent-bit.yaml

Fluent Bit 서비스의 설정을 위해서는 설정 파일을 작성해야 한다. 설정 파일은 conf 파일과 yaml 파일 두가지 형식이 있는데, conf 형식은 2026년을 마지막으로 deprecated 될 예정이라고 한다. 그래서 이 글에서는 yaml 형식을 사용하여 예제를 작성했다.

예제는 Fluent Bit 의 테스트 예제 설정으로 먼저 구성헀다. 예제 설정은 랜덤 값을 입력값으로 생성해서 이를 표준 출력으로 출력하도록 설정되어 있다.

해당 파일은 docker-compose.yaml 에서 확인할 수 있듯이 volume 연결을 통해 Fluent Bit 가 접근할 수 있도록 해주었다.

 

# https://github.com/fluent/fluent-bit/blob/master/packaging/testing/smoke/container/fluent-bit.yaml
service:
    http_server: "on"
    Health_Check: "on"
    log_level: debug

pipeline:
    inputs:
        - name: random
          tag: test
          samples: 10

    filters:
        - name: lua
          match: test
          call: append_tag
          code: |
              function append_tag(tag, timestamp, record)
                 new_record = record
                 new_record["tag"] = tag
                 return 1, timestamp, new_record
              end

        - name: expect
          match: test
          key_exists: tag
          key_val_eq: tag test
          action: exit

    outputs:
        - name: stdout
          match: test

 

- Fluent Bit 실행

이제 설정을 기반으로 Fluent Bit 를 실행하고 예제가 잘 동작하는지, 로그가 어떻게 출력되는지 확인해보겠다.

Docker Compose 로 Fluent Bit 를 실행하고 컨테이너가 출력하는 로그를 확인해보니 아래와 같이 랜덤한 수치를 가진 예제 로그가 출력되는 것을 확인할 수 있었다.

 

[0] cpu.local: [[1773219286.818495144, {}], {"cpu_p"=>0.772727, "user_p"=>0.136364, "system_p"=>0.636364, "cpu0.p_cpu"=>0.000000, "cpu0.p_user"=>0.000000, "cpu0.p_system"=>0.000000, "cpu1.p_cpu"=>0.000000, "cpu1.p_user"=>0.000000, "cpu1.p_system"=>0.000000, "cpu2.p_cpu"=>1.000000, "cpu2.p_user"=>0.000000, "cpu2.p_system"=>1.000000, "cpu3.p_cpu"=>0.000000, "cpu3.p_user"=>0.000000, "cpu3.p_system"=>0.000000, "cpu4.p_cpu"=>0.000000, "cpu4.p_user"=>0.000000, "cpu4.p_system"=>0.000000, "cpu5.p_cpu"=>2.000000, "cpu5.p_user"=>0.000000, "cpu5.p_system"=>2.000000, "cpu6.p_cpu"=>1.000000, "cpu6.p_user"=>1.000000, "cpu6.p_system"=>0.000000, "cpu7.p_cpu"=>0.000000, "cpu7.p_user"=>0.000000, "cpu7.p_system"=>0.000000, "cpu8.p_cpu"=>1.000000, "cpu8.p_user"=>0.000000, "cpu8.p_system"=>1.000000, "cpu9.p_cpu"=>1.000000, "cpu9.p_user"=>0.000000, "cpu9.p_system"=>1.000000, "cpu10.p_cpu"=>0.000000, "cpu10.p_user"=>0.000000, "cpu10.p_system"=>0.000000, "cpu11.p_cpu"=>0.000000, "cpu11.p_user"=>0.000000, "cpu11.p_system"=>0.000000, "cpu12.p_cpu"=>3.000000, "cpu12.p_user"=>0.000000, "cpu12.p_system"=>3.000000, "cpu13.p_cpu"=>0.000000, "cpu13.p_user"=>0.000000, "cpu13.p_system"=>0.000000, "cpu14.p_cpu"=>2.000000, "cpu14.p_user"=>0.000000, "cpu14.p_system"=>2.000000, "cpu15.p_cpu"=>0.000000, "cpu15.p_user"=>0.000000, "cpu15.p_system"=>0.000000, "cpu16.p_cpu"=>2.000000, "cpu16.p_user"=>0.000000, "cpu16.p_system"=>2.000000, "cpu17.p_cpu"=>0.000000, "cpu17.p_user"=>0.000000, "cpu17.p_system"=>0.000000, "cpu18.p_cpu"=>2.000000, "cpu18.p_user"=>1.000000, "cpu18.p_system"=>1.000000, "cpu19.p_cpu"=>0.000000, "cpu19.p_user"=>0.000000, "cpu19.p_system"=>0.000000, "cpu20.p_cpu"=>1.000000, "cpu20.p_user"=>1.000000, "cpu20.p_system"=>0.000000, "cpu21.p_cpu"=>1.000000, "cpu21.p_user"=>0.000000, "cpu21.p_system"=>1.000000}]
...

2. 로그 모니터링 시스템 연동

이제 예제가 아닌 실제 로그를 출력하는 my-app 이라는 application 과 Loki 등을 Fluent Bit 연동하여 로그를 수집하고 저장소에 전송하도록 해보겠다. 그리고 Loki 에 저장된 로그를 Grafana 에서 확인할 수 있도록 대시보드를 구성해보곘다.

- my-app 설정

먼저 로그를 출력할 application 부터 설정해보겠다.

파이썬으로 개발한 간단한 코드이고 5초마다 info, error 로그를 하나씩 출력하도록 개발했다.

 

import time
import structlog

structlog.configure(
    processors=[
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.add_log_level,
        structlog.processors.JSONRenderer(),
    ]
)

log = structlog.get_logger()

while True:
    log.info(
        "request handled",
        tenant_id="t_123",
        status_code=200,
    )

    log.error(
        "request failed",
        tenant_id="t_456",
        status_code=500,
    )

    time.sleep(5)

 

이 코드를 아래의 Dockerfile 과 docker-compose.yaml 을 통해서 빌드 후 도커 서비스로 실행시켜서 로그를 표준 출력으로 출력하도록 하겠다.

 

FROM python:3.11-slim

WORKDIR /app
COPY main.py .

RUN pip install structlog

CMD ["python", "main.py"]

 

services:
  ...
  my-app:
    image: my-app
    container_name: my-app
    build:
      context: ./app
      dockerfile: Dockerfile
    logging:
      driver: json-file
      options:
        tag: "my-app-service"

 

이렇게 구성한 후 Docker Compose 를 실행하면 아래와 같이 로그를 출력하는 것을 확인할 수 있다.

 

{"tenant_id": "t_123", "status_code": 200, "event": "request handled", "timestamp": "2026-03-11T09:18:29.644095Z", "level": "info"}
{"tenant_id": "t_456", "status_code": 500, "event": "request failed", "timestamp": "2026-03-11T09:18:29.644277Z", "level": "error"}
{"tenant_id": "t_123", "status_code": 200, "event": "request handled", "timestamp": "2026-03-11T09:18:34.642624Z", "level": "info"}
{"tenant_id": "t_456", "status_code": 500, "event": "request failed", "timestamp": "2026-03-11T09:18:34.642734Z", "level": "error"}

- Fluent Bit - input 연동

이제 Fluent Bit 가 my-app 의 로그를 수집하도록 input 연동을 진행해보겠다. 우선 docker container 의 로그를 읽기 위해서는 호스트의 도커 디렉토리를 Fluent Bit 컨테이너에 연결해주어야 한다.

docker container 의 logging driver 가 json-file 로 설정되어 있기 때문에 /var/lib/docker/containers 경로를 fluentbit 서비스에 volume 으로 연결해주어 로그 파일을 읽을 수 있게 해주었다.

 

fluentbit:
    volumes:
      - ./fluent-bit/fluent-bit.yaml:/fluent-bit/etc/fluent-bit.yaml
      - /var/lib/docker/containers:/var/lib/docker/containers:ro

 

그 다음 fluent-bit.yaml 설정 파일을 아래와 같이 변경하여 my-app 컨테이너의 로그를 수집하도록 설정했다. tail 플러그인을 통해 도커 컨테이너들의 로그 파일을 읽고 그 중 `my-app-service` 라는 태그를 가진 로그만 필터링 되도록 했다. (이 태그는 my-app 의 docker compose 설정에서 logging.option 의 tag 로 지정한 값이다.)

 

service:
    http_server: on
    Health_Check: on
    hot_reload: on

parsers:
    # application 의 log json 형식 parsing
    - name: json
      format: json
      time_key: timestamp
      time_format: '%Y-%m-%dT%H:%M:%S.%L'

pipeline:
    inputs:
        # docker 로그 파일을 tail 기능으로 로그 수집
        - name: tail
          tag: docker.service
          path: /var/lib/docker/containers/*/*-json.log
          multiline.parser: docker, cri

    filters:
        # my-app 의 로그만 수집되도록 하기 위한 필터
        # docker 로깅의 tag 설정 'my-app-service' 를 조건으로 로그 필터링
        - name: grep
          match: docker.service
          regex: $attrs['tag'] ^my-app-service$

        # my-app 의 로그에 대한 tag 변경
        # docker.service -> my-app.log
        - name: rewrite_tag
          match: docker.service
          rule: $attrs['tag'] ^my-app-service$ my-app.log false

        # application log 파싱
        - name: parser
          match: my-app.log
          key_name: log
          parser: json

    outputs:
        - name: stdout
          match: my-app.log

 

- Fluent Bit - Loki 연동

이번에는 output 설정을 변경하여 수집된 로그가 표준 출력이 아닌 Loki 로 전송되도록 변경해보겠다.

loki 플러그인을 사용했고 loki-write 서비스의 접속정보인 호스트와 포트를 지정해주었다. 그리고 labels, label_keys 를 통해 로그의 label 로 job, tenant_id, level 등을 지정해주었다.

 

pipeline:
...
    outputs:
        - name: loki
          match: my-app.log
          host: loki-write
          port: 3100
          labels: job=app
          label_keys: $tenant_id, $level

 

- Grafana Dashboard 설정

이제 Fluent Bit 를 실행시키고 출력되는 로그를 Grafana 대시보드에서 확인할 수 있도록 설정해보겠다. Docker Compose 로 Grafana, Loki, Fluent Bit, my-app 을 모두 실행시켜보겠다.

그 다음 Grafana 에 접속하여 Loki 를 Data source 로 지정한 대시보드를 생성한다. 그 다음 panel 설정에서 query 를 작성해주면 되는데 간단하게 Label filters 에서 `job = app` 으로 설정해주면 my-app 이 출력한 로그들이 출력되는 것을 확인할 수 있다.


여기에 filter 로 `level = info` 또는 `level = error` 를 지정해주면 my-app 이 출력한 로그 중 INFO 또는 ERROR 로그만 출력되는 것을 확인할 수 있다.

[References]

https://docs.fluentbit.io/manual

 

Fluent Bit documentation | Fluent Bit: Official Manual

High Performance Telemetry Agent for Logs, Metrics and Traces

docs.fluentbit.io

 

반응형