이야기박스

Logstash를 활용하여 rsyslog를 받아보자 본문

Computer & Data/Big Data

Logstash를 활용하여 rsyslog를 받아보자

박스님 2022. 3. 9. 20:24
반응형

개요

syslog를 json 형태의 구조화하고 이를 Elastic stack을 활용하여 받아보는 내용을 다루어 보려고 합니다. 

machine --(rsyslog)--> Nginx --> Logstash ---> Kafka

rsyslog는 TCP 포트를 활용하여 받을 예정입니다.

 

 

Logstash 설치

# get deb pkg
wget https://artifacts.elastic.co/downloads/logstash/logstash-7.11.2-amd64.deb

# install
sudo dpkg -i logstash-7.11.2-amd64.deb

 

 

- /etc/logstash/logstash.yml

queue.type: persisted
queue.max_bytes: 20gb
path.queue: /data3/logstash-logs

pipeline.ordered: auto
path.logs: /var/log/logstash
path.data: /var/lib/logstash

 

- /etc/logstash/jvm.options

... 가장 아래 라인에 아래 추가 
-Djava.net.preferIPv4Stack=true

 

- /etc/logstash/conf.d/rsyslog.conf

TCP만 열어주려고 했었는데, 테스트도 해볼겸 HTTP도 함께 열어주었습니다.

input {
  http{
        host => "0.0.0.0"
        port => 18080
        codec => "json"
        threads => 8
        ssl => false
  }

  tcp {
    port => 10514
    codec => "json"
    type => "rsyslog"
  }
}

output {
  kafka {
      bootstrap_servers => "story-kafka-dev01:9092,story-kafka-dev02:9092,story-kafka-dev03:9092"
      topic_id => "story_test2"
      codec => json
      acks => "1"
      batch_size => 500
      linger_ms => 100
      retries => 3
      request_timeout_ms => 5000
  }
}

 

# Logstash 테스트

HTTP

# Request
$ curl -XPOST -H "Content-Type: application/json" -H "Accept-Charset: utf-8" -H "Test-Ucl: uclog-header" -d '{"message":"tcp test", "service_id":"http-test"}' uc-log-kafka6.k9e.io:18080

# Response
{"message":"tcp test","headers":{"http_version":"HTTP/1.1","accept_charset":"utf-8","content_type":"application/json","request_method":"POST","http_host":"uc-log-kafka6.k9e.io:18080","http_accept":"*/*","http_user_agent":"curl/7.58.0","request_path":"/","test_uclog":"uclog-header","content_length":"48"},"@version":"1","host":"10.181.4.20","@timestamp":"2021-04-21T07:17:46.600Z","service_id":"http-test"}

 

TCP

# Request
$ cat test.json
{"message":"test message", "service_id":"logstash-test"}
$ nc uc-log-kafka1.k9e.io 10514 < test.json

# Response
{"service_id":"logstash-test","message":"test message","port":53046,"@timestamp":"2021-04-21T07:21:39.229Z","host":"10.181.4.47","@version":"1","type":"rsyslog"}

 

 

Nginx 구성

nginx.conf 만 가볍게 공유합니다. logstash 1번 서버에 nginx를 생성하여서 포트를 조금 다르게 잡았습니다.

#user  deploy;
worker_processes  auto;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    upstream logstashHttp {
        server story-dev01:18080;
        server story-dev02:18080;
        server story-dev03:18080;
    }

    server {
        listen 0.0.0.0:18081;
        server_name logstashHttp;

        client_max_body_size 1m;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        location /api/uclog/send/log {
            proxy_pass http://logstashHttp;
        }
    }
}

stream {
    upstream logstashStream {
  least_conn;

        server story-dev01:10514;
        server story-dev02:10514;
        server story-dev03:10514;
    }

    server {
        listen 0.0.0.0:10515;
        proxy_pass logstashStream;
        proxy_timeout 5s;
    }
}

 

rsyslog 설정

# 테스트 서버

# test server ip
deploy@story-test01:/etc/logstash/conf.d$ hostname -I
10.202.120.58

 

# /etc/rsyslog.conf

10514 포트로 tcp 로그를 받을 예정이기 때문에 아래와 같이 수정합니다.

# provides TCP syslog reception
module(load="imtcp")
input(type="imtcp" port="10514")

 

# /etc/rsyslog.d/story.conf

아래와 같이 template을 이용하여 syslog를 json 형태로 구조화 시켜봅니다.

template(name="story-json" type="list") {
      constant(value="{")
      constant(value="\"@timestamp\":\"")     property(name="timereported" dateFormat="rfc3339")
      constant(value="\",\"@version\":\"1")
      constant(value="\",\"service_id\":\"rsyslog-test")
      constant(value="\",\"message\":\"")     property(name="msg" format="json")
      constant(value="\",\"sysloghost\":\"")  property(name="hostname")
      constant(value="\",\"severity\":\"")    property(name="syslogseverity-text")
      constant(value="\",\"facility\":\"")    property(name="syslogfacility-text")
      constant(value="\",\"programname\":\"") property(name="programname")
      constant(value="\",\"procid\":\"")      property(name="procid")
      constant(value="\"}\n")
}

#*.* @@10.202.120.58:8081;story-json
if not ($programname contains "logstash") and not ($programname contains "filebeat") then @@10.202.120.58:10514;story-json
& ~

 

테스트 중 해당 서버에 filebeat, logstash를 같이 생성했었는데, 해당 로그는 제외하고 받기 위하여 아래 조건문을 추가하였습니다. 아래처럼 조건문을 활용하여 로그를 보다 다양하게 목적지로 보낼 수 있습니다.

if not ($programname contains "logstash") and not ($programname contains "filebeat") then

 

IP 앞에 붙는 골뱅이의 `@`는 UDP, `@@`는 TCP 프로토콜을 사용한다는 표시입니다. 그리고 위에 정의해두었던 template을 `;` 뒤에 기입해줍니다.

# template
{protocol}{address};{rsyslog-template}

# example
@@10.202.120.58:10514;story-json

 

서비스 실행

당연히 아래와 같이 모든 서비스를 재실행해 주어야 원하는대로 동작하게 됩니다.

# logstash
sudo service logstash start

# nginx
sudo service nginx restart

# rsyslog
sudo service rsyslog restart

 

후기

1년 전에 기술조사 & 테스트 한 것을 이제야 옮겨오게 되네요. 종종 이렇게 밀린 포스팅을 정리할 겸 가지고 오도록 하겠습니다. 

반응형