오늘은 elastic stack(과거 ELK stack)과 관련한, 그 중에서도 filebeat와 logstash에 대한 사항을 얘기하려고 한다. filebeat와 logstash는 ELK의 컴포넌트 중 raw data를 퍼다 날라주는 shipping layer 역할을 한다. 아래 그림이 logstash의 역할을 잘 설명하고 있다.

logstash, part of elastic stack (ELK stack)logstash infographic from elastic.co

elastic 회사의 공식 문서를 통해서 filebeat - logstash - elasticsearch - kibana로 이어지는 거의 실시간 로그 분석 시스템인 elastic stack을 체험해 볼 수 있을 것이다. 개인적으로 이 공식 문서 때문에 열 받은 적이 꽤 있기 때문에... 나중에 시간이 된다면 꼭 한 번 직접 정리를 하고 싶지만, 오늘은 간단히 filebeat와 logstash 사이의 여러 서로 다른 input들을 다루는 법을 정리하겠다. 따라서 여기서는 elastic stack에 대한 기본적인 이해가 있다고 가정하고 시작한다. 최신 버전인 5.1 버전 기준이다.

기본 설정: input 하나를 퍼나를 때

filebeat의 설정 파일인 filebeat.yml의 가장 기본적인 내용은 다음과 같을 것이다.


filebeat.prospectors:
    - input_type: log
        paths:
            - /path/to/file/mylogfile.log 
output.logstash:
    hosts: [ "localhost:5044" ]

또한 logstash의 개별 설정 파일 my-pipeline.conf의 내용은 다음과 같다.


input {
    beats {
        port => "5044"
    }
}
filter {
    # YOUR CUSTOM FILTERS ...
}
output {
    stdout { codec => rubydebug }
    elasticsearch {
        hosts => [ "localhost:9200" ]
    }
}

이렇게 설정하고 filebeat와 logstash를 가동시키자. 그러면 filebeat는 /path/to/file/mylogfile.log 파일을 지켜보면서 매 시간마다 (예를 들면 30초 마다) 파일이 업데이트된 줄을 감지하고 이를 logstash에게 5044포트로 계속 전달한다. 로그 파일이 박동(beat)하는 것을 감지해서 전달하는 것이다. 그리고 logstash는 5044포트를 계속 들으면서 filebeat가 보내주는 로그 내용들을 받는 것이다. 그 후에 logstash는 filter 부분에 설정한 만큼 로그를 분해(parse)해서 (stdout 설정을 통해) 터미널에 직접 보여주거나 elasticsearch에 index 시킴으로 자신의 할 일을 다하는 것이다.

고급 설정: 여러 input을 퍼나를 때

뒤늦게 밝히는 것인데, mylogfile.log는 Apache HTTP 서버의 로그 파일이었다. 근데 또 다른 로그를 elastic stack에 집어넣고 싶어졌다. 그 로그는 nginx 등의 다른 웹서버 로그일 수도 있고, DB 로그일 수도, 시스템 로그일 수도, 그냥 이상한 로그일 수도 있다. 우리가 원하는 바를 이루기 위해서 filebeat 하나를 새로 설치할 필요 없이 filebeat와 logstash 설정을 변경해서 type을 구분해주면 된다.

먼저 filebeat의 설정 파일인 filebeat.yml을 다음과 같이 변경한다.


filebeat.prospectors:
    - input_type: log
        path:
            - /path/to/apache/access.log
        document_type: apache
    - input_type: log
        path:
            - /path/to/db/mydb.log
        document_type: postgres
output.logstash:
    hosts: [ "localhost:5044" ]

바뀐 점은? filebeat.prospector를 하나 더 추가한 것이다. - 기호를 구분으로 여러 prospector 설정을 할 수 있다. 또 한 가지 중요한 점은 document_type를 설정한 것이다. 여기서 설정한 document_type는 logstash에서 [type] 변수로 활용할 수 있다. 이제 logstash 설정 파일 my-pipeline.conf을 바꿔보자.


input {
    beats {
        port => "5044"
    }
}
filter {
    if [type] == "apache" {
        # YOUR CUSTOM FILTERS FOR APACHE LOG ...
    }
    else if [type] == "postgres" {
        # YOUR CUSTOM FILTERS FOR POSTGRESQL LOG ...
    }
}
output {
    if [type] == "apache" {
        # YOUR CUSTOM OUTPUT FOR APACHE LOG ...
    }
    else if [type] == "postgres" {
        # YOUR CUSTOM OUTPUT FOR POSTGRESQL LOG ...
    }
}

filebeat가 지정한 document_type을 logstash에서는 [type] 변수로 이어받게 된다. 하나의 filebeat가 두 가지 document_type를 가진 로그 내용을 주도록 설정해 놨으니까 logstash의 input은 filebeat 하나인 것은 변함 없다. 그 이후의 filteroutput 부분에서 filebeat가 지정한 type 별로 다른 동작을 설정한 것이다.

실제로 원하는 output이 모두 들어가는 지 확인해보자. 원하는 대로 되지 않았다면, 공식 문서 등을 살펴 보면서 차근차근 되짚어보자... ㅎㅎ 빠팅


참조 링크

filebeat - logstash 공식 문서
https://www.elastic.co/guide/en/logstash/current/index.html

stackoverflow 만세
http://stackoverflow.com/questions/18330541/how-to-handle-multiple-heterogeneous-inputs-with-logstash
http://stackoverflow.com/questions/37684167/filebeat-and-logstash-data-in-multiple-different-formats