이야기박스
Logstash를 활용하여 rsyslog를 받아보자 본문
개요
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년 전에 기술조사 & 테스트 한 것을 이제야 옮겨오게 되네요. 종종 이렇게 밀린 포스팅을 정리할 겸 가지고 오도록 하겠습니다.
'Computer & Data > Big Data' 카테고리의 다른 글
Streaming 비교, Spark Streaming - Flink Streaming (0) | 2022.03.24 |
---|---|
Hive 및 Metastore 버전간 호환성 체크 (2.3.2, 3.1.2) (0) | 2022.03.20 |
Hadoop 시리즈. Hive metastore 2버전 설치 (0) | 2022.01.10 |
Hadoop 시리즈. Hive metastore 3버전 설치 (0) | 2022.01.10 |
Hadoop 시리즈. Spark 구성해보기 (0) | 2021.09.26 |