최종프로젝트 MSA 적용기 #5 - ELK

Skadi·2024년 4월 10일
0

ELK란


ELK는 Elasticsearch, Logstash, Kibana의 약어로, 대규모 데이터의 수집, 저장, 시각화 및 분석을 위한 오픈 소스 플랫폼입니다. 각각의 구성 요소는 다음과 같은 역할을 합니다

Elasticsearch: 실시간으로 데이터를 저장하고 검색할 수 있는 분산형 검색 및 분석 엔진입니다. Elasticsearch는 고성능의 RESTful API를 제공하여 데이터를 쉽게 쿼리하고 검색할 수 있습니다.

Logstash: 다양한 소스에서 로그 데이터를 수집하고 가공하여 Elasticsearch로 전송하는 데이터 수집 도구입니다. Logstash는 다양한 입력 소스와 출력 형식을 지원하며, 데이터 파이프라인을 구성하여 데이터를 가공하고 변환할 수 있습니다.

Kibana: Elasticsearch에서 수집된 데이터를 시각화하고 분석할 수 있는 대시보드 및 시각화 도구입니다. Kibana를 사용하면 다양한 차트, 그래프, 지도 등을 생성하여 데이터를 쉽게 이해하고 관리할 수 있습니다.

ELK 스택은 로그 및 이벤트 데이터의 수집, 분석, 모니터링 및 시각화에 널리 사용되며, 주로 시스템 및 응용 프로그램 로그의 분석 및 모니터링에 활용됩니다. 예를 들어, 서버 로그, 웹 서버 로그, 애플리케이션 로그 등 다양한 종류의 로그 데이터를 수집하여 실시간으로 분석하고 모니터링할 수 있습니다. ELK 스택을 통해 사용자는 데이터 기반의 의사결정을 내릴 수 있으며, 시스템의 성능을 최적화하고 문제를 해결할 수 있습니다.

MSA에 ELK를 적용하는 이유


  1. 로그 수집 및 분석: MSA 환경에서는 다수의 마이크로서비스가 동작하므로 각 서비스의 로그를 통합적으로 수집하고 분석하는 것이 중요합니다. ELK 스택은 Logstash를 통해 다양한 소스에서 로그를 수집하고 Elasticsearch에 저장한 뒤, Kibana를 통해 데이터를 시각화하여 분석할 수 있습니다.

  2. 분산된 환경에서의 로그 모니터링: MSA에서는 여러 서비스가 동작하므로 서비스 간 통신이나 데이터 처리에 문제가 발생할 수 있습니다. ELK를 사용하면 분산된 환경에서 발생하는 로그를 실시간으로 모니터링하여 문제를 신속하게 파악하고 대응할 수 있습니다.

  3. 디버깅 및 문제 해결: 서비스가 분산되어 있을 때 발생하는 문제를 해결하기 위해서는 각 서비스의 로그를 종합적으로 분석해야 합니다. ELK를 사용하면 전체 시스템의 로그를 통합적으로 분석하여 문제의 원인을 파악하고 신속하게 해결할 수 있습니다.

  4. 성능 및 안정성 개선: ELK를 통해 로그 데이터를 분석하고 모니터링함으로써 시스템의 성능을 개선하고 안정성을 향상시킬 수 있습니다. 예를 들어, 비정상적인 로그 패턴을 식별하고 예측적인 유지보수 및 용량 계획을 수립할 수 있습니다.

  5. 실시간 모니터링 및 경고: ELK는 실시간으로 데이터를 수집하고 분석하기 때문에 장애 상황이나 비정상적인 상황이 발생할 경우 즉각적으로 대응할 수 있습니다. 또한, 경고 시스템을 구축하여 비정상적인 동작을 감지하고 경고를 발생시킬 수 있습니다.

ELK 적용하기


해당 포스트에서는 docker를 이용한 ELK 방법을 소개하겠다.
Docker & Docker-Compose 설치는 다루지 않겠다.

  1. docker-compose.yml 작성
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
  1. logstash > config > logstash.yml 파일 생성
http.host: "0.0.0.0"
path.config: /usr/share/logstash/pipeline
xpack.monitoring.elasticsearch.hosts: [ "localhost:9200" ]
  1. logstash > pipline > logstash.conf 파일 생성
input {
  tcp{
	port => 5000
	codec => json
	type => "springboot_logs"
	host => "0.0.0.0" # 변경: 로컬 호스트 대신 모든 IP에서 로그를 수신합니다.
  }
}
 
output {
 
  elasticsearch {
    hosts => "elasticsearch:9200"
	  index => "springboot-%{app}"
  }
}
  1. docker-compose up 명령어 실행
  2. Kibana 포트에 접근 - 아래 페이지가 나타나면 성공!
  3. 로그를 보낼 스프링부트 프로젝트 생성
  4. build.gradle 설정
implementation group: 'net.logstash.logback', name: 'logstash-logback-encoder', version: '7.4'
  1. resources > logback.xml 생성
<?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>
  1. 로그를 생성할 controller 임시 생성
@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";
    }


}
  1. Kibana에 접속 > 왼쪽 메뉴 아이콘 > Discover > Create a data view > 만들어진 log에 맞추어 이름 생성

로그 수집 완성!!!

정리


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)

  • 다만 8버전으로 넘어오면서 추가된 보안 설정에 힘들어 잘 사용하지 못했다.
  • Kibana는 정상적으로 작동하는데 Logstash와 ElasticSearch와의 연결에 문제가 있었다
    • Logstash가 ElasticSearch에 대한 작성 권한이 없음
    • ElasticSearch에서는 작성 권한 부여 완료 ...?
    • vmmem에서 메모리 부족으로 읽기 전용파일로 만들어버린 것이 문제 ㅠㅠ 해결 실패
      => 해결 방법 : docker-compose.yml 파일에서 elasticsearch의 xpack.security.enabled=false 으로 일단 해결하긴 했다 다만 보안을 생각해서 추후 재도전 예정
  1. EC2 프리티어에 호스팅 후 Kibana 접근 불가
  • 10번에 1번 정도 성공하거나 503 에러 발생
    • EC2 프리티어에서 메모리 스왑 4GB 사용 - 실패(메모리 스왑 4GB중 2GB만 사용 / 접근 불가)
    • EC2 t2모델에서 t4g모델로 변경 - 성공(서버의 성능 문제였을 가능성이 높다)
      => 다만 비용문제로 유저테스트의 기간에만 사용하는 것으로 결정
  1. Logstash에서 Elasticsearch 접근 실패 메시지 발생
  • 다만 실제적으로는 로그를 잘 전송하는것으로 보여 문제가 발생하면 조치를 취하기로 함

이전 포스트 :
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

1개의 댓글

comment-user-thumbnail
2025년 3월 17일

안녕하세요 이번에 프로젝트에 MSA와 elasticsearch를 사용하게 되었는데요 자원을 어느정도 설정해야할지 몰라서 찾아보고 있었습니다 !
혹시 elasticsearch를 ec2서버에 같이 배포한 건가요? 최소 메모리가 어느정도는 되어야 하는지 궁금합니다! 실 사용을 아직 하기전이라서 설계 단계에서 미리 리소스를 정해놓고 추가적으로 서버를 증설할지 정하는게 나을 것 같아서요!!

답글 달기