티스토리 뷰

web/backEnd

fluentd 도입기 - log aggregator

길세현 2022. 10. 5. 19:05

서문

이전 글에서 log forwarder를 마무리했다.

 

이번 글은 log forwarder가 포워딩한 데이터를 받아 실제로 DB or S3와 같은 오브젝트 스토리지에 저장하는 역할을 수행하는 log aggregator 구현한 경험을 기록한다.


본문

aggregator config

aggregator의 config 파일을 살펴보겠다.

<source>
  @type  forward
  port  24224
  <parse>
    @type json
  </parse>
</source>

# Mysql
<match ${table_1}.db.input>
  @type mysql_bulk
  host ${host}
  port ${port}
  database ${db}
  username ${mysqlUserName}
  password ${mysqlUserPassword}
  column_names id, datetime
  table ${tableName}
  flush_interval 30s
</match>

. . .

<match ${table_n}.db.input>
  @type mysql_bulk
  host ${host}
  port ${port}
  database ${db}
  username ${mysqlUserName}
  password ${mysqlUserPassword}
  column_names id, datetime
  table ${tableName}
  flush_interval 30s
</match>

# object storage
<match **>
  @type copy
  <store>
    @type stdout
  </store>
  <store>
    @type s3

    aws_key_id ${key}
    aws_sec_key ${secertKey}

    s3_bucket ${bucket} # 로그가 저장될 버킷 네임
    s3_region ${region}
    s3_endpoint ${endPoint} # 엔드 포인트 지정

    buffer_path /var/log/td-agent/s3/buffer

    path logs/

    time_slice_format %Y%m%d%H

    flush_interval 1m
  </store>
  <store>
    @type rewrite_tag_filter
    <rule>
      key key
      pattern /(.+)/
      tag $1.db.input
    </rule>
  </store>
</match>

<source>

forwarder와 유사하게 <source>태그로 시작하지만 이번엔 http 플러그인이 아닌 forward 플러그인을 사용한다.

forward 플러그인은 기본적으로 tcp 통신이다.

 

24224 포트로 데이터를 받고, <parse> 태그에 json 플러그인을 붙여 데이터를 json으로 변환해서 받는다.

 

mysql bulk insert <match>

그 다음 n개의 <match> 태그들을 사용했다.

 

이 태그들은 mysql_bulk 플러그인을 사용하여, mysql에 bulk insert를 직접 수행하는 태그들이다.

데이터들의 종류만큼 <match>태그를 사용하여 입력되어야할 테이블, 컬럼 등을 분리하였다.

 

flush_interval은 30s로 설정하여 30초 간격으로 bulk insert를 수행한다.

 

30초는 첫번째 글에서 분석한 결과를 토대로 설정한 시간으로, 현재 서비스는 제일 많이 입력되는 통계가 초당 5건 입력중이므로 30초면 많이 쌓여야 150건으로 예측 할 수 있다.

 

첫번째 글의 테스트 결과를 보면 1000건을 bulk insert로 입력 시, 0.055초가 소요되기에 30초 간격으로 유지해도 5배 이상의 서비스 성장까지 큰 문제없이 견딜 수 있다고 예상했다.

 

s3 <match>

마지막에 작성된 <match> 태그는 로그들을 시간단위로 object storage(ex: s3)에 저장하기 위한 설정으로, copy 플러그인으로 받아온 데이터를 복사해 내부의 <store> 태그들에 뿌려준다.

 

첫 <store> 태그는 이전 글과 마찬가지로 stdout 플러그인을 사용하여 콘솔창에 데이터 뿌려줌을 담당한다.

 

두번째 <store> 태그는 s3 플러그인을 사용해 실제 s3에 로그 작성을 담당한다.

aws key, secret key, bucket, region, endpoint 등 s3 정보를 입려하고, buffer_path로 데이터가 s3에 입력되기 전 임시 저장공간을 지정해준다.

path로 로그가 저장될 버킷 내 경로를 지정해주고, 어떤 시간단위로 로그파일을 잘라서 저장할지 time_slice_format 값으로 입력한다.

flush_interval를 1m으로 설정하여 1분마다 로그를 모아 실제 s3에 저장한다.

 

세번째 <store> 태그는 rewrite_tag_filter 플러그인을 사용하여 데이터들에 새로운 태그를 붙여서 다시 라우팅한다.

다시 라우팅하는 이유는 아래에 정리한다 

  • 데이터들이 적절한 mysql bulk insert를 담당하는 <match> 태그들에게 라우팅되려면, 태그가 필요함
  • rewrite_tag_filter 플러그인을 통과하지 않은 데이터들은 1개의 <match> 태그에 라우팅되면 그 다음 태그들에게 전파되지 않음
  • 이러한 이유로 forwarder에서 mysql bulk insert 담당 <match> 태그들을 위한 태깅을 하여 전송 시, 모든 <match> 태그안에 s3 플러그인 또한 구현해주어 중복 코드가 매우 많아지게 됨.
  • 그래서 일단 모든 데이터들을 마지막 <match> 태그에서 받아 s3에 저장하고, rewrite_tag_filter로 다시 태깅하여 라우팅 시킴
  • 이렇게하면 forwarder -> aggregator -> s3 저장 -> 다시 라우팅 -> 적절한 db 입력용 match 태그로 라우팅
  • 위의 과정을 거쳐 원하는 기능 구현 및 중복 코드의 최소화를 모두 만족하게 됨

 

Dockerfile

위 config 파일을 사용하여, aggregator를 도커 컨테이너로 생성하는 dockerfile도 설명한다.

FROM fluent/fluentd:v1.14.6-debian-1.0

USER root

# fluent-plugin-mysql 사용을 위한 유틸리티 설치
RUN apt-get update -y
RUN apt-get install -f -y ubuntu-dev-tools gcc 
RUN apt-get install -f -y default-libmysqlclient-dev

# 추가 플러그인 설치
RUN gem install fluent-plugin-s3
RUN gem install fluent-plugin-mysql 
RUN fluent-gem install fluent-plugin-rewrite-tag-filter

COPY ./etc /fluentd/etc

fluent-plugin-mysql 사용을 위한 유틸리티 설치

bulk insert를 위한 fluent-plugin-mysql 플러그인을 사용하기 위하여 ubuntu-dev-tools, gcc, default-libmysqlclient-dev 유틸리티들을 설치해야 한다.

이때,  

dpkg: dependency problems prevent configuration of libpaper-utils: libpaper-utils depends on libpaper1; however: Package libpaper1:amd64 is not configured yet. dpkg: error processing package libpaper-utils (--configure): dependency problems - leaving unconfigured
이 에러 메세지와 함께 설치가 실패 할 수 있는데, 도커 버전을 업데이트 해주면 되는 이슈이다.
 

추가 플러그인 설치

config에서 사용할 s3, mysql_bulk 등 공식 플러그인이 아닌 친구들은 gem에 올라와있으므로, gem을 통해 설치해주고

 

forwarder에서 했던 것처럼, rewrite_tag_filter 플러그인은 공식이기때문에 fluent-gem을 이용해 설치해주면 된다.

 

 

마지막으로 config 파일을 복사해준다.


마무리

이렇게 데이터를 bulk insert를 하기 위하여 fluentd를 구성을 마무리한다.