ELK는 Elasticsearch, Logstash, Kibana의 약어로, 대규모 데이터의 수집, 저장, 시각화 및 분석을 위한 오픈 소스 플랫폼입니다. 각각의 구성 요소는 다음과 같은 역할을 합니다
Elasticsearch: 실시간으로 데이터를 저장하고 검색할 수 있는 분산형 검색 및 분석 엔진입니다. Elasticsearch는 고성능의 RESTful API를 제공하여 데이터를 쉽게 쿼리하고 검색할 수 있습니다.
Logstash: 다양한 소스에서 로그 데이터를 수집하고 가공하여 Elasticsearch로 전송하는 데이터 수집 도구입니다. Logstash는 다양한 입력 소스와 출력 형식을 지원하며, 데이터 파이프라인을 구성하여 데이터를 가공하고 변환할 수 있습니다.
Kibana: Elasticsearch에서 수집된 데이터를 시각화하고 분석할 수 있는 대시보드 및 시각화 도구입니다. Kibana를 사용하면 다양한 차트, 그래프, 지도 등을 생성하여 데이터를 쉽게 이해하고 관리할 수 있습니다.
ELK 스택은 로그 및 이벤트 데이터의 수집, 분석, 모니터링 및 시각화에 널리 사용되며, 주로 시스템 및 응용 프로그램 로그의 분석 및 모니터링에 활용됩니다. 예를 들어, 서버 로그, 웹 서버 로그, 애플리케이션 로그 등 다양한 종류의 로그 데이터를 수집하여 실시간으로 분석하고 모니터링할 수 있습니다. ELK 스택을 통해 사용자는 데이터 기반의 의사결정을 내릴 수 있으며, 시스템의 성능을 최적화하고 문제를 해결할 수 있습니다.
로그 수집 및 분석: MSA 환경에서는 다수의 마이크로서비스가 동작하므로 각 서비스의 로그를 통합적으로 수집하고 분석하는 것이 중요합니다. ELK 스택은 Logstash를 통해 다양한 소스에서 로그를 수집하고 Elasticsearch에 저장한 뒤, Kibana를 통해 데이터를 시각화하여 분석할 수 있습니다.
분산된 환경에서의 로그 모니터링: MSA에서는 여러 서비스가 동작하므로 서비스 간 통신이나 데이터 처리에 문제가 발생할 수 있습니다. ELK를 사용하면 분산된 환경에서 발생하는 로그를 실시간으로 모니터링하여 문제를 신속하게 파악하고 대응할 수 있습니다.
디버깅 및 문제 해결: 서비스가 분산되어 있을 때 발생하는 문제를 해결하기 위해서는 각 서비스의 로그를 종합적으로 분석해야 합니다. ELK를 사용하면 전체 시스템의 로그를 통합적으로 분석하여 문제의 원인을 파악하고 신속하게 해결할 수 있습니다.
성능 및 안정성 개선: ELK를 통해 로그 데이터를 분석하고 모니터링함으로써 시스템의 성능을 개선하고 안정성을 향상시킬 수 있습니다. 예를 들어, 비정상적인 로그 패턴을 식별하고 예측적인 유지보수 및 용량 계획을 수립할 수 있습니다.
실시간 모니터링 및 경고: ELK는 실시간으로 데이터를 수집하고 분석하기 때문에 장애 상황이나 비정상적인 상황이 발생할 경우 즉각적으로 대응할 수 있습니다. 또한, 경고 시스템을 구축하여 비정상적인 동작을 감지하고 경고를 발생시킬 수 있습니다.
해당 포스트에서는 docker를 이용한 ELK 방법을 소개하겠다.
Docker & Docker-Compose 설치는 다루지 않겠다.
version: "3"
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.3.3
container_name: elasticsearch_springboot
environment:
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- "discovery.type=single-node"
- xpack.security.enabled=false
ports:
- "9200:9200"
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
networks:
- elastic
kibana:
image: docker.elastic.co/kibana/kibana:8.3.3
container_name: kibana_springboot
ports:
- "5601:5601"
environment:
ELASTICSEARCH_URL: http://elasticsearch:9200
ELASTICSEARCH_HOSTS: '["http://elasticsearch:9200"]'
depends_on:
- elasticsearch
networks:
- elastic
logstash:
image: docker.elastic.co/logstash/logstash:8.3.3
container_name: logstash_springboot
volumes:
- ./logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml:ro
- ./logstash/pipeline:/usr/share/logstash/pipeline:ro
ports:
- "5044:5044"
- "5000:5000/tcp"
- "5000:5000/udp"
- "9600:9600"
environment:
LS_JAVA_OPTS: "-Xmx256m -Xms256m"
LS_LOG_LEVEL: "info"
networks:
- elastic
depends_on:
- elasticsearch
networks:
elastic:
driver: bridge
volumes:
elasticsearch_data:
driver: local
http.host: "0.0.0.0"
path.config: /usr/share/logstash/pipeline
xpack.monitoring.elasticsearch.hosts: [ "localhost:9200" ]
input {
tcp{
port => 5000
codec => json
type => "springboot_logs"
host => "0.0.0.0" # 변경: 로컬 호스트 대신 모든 IP에서 로그를 수신합니다.
}
}
output {
elasticsearch {
hosts => "elasticsearch:9200"
index => "springboot-%{app}"
}
}

implementation group: 'net.logstash.logback', name: 'logstash-logback-encoder', version: '7.4'
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%-5level %d{HH:mm:ss.SSS} [%thread] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="stash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>localhost:5000</destination>
<!-- encoder is required -->
<encoder class="net.logstash.logback.encoder.LogstashEncoder" />
</appender>
<root level="INFO">
<appender-ref ref="console"/>
<appender-ref ref="stash"/>
</root>
</configuration>
@RestController
@Slf4j
public class HomeController {
@GetMapping("/")
public String HomePage(){
LocalDateTime localDateTime = LocalDateTime.now();
log.info("Welcome home Page " + localDateTime);
return "Welcome to Home page";
}
@GetMapping("/logs")
public String LogsPage(){
LocalDateTime localDateTime = LocalDateTime.now();
log.info("This Logs page " + localDateTime);
return "Welcome to logs page";
}
@GetMapping("/warn")
public String WarnPage(){
LocalDateTime localDateTime = LocalDateTime.now();
log.warn("This warn page " + localDateTime);
return "Welcome to warn page";
}
@GetMapping("/er")
public String ErrorPage(){
LocalDateTime localDateTime = LocalDateTime.now();
log.error("This error page " + localDateTime);
return "Welcome to error page";
}
}

로그 수집 완성!!!
MSA에서 오류가 발생했을 때 어디서 발생했는지 빠르게 확인하기 위해 도입하였다.
추가적으로 error 로그만 나타나게 하려면 logback.xml을 아래와 같이 수정하면 된다.
<root level="error">
<appender-ref ref="console"/>
<appender-ref ref="stash"/>
</root>
사실 굉장히 오류가 많았다. 모든 내용을 담기 힘들정도로 많았고 해결하지 못하여 대체 방법을 찾았다.
1. https://github.com/deviantony/docker-elk 에 접근하면 기본 ELK를 제공한다(Docker)

이전 포스트 :
https://velog.io/@meleu/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-MSA-%EC%A0%81%EC%9A%A9%EA%B8%B0-4-Fiegn
다음 포스트 :
https://velog.io/@meleu/%EC%B5%9C%EC%A2%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-MSA-%EC%A0%81%EC%9A%A9%EA%B8%B0-6-Feign-%ED%86%B5%EC%8B%A0-%EC%97%90%EB%9F%AC
안녕하세요 이번에 프로젝트에 MSA와 elasticsearch를 사용하게 되었는데요 자원을 어느정도 설정해야할지 몰라서 찾아보고 있었습니다 !
혹시 elasticsearch를 ec2서버에 같이 배포한 건가요? 최소 메모리가 어느정도는 되어야 하는지 궁금합니다! 실 사용을 아직 하기전이라서 설계 단계에서 미리 리소스를 정해놓고 추가적으로 서버를 증설할지 정하는게 나을 것 같아서요!!