EFK를 정리하자 2일차 - Fluentd Configuration1

0

EFK

목록 보기
2/8

Configuration

fluentd의 configuration file은 fluentd의 동작 전부를 결정하는 아주 중요한 요소이다.
1. input source와 output destination을 무엇으로 쓸 것인지(plugin) 결정하고
2. input과 output plugin에 대한 parameter를 결정하며
3. 이 configuration을 기반으로 fluentd가 동작한다.
즉, 어느 source에서 input event data를 받아서 어떤 곳에 output을 전달해줄 지 결정한다는 것이다.

event cycle을 설명하기 위해서 간단한 example을 알아볼 것인데, in_http plugin을 만들어 http요청을 받아 log data를 가져오고, out_stdout plugin을 만들어 이 data를 stdout에 뿌려주도록 할 것이다. 이 두 plguin은 basic.conf 파일 하나에 적어주면 된다.

  • basic.conf
<source>
  @type http
  port 8888
  bind 0.0.0.0
</source>

<match test.cycle>
  @type stdout
</match>

<source>부분이 바로 in_http plugin에 해당하는 부분으로 @type으로 http를 가지겠다는 것이다. 또한 port8888을 TCP로 열고, host는 0.0.0.0(localhost)로 가져오겠다는 것이다.

<match test.cycle>부분이 out_stdout plugin에 해당하는 부분으로 source로부터 들어오는 log data의 tagtest.cycle이라면 stdout으로 보내겠다는 것이다.

이제 fleuntd container에 다음의 conf파일을 적용시켜보도록 하자.

docker run -p 8888:8888 -v ./conf:/fluentd/etc fluent/fluentd:edge-debian -c /fluentd/etc/basic.conf

잘 실행되었다면 8888 port로 http요청을 보내도록 하자. 이때 data를 써주면 fluentd에서 source로 받아 output으로 뽑아내줄 것이다. 단, 요청 시에는 반드시 test.cycle이라는 태그가 매칭되어야 하기 때문에 다음과 같이 요청해주어야 한다.

curl -i -X POST -d 'json={"action":"login","user":2}' http://localhost:8888/test.cycle

fluentd container에서는 다음의 로그가 찍혔을 것이다.

2023-10-20 08:46:57 +0000 [info]: #0 starting fluentd worker pid=16 ppid=7 worker=0
2023-10-20 08:46:57 +0000 [info]: #0 fluentd worker is now running worker=0
2023-10-20 08:47:10.748692079 +0000 test.cycle: {"action":"login","user":2}

우리가 만든 in_http plugin과 out_stdout plugin이 잘 적용된 것을 볼 수 있다. 이처럼 fluentd는 configuration file을 통해서, plugin을 설정할 수 있으며 plugin은 source와 output에 대해서 관여해 log event들을 어디서 받고 어디로 내보낼 지 결정해준다.

Event 구조

fluentd에서 다루는 data를 event라고 부른다. event는 3가지 구조로 이루어져 있다.

  1. tag: tag는 어디서부터 event가 왔는 지를 나타낸다. 따라서 하나의 식별자 역할을 하여 메시지 라우팅에 있어 사용된다.
  2. time: 나노초 단위로 event가 발생했을 때의 시간을 알려준다.
  3. record: JSON object로 실제 로그를 나타낸다.

즉, source로 부터 들어온 log를 record로 만들고, tag와 time이라는 특성을 붙여 event로 만드는 것이다. 또한, input plugin 설정을 통해서 여러 data source들에서 온 log를 fluent event로 만들어주는데, in_tail input plugin을 사용하면 text line으로부터 다음과 같은 events를 만들어준다.

다음의 아파치 로그를

192.168.0.1 - - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777

아래의 fluentd log로 만들어준다.

tag: apache.access         # set by configuration
time: 1362020400.000000000 # 28/Feb/2013:12:00:00 +0900
record: {"user":"-","method":"GET","code":200,"size":777,"host":"192.168.0.1","path":"/"}

Events 처리

Setup이 정의되면 Route Engine이 서로 다른 input data에 대해서 몇 가지를 rule들을 포함한다. 내부적으로 Event는 일련의 절차를 걸쳐 정제되는 것이다.

Setup으로 Filter를 사용하여 어떻게 Events cycle이 변경되는 지 확인해보자. Filter는 말 그대로 rule에 따라서 event를 pass할지 거절할 지를 결정하는 것이다. 다음은 Filter정의를 추가한 configuration 파일이다.

  • basic-filter.conf
<source>
  @type http
  port 8888
  bind 0.0.0.0
</source>

<filter test.cycle>
  @type grep
  <exclude>
    key action
    pattern ^logout$
  </exclude>
</filter>

<match test.cycle>
  @type stdout
</match>

위의 configuration은 source인 http로부터 event를 받는데, test.cycle요청의 경우에 filter를 통과한다. filtergrep으로 keyaction인데 value같이 pattern에 일치하면 제외시키는 것이다. 다음의 그림을 참고하도록 하자.

|----http----|    |-------grep------|     |------stdout-----|  
|Tag: null   |----|Match: test.cycle|-----|Match: test.cycle|  
|------------|    |-----------------|     |-----------------|     

먼저 basic-filter.conf를 적용한 fluentd container를 배포하도록 하자.

docker run -p 8888:8888 -v ./conf:/fluentd/etc fluent/fluentd:edge-debian -c /fluentd/etc/basic-filter.conf

다음의 요청을 보내보도록 하자.

curl -i -X POST -d 'json={"action":"login","user":2}' http://localhost:8888/test.cycle

tagtest.cycle이지만 actionlogin이라 filter되지 않는다. fluentd container의 log에 다음과 같이 나온다.

2023-10-23 02:04:04.669503595 +0000 test.cycle: {"action":"login","user":2}

다음의 요청을 보내보도록 하자.

curl -i -X POST -d 'json={"action":"logout","user":2}' http://localhost:8888/test.cycle

tagtest.cycle이고, actionlogout이며 이기 때문에 filter의 rule에 일치한다. 따라서 fluentd container output에 다음의 event는 필터링된다.

위에서 보았듯이 Events는 step-by-step 단계를 순서대로 따라가 정제된다. 그러나 점점 configuration이 복잡해지고, 다양한 source의 event들이 들어오기 시작하면서 reader입장에서 fluentd 설정이 너무 복잡해지는데, 이러한 문제를 해결하고자 Labels라는 것이 도입되었다.

Labels

Labels는 configuration file 복잡도를 해결하고 새로운 Routing section을 도입하는데, 이는 configuration의 top-bottom 순서대로 event가 흐르는 것이 아니라 linked 레페런스와 같이 동작하도록 만드는 것이다.

다음의 setup을 보도록 하자.

  • basic-filter-label.conf
<source>
  @type http
  bind 0.0.0.0
  port 8888
  @label @STAGING
</source>

<filter test.cycle>
  @type grep
  <exclude>
    key action
    pattern ^login$
  </exclude>
</filter>

<label @STAGING>
  <filter test.cycle>
    @type grep
    <exclude>
      key action
      pattern ^logout$
    </exclude>
  </filter>

  <match test.cycle>
    @type stdout
  </match>
</label>

위의 예제를 잘보면 <source>@label @STAGING이 있는 것을 볼 수 있다. 이 <source>로 부터 들어온 event들은 <fitler test.cycle>을 거치는 것이 아니라, <label @STAGING>으로 바로 거친다. 따라서, 현재는 <fitler test.cycle>를 거치는 경우가 없다.

filter내용이 같아서 결과에는 큰 변화가 없지만, 다양한 source로부터 event들이 들어올 때, 이들을 쉽게 라우팅해주기 좋다.

Buffers

지금까지 output plugin으로 stdout만 사용하였다. 그러나 stdout은 non-buffer이므로 실제 production환경에서는 buffered 모드인 forware, mongodb, s3 등을 사용한다. buffered output plugin을 사용하는 경우에 event들이 buffer에 차오르기 시작하고, flush조건을 만족하면 내용물들을 destination으로 전달하여 buffer를 비워낸다. 따라서, buffered output을 사용하면 stdout과 같은 non-buffered output처럼 즉각적으로 output을 확인할 필요가 사라진다.

0개의 댓글