개발하는 두부

CentOS 환경에 Elastic Stack 구축하기

by 뚜부니

00. 실습 환경

Apache 2.0 License 내에서 사용할 수 있는 기능만 포함된 OSS 버전을 활용하여 실습하였습니다.

  • CentOS 7.9
  • Elasticsearch OSS 7.10.2
  • Logstash OSS 7.10.2
  • Kibana OSS 7.10.2
  • Filebeat OSS 7.10.2
  • Java 11

여기서는 공식 홈페이지에서 다운로드 받은 후 CentOS 서버로 파일을 옮겨 설치하는 방식으로 환경을 구축하였으며,
다른 방식으로 환경 구축을 하고 싶다면 공식 문서를 참고하시길 바랍니다.

01. Elasticsearch 환경 구축

Elasticsearch 설치

공식 홈페이지에서
Elasticsearch RPM 버전을 다운로드 받은 후, CentOS 서버에 업로드합니다.

서버에 업로드가 완료되면, 아래 명령어를 통해 elasticsearch를 설치합니다.

sudo rpm --install elasticsearch-oss-7.10.2-x86_64.rpm

설치가 완료되면, sudo service elasticsearch status 명령어를 입력합니다.

명령어를 입력했을 때, 다음과 같은 문구가 화면에 표출되면 정상 설치된 것입니다.

● elasticsearch.service - Elasticsearch
   Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: https://www.elastic.co

Elasticsearch 실행 및 종료

Elasticsearch를 rpm으로 설치하였다면, 다음 명령어를 통해 실행과 종료를 할 수 있습니다.

# 실행
sudo -i service elasticsearch start
# 종료
sudo -i service elasticsearch stop

Elasticsearch를 실행 후 sudo service elasticsearch status 명령어로 status를 확인하면, 다음과 같은 문구를 확인할 수 있습니다.

● elasticsearch.service - Elasticsearch
   Loaded: loaded (/usr/lib/systemd/system/elasticsearch.service; disabled; vendor preset: disabled)
   Active: active (running) since Mon 2023-05-08 17:52:01 KST; 3s ago
     Docs: https://www.elastic.co
 Main PID: 14541 (java)
   CGroup: /system.slice/elasticsearch.service
           └─14541 /usr/share/elasticsearch/jdk/bin/java -Xshare:auto -Des.networkaddress.cache.ttl=60 -Des.networkaddress.cache.negative.ttl=1...

May 08 17:51:53 buildagent002 systemd[1]: Starting Elasticsearch...
May 08 17:52:01 buildagent002 systemd[1]: Started Elasticsearch.

실행된 Elasticsearch에서 정상 응답이 오는지 확인하고 싶다면, 아래 명령어를 입력하면 됩니다.

curl -X GET localhost:9200?pretty

그러면 다음과 유사한 형태의 JSON 응답을 확인할 수 있습니다.

{
  "name" : "buildagent002",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "SO3bsr3CSOC25BJzgpk9Qw",
  "version" : {
    "number" : "7.10.2",
    "build_flavor" : "oss",
    "build_type" : "rpm",
    "build_hash" : "747e1cc71def077253878a59143c1f785afa92b9",
    "build_date" : "2021-01-13T00:42:12.435326Z",
    "build_snapshot" : false,
    "lucene_version" : "8.7.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

02. Kibana 환경 구축

Kibana 설치

Elaticsearch와 마찬가지로 공식 홈페이지에서 Kibana RPM 버전을 다운로드 받은 후, CentOS 서버에 업로드합니다.

서버에 업로드가 완료되면, 아래 명령어를 통해 kibana를 설치합니다.

sudo rpm --install kibana-oss-7.10.2-x86_64.rpm

Kibana 설정하기

현재 상태로 실행하면 서버에서 실행한 Kibana 대시보드를 열어볼 수 없으므로,
Kibana 설정을 변경하도록 하겠습니다.

먼저, kibana 설정 파일을 열어줍니다.

sudo vi /etc/kibana/kibana.yml

우선, 서버 외부에서도 접속할 수 있도록 host를 변경합니다.

# ...

# Specifies the address to which the Kibana server will bind. IP addresses and host names are both valid values.
# The default is 'localhost', which usually means remote machines will not be able to connect.
# To allow connections from remote users, set this parameter to a non-loopback address.
#server.host: "localhost"
server.host: "0.0.0.0"

# ...

그다음, elasticsearch를 연결해 줍니다. 현재 elasticsearch와 kibana는 동일 서버에 있으므로 localhost로 하였습니다.

# The URLs of the Elasticsearch instances to use for all your queries.
elasticsearch.hosts: ["http://localhost:9200"]

Kibana 실행 및 종료

elasticsearch와 유사한 형식으로 kibana를 실행 및 종료를 할 수 있습니다.

# 실행
sudo -i service kibana start
# 종료
sudo -i service kibana stop

kibana 실행 후 {서버 IP}:5601로 접속하면, 다음과 같이 kibana가 실행된 웹 페이지를 볼 수 있습니다. 예를 들어, 서버가 127.2.3.4라고하면, 127.2.3.4:5601로 접속하면 됩니다.

image

03. Logstash 환경 구축

Logstash 설치

Logstash도 공식 홈페이지에서 RPM 버전을 다운로드한 후, CentOS 서버에 업로드하여 설치하도록 하겠습니다.

서버에 업로드가 완료되면, 아래 명령어를 통해 logstash를 설치합니다.

sudo rpm --install logstash-oss-7.10.2-x86_64.rpm

Logstash를 사용하려면 Java 설치가 필요합니다. 여기서는 Java 설치 방법에 대해서는 생략합니다. Java 설치 시, 공식 홈페이지의 서포트 매트릭스에서 logstash 버전에 따라 지원하는 Java 버전을 확인한 다음 설치하시길 바랍니다.

Logstash 설정

input.log 파일을 읽어와 output.log 파일에 쓰도록 설정해 보겠습니다. 이때, 다음과 같은 조건이 필요합니다.

  1. 읽을 파일과 파일이 위치하는 디렉터리에 대해 logstash가 읽고 실행할 수 있는 권한이 필요합니다.
  2. 쓸 파일과 파일이 위치하는 디렉터리에 대해 logstash가 쓸 수 있는 권한이 필요합니다.

조건에 따라 읽을 파일은 /var/log/testlog에 생성하고 쓸 파일은 /var/log/logstash에 생성하도록 하겠습니다.

먼저 input 파일을 생성합니다. vi 명령어를 통해 파일을 열고 난 다음 esc 클릭 후 :wq를 입력하면 생성됩니다.

vi /var/log/testlog/input.log

그리고 조건에 맞게 권한을 변경해 줍니다.

sudo chmod 777 /var/log/testlog/input.log

그다음, output 파일을 생성합니다.

vi /var/log/logstash/output.log

그리고 output 파일로 조건에 맞게 권한을 변경해 줍니다.

sudo chown logstash:logstash /var/log/logstash/*.log

이제 읽고 쓸 파일이 생성되었으니, logstash 설정을 추가해 줍시다!

sudo vi /etc/logstash/conf.d/test.conf

test를 위한 test.conf 파일을 열어서 아래 내용을 입력하고 저장합니다.

input {
    file {
        path => "/var/log/testlog/input.log"
        start_position => "beginning"
        sincedb_path => "/dev/null"
        ignore_older => 0
    }
}

output {
    file {
        path => "/var/log/logstash/output.log"
    }
}

output을 file이 아닌 elasticsearch로 설정하려면 다음과 유사한 방식으로 하면 됩니다.

output {
    elasticsearch{
        hosts => ["127.0.0.1:9200"]
        index => "test-%{+YYYY.MM.dd}"
    }
}

Logstash 실행 및 종료

logstash를 실행하는 방법은 elasticsearch와 kibana와 유사합니다.

# 실행
sudo -i service logstash start
# 종료
sudo -i service logstash stop

logstash를 실행한 다음 아래 명령어를 실행하면 실시간으로 쌓이는 log를 확인할 수 있습니다.

tail -f /var/log/logstash/logstash-plain.log

다음과 같이 로그가 뜨면 logstash 실행이 완료된 것입니다.

[2023-05-10T17:16:24,448][INFO ][logstash.runner          ] Starting Logstash {"logstash.version"=>"7.10.2", "jruby.version"=>"jruby 9.2.13.0 (2.5.7) 2020-08-03 9a89c94bcc OpenJDK 64-Bit Server VM 11.0.8+10 on 11.0.8+10 +indy +jit [linux-x86_64]"}
[2023-05-10T17:16:25,713][INFO ][org.reflections.Reflections] Reflections took 24 ms to scan 1 urls, producing 23 keys and 47 values
[2023-05-10T17:16:25,989][INFO ][logstash.javapipeline    ][main] Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>8, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>50, "pipeline.max_inflight"=>1000, "pipeline.sources"=>["/etc/logstash/conf.d/test.conf"], :thread=>"#<Thread:0x50e1013f run>"}
[2023-05-10T17:16:26,470][INFO ][logstash.javapipeline    ][main] Pipeline Java execution initialization time {"seconds"=>0.47}
[2023-05-10T17:16:26,607][INFO ][logstash.javapipeline    ][main] Pipeline started {"pipeline.id"=>"main"}
[2023-05-10T17:16:26,646][INFO ][filewatch.observingtail  ][main][4dc77633e71bb984112a24ec0b874b2227768feace11807fb880a14efd3ebc20] START, creating Discoverer, Watch with file and sincedb collections
[2023-05-10T17:16:26,649][INFO ][logstash.agent           ] Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[2023-05-10T17:16:26,795][INFO ][logstash.agent           ] Successfully started Logstash API endpoint {:port=>9600}

실제로 동작하는지 테스트를 하기 위해, 위에서 생성한 input.log 파일에 내용을 추가합니다.

echo "Hello World" >> input.log

그러면 다음과 같이 output.log 파일을 열어 읽어온 내용을 작성하는 것으로 보이는 로그가 발생하는 것을 확인할 수 있습니다.

[2023-05-10T17:18:27,078][INFO ][logstash.outputs.file    ][main][877769ce6ad911efbfb23c362b7171c3bffaf81f60c437ee02823cbf6e1ca9a8] Opening file {:path=>"/var/log/logstash/output.log"}
[2023-05-10T17:18:51,641][INFO ][logstash.outputs.file    ][main][877769ce6ad911efbfb23c362b7171c3bffaf81f60c437ee02823cbf6e1ca9a8] Closing file /var/log/logstash/output.log

실제로 작성되었는지 vi /var/log/logstash/output.log를 통해 파일을 열어보면 다음과 같이 logstash에서 추가한 내용이 존재하는 것을 확인할 수 있습니다.

{"@version":"1","path":"/var/log/testlog/input.log","message":"Hello World","host":"buildagent002","@timestamp":"2023-05-10T08:18:26.927Z"}

04. Filebeat 환경 구축

logstash로 직접 파일을 읽는 방법도 있지만, filebeat를 통해서 파일을 읽을 수도 있습니다.
filebeat는 파일을 읽고 전달하는 것을 포함하여 logstash 대비 단순하고 적은 기능을 가지고 있어 더 가볍습니다. 서버에서 단순히 파일을 읽어 전달하는 기능만 필요하다면 logstash를 설치하는 것보다 filebeat를 사용하는 것이 더 좋습니다.

Filebeat 설치

Filebeat도 공식 홈페이지에서 RPM 버전을 다운로드 받은 후, CentOS 서버에 업로드하여 설치하도록 하겠습니다.

서버에 업로드가 완료되면, 아래 명령어를 통해 filebeat를 설치합니다.

sudo rpm --install filebeat-oss-7.10.2-x86_64.rpm

Filebeat 설정

Filebeat를 실행 및 종료하기 전, Filebeat를 통해 수집한 파일 내용을 Logstash로 전달하도록 구성해 보겠습니다.

먼저, 전달할 logfile을 생성해 줍니다. 이때, logstash에서와 같이 파일을 실행할 권한도 주어야 합니다.

# 생성
vi /var/log/testlog/input2.log
# 권한 부여
sudo chmod 755 /var/log/testlog/input2.log

그다음 input.log 파일을 logstash로 넘길 수 있도록 filebeat.yml을 수정해 봅시다.

먼저, 설정 파일을 열어줍니다.

sudo vi /etc/filebeat/filebeat.yml

그다음, 아래와 같이 설정 파일을 작성하였습니다.

# ...

filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/testlog/input2.log
    #- /var/log/*.log

  # ...

  multiline.pattern: '^[[:space:]]+(at|\.{3})[[:space:]]+\b|^Caused by:'
  multiline.negate: false
  multiline.match: after

# ...

output.logstash:
  # The Logstash hosts
  hosts: ["localhost:5044"]

각 설정에 대한 내용은 다음과 같습니다.

  • filebeat.inputs : filebeat로 수집하려는 대상에 대한 설정
    • type : input type으로, log 뿐만 아니라 filestream, kafka, redis, S3, container 등이 존재함
    • enabled : 설정한 input type에 대해 수집할 것인지 설정 (true : 수집, flase : 미수집)
    • paths : input type에 대한 경로 리스트
    • multiline.pattern : 여러 줄 수집 패턴. 여기서는 복잡한 자바 로그에 맞춰 설정했습니다.
    • multiline.negate : false로 설정 시 pattern에 일치하는 연속된 줄을 멀티라인으로 인식하며, true 설정 시 pattern에 일치하지 않는 연속된 줄을 멀티 라인으로 인식
    • multiline.match : after로 설정 시 negate에 맞춰 수집한 멀티 라인을 싱글 라인 뒤에 붙이고, before로 설정 시 negate에 맞춰 수집한 멀티 라인을 싱글 라인 앞에 붙임
  • output.logstash : filebeat로 수집한 내용을 전달받을 대상에 대한 설정으로, 여기서는 logstash로 설정. logstash 외에 elasticsearch, kafka, redis, file 등이 존재
    • hosts : output 대상 host 목록
    • output 설정을 할 때, logstash 외에 다른 경로로 output을 내보내지 않으려면 주석 처리 해야 합니다. (e.g. #output.elasticsearch #...)

Logstash Input을 Filebeat로 설정 - 다중 파이프라인

filebeat의 output을 logstash로 설정했으므로, logstash에서 filebeat를 통해 input을 받도록 설정해주어야 합니다. 기존의 file을 통해 일어오던 부분을 유지한 채, beat에 대한 설정을 추가하기 위해 다중 파이프라인으로 설정하도록 하겠습니다.

다중 파이프라인 설정을 위해 pipelines.yml을 열어줍니다.

sudo vi /etc/logstash/pipelines.yml

그리고 다음과 같이 설정 파일을 수정합니다.

#- pipeline.id: main
#  path.config: "/etc/logstash/conf.d/*.conf"

- pipeline.id: test1
  path.config: "/etc/logstash/conf.d/test.conf"
- pipeline.id: test2
  path.config: "/etc/logstash/conf.d/test2.conf"

이제, logstash에서 filebeat를 통해 데이터를 받아오도록 test2.conf 파일을 생성하여 설정해 봅시다.

sudo vi /etc/logstash/conf.d/test2.conf

filebeat를 통한 수집은 다음과 같이 설정합니다.

input {
    beats{
        port => 5044
    }
}

output {
    file {
        path => "/var/log/logstash/output2.log"
    }
}

그리고 결과를 저장할 output2.log도 생성합니다. 이때, logstash에서 읽을 수 있도록 설정해야 합니다.

# 생성
sudo vi /var/log/logstash/output2.log
# 권한 부여
sudo chown logstash:logstash /var/log/logstash/*.log

그다음 logstash를 재시작하고, file을 통한 입력이 정상적으로 수행되는지 확인해 봅시다.

# 재시작
sudo -i service logstash restart
# input.log 파일 내에 내용 추가
echo "multi pipeline test" >> input.log
# output.log 출력
cat /var/log/logstash/output.log
# output.log 출력 결과 내에 다음과 같은 로그가 기록되어 있음
{"host":"buildagent002","@version":"1","message":"multi pipeline test","@timestamp":"2023-05-11T04:52:05.096Z","path":"/var/log/testlog/input.log"}

정상 동작하는 것을 확인했으므로 이제 filebeat를 실행하고 테스트를 진행해 봅시다. 해당 내용은 아래에서 확인할 수 있습니다!

Filebeat 실행 및 종료

다른 Elastic Stack 제품군과 유사하게 Filebeat를 실행할 수 있습니다.

# 실행
sudo -i service filebeat start
# 종료
sudo -i service filebeat stop

그다음 아래 내용을 input2.log 내에 추가해 줍니다.

echo -e "2023-05-11 13:54:30.123 ERROR [HomeController] I/O error on POST request for \"http://localhost:9090\"; Connect to failed; connect timed out\n    at org.springframework\n    at org.spring.framework\nCaused by: org.apache.http.conn\n    at org.apache.http\n    at org.apache.http\n    ... 1 more" > input2.log

그다음 cat 명령어를 통해 output2.log를 화면에 출력해 보면, 아래와 같이 저장된 데이터를 확인할 수 있습니다. 해당 데이터의 "message" 부분을 보면, 입력한 데이터가 저장되어 있는 것을 확인할 수 있습니다.

# 파일 내용 보기
cat /var/log/logstash/output2.log
# 출력된 파일 내용
{"@version":"1","log":{"offset":287,"flags":["multiline"],"file":{"path":"/var/log/testlog/input2.log"}},"tags":["beats_input_codec_plain_applied"],"host":{"name":"buildagent002","architecture":"x86_64","id":"52a8654f14a0436b88623af1d800154a","mac":["fa:16:3e:28:0e:d2"],"containerized":false,"ip":["10.5.187.114","fe80::f816:3eff:fe28:ed2"],"os":{"version":"7 (Core)","name":"CentOS Linux","codename":"Core","kernel":"3.10.0-1160.el7.x86_64","platform":"centos","family":"redhat"},"hostname":"buildagent002"},"@timestamp":"2023-05-11T05:09:42.525Z","input":{"type":"log"},"agent":{"version":"7.10.2","name":"buildagent002","id":"5da5758f-13a9-45f2-9ad4-f6028ba03886","type":"filebeat","ephemeral_id":"93a3c224-5490-4847-be02-80e6b7e01899","hostname":"buildagent002"},"cloud":{"machine":{"type":"8vCPU_RAM64GB_Disk100GB_huge"},"provider":"openstack","instance":{"id":"i-0000aaa1","name":"buildagent002.kr.hmgcloud.com"},"availability_zone":"Reserve-Zone"},"message":"2023-05-11 13:54:30.123 ERROR [HomeController] I/O error on POST request for \"http://localhost:9090\"; Connect to failed; connect timed out\n    at org.springframework\n    at org.spring.framework\nCaused by: org.apache.http.conn\n    at org.apache.http\n    at org.apache.http\n    ... 1 more","ecs":{"version":"1.6.0"}}

 

 

참고

블로그의 정보

개발하는 두부

뚜부니

활동하기