본문 바로가기
WIKI 기술 지식 베이스

Logstash

원문 보기 위키 갱신

출처: 문서

본문

Logstash

Logstash는 실시간 이벤트 처리 엔진이에요. OpenSearch, Beats, OpenSearch Dashboards를 포함하는 OpenSearch 스택의 일부예요.

다양한 소스에서 Logstash로 이벤트를 보낼 수 있어요. Logstash는 이벤트를 처리해서 하나 이상의 목적지로 보내요. 예를 들어 웹 서버의 액세스 로그를 Logstash로 보낼 수 있어요. Logstash는 각 로그에서 유용한 정보를 추출해서 OpenSearch 같은 목적지로 보내요.

Logstash로 이벤트를 보내면 이벤트 처리를 앱에서 분리할 수 있어요. 앱은 이벤트를 Logstash로 보내기만 하면 되고, 그 이후에 이벤트에 어떤 일이 일어나는지는 전혀 알 필요가 없어요.

오픈 소스 커뮤니티는 원래 로그 데이터를 처리하기 위해 Logstash를 만들었지만, 이제는 XML이나 JSON 형식의 이벤트를 포함해 어떤 유형의 이벤트든 처리할 수 있어요.

파이프라인 구조

Logstash는 입력, 필터, 출력이라는 세 단계로 이루어진 파이프라인을 구성하는 방식으로 동작해요.

각 단계는 하나 이상의 플러그인을 사용해요. Logstash에는 200개가 넘는 내장 플러그인이 있어서 필요한 걸 찾을 가능성이 높아요. 내장 플러그인 외에도 커뮤니티에서 제공하는 플러그인을 사용하거나 직접 작성할 수도 있어요.

파이프라인의 구조는 다음과 같아요:

input {
  input_plugin => {}
}

filter {
  filter_plugin => {}
}

output {
  output_plugin => {}
}

여기서:

  • input은 여러 소스에서 로그 같은 이벤트를 동시에 받아요. Logstash는 TCP/UDP, 파일, syslog, Microsoft Windows EventLogs, stdin, HTTP 등을 위한 다양한 입력 플러그인을 지원해요. 이벤트를 수집할 때는 Beats라는 오픈 소스 입력 도구 모음을 사용할 수도 있어요. 입력 플러그인은 이벤트를 필터로 보내요.
  • filter는 이벤트를 여러 방식으로 파싱하고 보강해요. Logstash에는 이벤트를 수정해서 출력으로 전달하는 필터 플러그인이 많이 있어요. 예를 들어 grok 필터는 비정형 이벤트를 필드로 파싱하고, mutate 필터는 필드를 변경해요. 필터는 순차적으로 실행돼요.
  • output은 필터링된 이벤트를 하나 이상의 목적지로 보내요. Logstash는 OpenSearch, TCP/UDP, 이메일, 파일, stdout, HTTP, Nagios 같은 목적지를 위한 다양한 출력 플러그인을 지원해요.

입력 단계와 출력 단계 모두 이벤트가 파이프라인에 들어가거나 나올 때 이를 처리하는 코덱을 지원해요. 널리 쓰이는 코덱으로는 json과 multiline이 있어요. json 코덱은 JSON 형식의 데이터를 처리하고, multiline 코덱은 여러 줄 이벤트를 한 줄로 합쳐요.

파이프라인 설정 안에 조건문을 작성해서 특정 조건이 충족될 때 특정 동작을 수행하게 할 수도 있어요.

Logstash 설치

OpenSearch에서 Logstash를 설치하려면 다음 단계에서 설명하는 대로 먼저 클러스터에 Logstash를 설치하고, 그다음 OpenSearch Logstash 플러그인을 설치하세요.

Tarball

Java Development Kit (JDK) 버전 8 또는 11이 설치되어 있는지 확인하세요.

  1. Logstash 다운로드에서 Logstash tarball을 다운로드하세요.

  2. 터미널에서 다운로드한 폴더로 이동해서 파일의 압축을 풀어요. 사용 중인 Logstash 버전과 플랫폼이 다운로드한 것과 일치하는지 확인하세요:

    tar -zxvf logstash-8.8.2-linux-x86_64.tar.gz
    

    {% include copy.html %}

  3. logstash-8.8.2 디렉터리로 이동하세요.

  4. 다음 명령어로 플러그인을 설치하세요:

    bin/logstash-plugin install logstash-output-opensearch
    

    {% include copy.html %}

    다음과 같은 출력이 표시돼요:

    Validating logstash-output-opensearch
    Resolving mixin dependencies
    Updating mixin dependencies logstash-mixin-ecs_compatibility_support
    Bundler attempted to update logstash-mixin-ecs_compatibility_support but its version stayed the same
    Installing logstash-output-opensearch
    Installation successful
    

파이프라인 설정은 config 디렉터리에 추가할 수 있어요. Logstash는 플러그인의 데이터를 data 디렉터리에 저장해요. bin 디렉터리에는 Logstash를 시작하고 플러그인을 관리하는 바이너리가 들어 있어요.

Docker

커스텀 Dockerfile로 Logstash 이미지를 빌드하거나 표준 Logstash 이미지를 사용할 수 있어요.

옵션 1: 커스텀 Dockerfile 사용 (권장)

  1. 필요한 OpenSearch 플러그인이 포함된 Logstash 이미지를 빌드하기 위한 커스텀 Dockerfile을 만드세요:

    FROM logstash:<LATEST_VERSION>
    RUN bin/logstash-plugin install logstash-output-opensearch
    RUN bin/logstash-plugin install logstash-input-opensearch
    

    {% include copy.html %}

  2. 이미지를 빌드하세요:

    docker build -t logstash-with-opensearch-plugins .
    

    {% include copy.html %}

옵션 2: 표준 Logstash 이미지 사용

  1. Logstash 다운로드에 나온 대로 최신 Logstash 이미지를 pull하세요.

    docker pull docker.elastic.co/logstash/logstash:8.8.2
    

    {% include copy.html %}

  2. Docker 네트워크를 만드세요:

    docker network create test
    

    {% include copy.html %}

  3. 이 네트워크로 OpenSearch를 시작하세요:

    docker run -p 9200:9200 -p 9600:9600 --name opensearch --net test -e "discovery.type=single-node" opensearchproject/opensearch:1.2.0
    

    {% include copy.html %}

  4. Logstash를 시작하세요:

    docker run -it --rm --name logstash --net test opensearchproject/logstash-oss-with-opensearch-output-plugin:7.16.2 -e 'input { stdin { } } output {
      opensearch {
        hosts => ["https://opensearch:9200"]
        index => "opensearch-logstash-docker-%{+YYYY.MM.dd}"
        user => "admin"
        password => "admin"
        ssl => true
        ssl_certificate_verification => false
      }
    }'
    

    {% include copy.html %}

터미널에서 텍스트 처리하기

stdin에서 이벤트를 듣고 stdout으로 이벤트를 출력하는 파이프라인을 정의할 수 있어요. stdin과 stdout은 Logstash를 실행 중인 터미널을 가리켜요.

터미널에 텍스트를 입력하고 출력에서 이벤트 데이터를 확인하려면:

  1. -e 인자를 사용해서 파이프라인 설정을 Logstash 바이너리에 직접 전달해요. 이 경우 stdin이 입력 플러그인이고 stdout이 출력 플러그인이에요:

    bin/logstash -e "input { stdin { } } output { stdout { } }"
    

    {% include copy.html %}

    더 자세한 출력을 보려면 —debug 플래그를 추가하세요.

  2. 터미널에 "hello world"를 입력하세요. Logstash가 텍스트를 처리해서 터미널로 다시 출력해요:

    {
     "message" => "hello world",
     "host" => "a483e711a548.ant.amazon.com",
     "@timestamp" => 2021-05-30T05:15:56.816Z,
     "@version" => "1"
    }
    

    message 필드에는 원본 입력이 들어 있어요. host 필드는 Logstash를 로컬에서 실행하지 않을 때 IP 주소예요. @timestamp는 이벤트가 처리된 날짜와 시간을 보여줘요. Logstash는 내부 처리를 위해 @version 필드를 사용해요.

  3. Ctrl + C를 눌러서 Logstash를 종료하세요.

문제 해결

이미 실행 중인 Logstash 프로세스가 있으면 오류가 발생해요. 이 문제를 해결하려면:

  1. data 디렉터리에서 .lock 파일을 삭제하세요:

    cd data
    rm -rf .lock
    

    {% include copy.html %}

  2. Logstash를 다시 시작하세요.

JSON 또는 HTTP 입력을 처리해서 파일로 출력하기

JSON 요청을 처리하는 파이프라인을 정의하려면:

  1. 원하는 텍스트 편집기로 config/pipeline.conf 파일을 열어요. 파이프라인 설정 파일은 어떤 확장자로 만들어도 되는데, .conf 확장자가 Logstash의 관례예요. 입력으로 JSON을 받도록 json 코덱을 추가하고, 처리된 이벤트를 .txt 파일로 출력하도록 file 플러그인을 추가하세요:

    input {
      stdin {
        codec => json
      }
    }
    output {
      file {
        path => "output.txt"
      }
    }
    

    {% include copy.html %}

    파일에서 입력을 처리하려면 events-data 디렉터리에 입력 파일을 추가하고, 그 경로를 입력의 file 플러그인에 전달하세요:

    input {
      file {
        path => "events-data/input_data.log"
      }
    }
    

    {% include copy.html %}

  2. Logstash를 시작하세요:

    bin/logstash -f config/pipeline.conf
    

    {% include copy.html %}

    config/pipeline.conf는 pipeline.conf 파일의 상대 경로예요. 절대 경로를 사용할 수도 있어요.

  3. 터미널에 JSON 객체를 입력하세요:

    { "amount": 10, "quantity": 2}
    

    {% include copy.html %}

    파이프라인은 한 줄 입력만 처리해요. 여러 줄에 걸친 JSON을 붙여 넣으면 오류가 발생해요.

  4. JSON 객체의 필드가 output.txt 파일에 추가됐는지 확인하세요:

    cat output.txt
    

    {% include copy.html %}

    {
      "@version": "1",
      "@timestamp": "2021-05-30T05:52:52.421Z",
      "host": "a483e711a548.ant.amazon.com",
      "amount": 10,
      "quantity": 2
    }
    

    입력으로 잘못된 JSON을 넣으면 JSON 파싱 오류가 표시돼요. Logstash는 잘못된 JSON을 버리지 않는데, 그걸로 뭔가를 하고 싶을 수도 있기 때문이에요. 예를 들어 이메일을 발송하거나 Slack 채널에 알림을 보낼 수 있어요.

HTTP 요청을 처리하는 파이프라인을 정의하려면:

  1. http 플러그인을 사용해서 HTTP를 통해 Logstash로 이벤트를 보내세요:

    input {
      http {
        host => "127.0.0.1"
        port => 8080
      }
    }
    
    output {
      file {
        path => "output.txt"
      }
    }
    

    {% include copy.html %}

    옵션을 지정하지 않으면 http 플러그인은 localhost에 바인딩되고 8080 포트에서 대기해요.

  2. Logstash를 시작하세요:

    bin/logstash -f config/pipeline.conf
    

    {% include copy.html %}

  3. Postman을 사용해서 HTTP 요청을 보내세요. Content-Type을 application/json 값을 가진 HTTP 헤더로 설정하세요:

    PUT 127.0.0.1:8080
    {
      "amount": 10,
      "quantity": 2
    }
    

    {% include copy.html %}

    또는 curl 명령어를 사용할 수도 있어요:

    curl -XPUT -H "Content-Type: application/json" -d ' {"amount": 7, "quantity": 3 }' http://localhost:8080 (http://localhost:8080/)
    

    {% include copy.html %}

    입력에 json 플러그인을 추가하지 않았는데도 파이프라인 설정이 동작해요. HTTP 플러그인이 Content-Type 헤더를 기준으로 알맞은 코덱을 자동으로 적용하기 때문이에요. 값을 applications/json으로 지정하면 Logstash가 요청 본문을 JSON으로 파싱해요.

    headers 필드에는 Logstash가 받은 HTTP 헤더가 들어 있어요:

    {
      "host": "127.0.0.1",
      "quantity": "3",
      "amount": 10,
      "@timestamp": "2021-05-30T06:05:48.135Z",
      "headers": {
        "http_version": "HTTP/1.1",
        "request_method": "PUT",
        "http_user_agent": "PostmanRuntime/7.26.8",
        "connection": "keep-alive",
        "postman_token": "c6cd29cf-1b37-4420-8db3-9faec66b9e7e",
        "http_host": "127.0.0.1:8080",
        "cache_control": "no-cache",
        "request_path": "/",
        "content_type": "application/json",
        "http_accept": "*/*",
        "content_length": "41",
        "accept_encoding": "gzip, deflate, br"
      },
    "@version": "1"
    }
    

파이프라인 설정 자동 리로드하기

Logstash가 파이프라인 설정 파일이나 입력 로그 파일의 변경 사항을 감지해서 설정을 자동으로 리로드하도록 구성할 수 있어요.

stdin 플러그인은 자동 리로드를 지원하지 않아요. {: .note }

  1. 입력 플러그인에 값이 beginning인 start_position 옵션을 추가하세요:

    input {
      file {
        path => "/Users/<user>/Desktop/logstash7-12.1/events-data/input_file.log"
        start_position => "beginning"
      }
    }
    

    {% include copy.html %}

    Logstash는 입력 파일에 새로 추가된 이벤트만 처리하고, 재시작할 때 같은 이벤트를 두 번 처리하지 않도록 이미 처리한 이벤트는 무시해요.

    Logstash는 진행 상황을 sinceDB 파일이라고 불리는 파일에 기록해요. Logstash는 변경 사항을 감시하는 각 파일마다 sinceDB 파일을 하나씩 만들어요.

  2. sinceDB 파일을 열어서 입력 파일이 얼마나 처리됐는지 확인하세요:

    cd data/plugins/inputs/file/
    ls -al
    
    -rw-r--r--  1 user  staff   0 Jun 13 10:50 .sincedb_9e484f2a9e6c0d1bdfe6f23ac107ffc5
    
    cat .sincedb_9e484f2a9e6c0d1bdfe6f23ac107ffc5
    
    51575938 1 4 7727
    

    {% include copy.html %}

    sinceDB 파일의 마지막 숫자(7727)는 마지막으로 처리된 것으로 확인된 이벤트의 바이트 오프셋이에요.

  3. 입력 파일을 처음부터 처리하려면 sinceDB 파일을 삭제하세요:

    rm .sincedb_*
    

    {% include copy.html %}

  4. —-config.reload.automatic 인자를 붙여서 Logstash를 시작하세요:

    bin/logstash -f config/pipeline.conf --config.reload.automatic
    

    {% include copy.html %}

    reload 옵션은 파이프라인 설정 파일 끝에 새 줄을 추가했을 때만 리로드해요.

    샘플 출력:

    {
       "message" => "216.243.171.38 - - [20/Sep/2017:19:11:52 +0200] \"GET /products/view/123 HTTP/1.1\" 200 12798 \"https://codingexplained.com/products\" \"Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)\"",
       "@version" => "1",
          "host" => "a483e711a548.ant.amazon.com",
          "path" => "/Users/kumarjao/Desktop/odfe1/logstash-7.12.1/events-data/input_file.log",
       "@timestamp" => 2021-06-13T18:03:30.423Z
    }
    {
       "message" => "91.59.108.75 - - [20/Sep/2017:20:11:43 +0200] \"GET /js/main.js HTTP/1.1\" 200 588 \"https://codingexplained.com/products/view/863\" \"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0\"",
      "@version" => "1",
          "host" => "a483e711a548.ant.amazon.com",
          "path" => "/Users/kumarjao/Desktop/odfe1/logstash-7.12.1/events-data/input_file.log",
    "@timestamp" => 2021-06-13T18:03:30.424Z
    }
    
  5. 입력 파일에 새 줄을 추가하세요.

    • Logstash가 변경 사항을 즉시 감지하고 새 줄을 이벤트로 처리해요.
  6. pipeline.conf 파일을 변경하세요.

    • Logstash가 변경 사항을 즉시 감지하고 수정된 파이프라인을 리로드해요.

더 알아보기 (Learn more)