본문 바로가기
Today I Learned 2024. 11. 8.

(24.11.08) ELK 스택에 관하여 (1)

ELK 스택을 적극적으로 활용하는 회사도 많지만,

실제로는 실무 경험 내지는 대용량 트래픽을 다루는 경험이 많지 않은 이상 ELK 스택을 전부 활용하자는 아키텍쳐 구성 아이디러를 활용할 기회가 없었다.

 

오픈 소스이기도 해서 부담은 없지만, 실제로는 ElasticSearch에 대해서만 알고 있었기 때문에,

이번 기회에 ELK 스택 전부를 알아보고 실제 프로젝트의 파이프라인(AWS 인프라 활용, 컨테이너 활용) 환경에서 어떻게 적응할지에 대해서 고민하면서 찾아보고 공부하면서 스스로 정리했다.


ELK 스택

  • Elasticsearch, Logstash, Kibana 의 약자, 로그 및 데이터 분석을 위한 강력한 오픈소스 플랫폼 스택
    • 가격 부담없이 운용이 가능
  • 각 구성요소가 서로 보완적으로 작동 내지는 독립적으로
    • 대규모 데이터 수집, 저장, 검색, 분석, 시각화를 가능하게 작동
  • DevOps 환경에서 오류 진단, 애플리케이션 성능, 인프라 모니터링으로부터 값진 인사이트를 얻을 수 있도록 적은 비용으로 단순하면서도 강력한 로그 분석 솔루션
  • 한계
    • 데이터 중복 저장으로 인한 리소스 소모 발생 가능
    • 초기 설정의 복잡성
    • 대규모 데이터에서 성능적인 이슈가 발생 가능성이 있음

작동 FLOW

  1. Logstash는 데이터 수집 및 변환 후 전송
  2. Elasticsearch는 수집된 데이터를 인덱싱하고, 분석하고, 검색
  3. Kibana는 분석 결과를 시각화

Elasticsearch

  • 데이터를 저장하고 빠르게 검색할 수 있도록 돕는 분산 검색 및 분석 엔진 : Search & Analyze
  • JSON 형식 데이터를 Index로 저장
  • 강력한 Full-Text Search 기능을 제공
    • 빠른 검색 및 필터링 작업
  • 분산 아키텍처를 지원하여 대규모 데이터 처리에 적합한 엔진
  • 데이터의 Aggregation 기능을 통해 실시간 분석이 가능

Full-Text Search

  • 텍스트 데이터를 단어 수준으로 분석해 효율적으로 저장 → 사용자가 입력한 검색어(Query)와 비교하여 관련 있는 문서를 찾아내는 검색 방식
    • 단, 복잡한 초기 설계가 반드시 필요할 수 있고, 많은 리소스를 낭비하는 원인이 될 수 있음
  • 구성 및 FLOW
    1. Inverted Index : 문서를 통째로 저장하지 않고, 역색인 구조로 변환
    2. Analyzer : 사용자가 텍스트 저장, 검색 시 처리
      • 텍스트를 토큰으로 분리 Tokenization → 단어 표준화(대소문자, 어근, 복수형 등) Normalization → 높은 사용 빈도 단어 제거 Stop Words Removal
    3. 사용자 검색어 입력시, Inverted Index 데이터로 문서 검색결과의 관련성을 점수화
      • 특정 알고리즘으로 계산
  • 주요 기능
    • 매칭 쿼리 Match Query : 기본 검색 방식
      • {"match": {"content": "quick brown fox"}} : content 필드에서 관련 텍스트를 검색
    • 멀티-매칭 쿼리(Multi-Match Query) : 여러 필드(제목, 본문)에서 텍스트를 검색
    • 프레이즈 검색(Phrase Query) : 단어 순서를 고려하여 문구 전체를 검색
      • "match_phrase": {"content": "quick brown fox"} : 정확히 이 순서로 포함된 문서만 반환
    • 하이라이팅(Highlighting) : 검색 결과에서 매칭된 부분을 강조하여 표시
    • 퍼지 검색(Fuzzy Search) : 철자가 약간 틀리거나 유사한 단어도 검색
      • "fuzzy": {"content": "quik"}} ****: quick 도 검색 가능
    • Synonym Search : 동의어를 사용해 관련 문서도 검색
      • "car" → "automobile”
    • Wildcard 및 정규식 검색 : 와일드카드(*, ?)나 정규식을 활용한 유연한 검색
      • "wildcard": {"content": "bro*n"}} → "brown", "bron" 검색

Aggregation 기능

  • 분석 쿼리를 통해서 요약(Summarize)하고 분석(Analyze)하는 기능
  • 데이터의 그룹화, 패턴을 통한 어떠한 인사이트를 도출 가능함
  • Bucket Aggregation (그룹화) : 데이터를 특정 기준으로 그룹화
    • Terms Aggregation : 특정 필드 값을 기준으로 그룹화
      • 카테고리별 문서 수 집계 → {"field": "category.keyword"}
    • Range Aggregation : 숫자나 날짜 범위를 기준으로 그룹화
    • Date Histogram Aggregation : 데이터를 날짜 단위로 그룹화
    • Filter Aggregation : 특정 조건을 만족하는 데이터만 그룹화
      • 예: {"status": "active"} 조건에 맞는 데이터 필터링
  • Metric Aggregation (수치 계산) : 데이터를 수치 값으로 요약
    • Avg Aggregation : 평균 값 계산
    • Sum Aggregation : 합계 계산
    • Min/Max Aggregation : 최소값/최대값 계
    • Count Aggregation : 데이터 개수 계산
    • Stats Aggregation : 평균, 합계, 최소값, 최대값, 개수를 한 번에 계산
      • 결과: { "min": 10, "max": 100, "avg": 55, "sum": 220 }
  • Pipeline Aggregation (추가 분석) : Aggregation 결과를 기반으로 추가 연산 수행
    • Derivative Aggregation : 데이터 변화량 계산 ex)이전 달 대비 매출 증가율
    • Cumulative Sum Aggregation : 누적 합계 계산 ex)월별 매출 누적 합
    • Moving Average Aggregation : 이동 평균 계산 ex)최근 3개월 동안의 평균 매출

Logstash

  • 다양한 소스로부터 데이터를 수집, 처리, 변환한 후 Elasticsearch로 전송하는 엔진 : Collect & Transform
  • 파이프라인 형태의 테이터 구성
    • Input → Filter → Output
  • 다양한 Input Plugin 활용 가능
    • 로그 파일, DB, 메시징 큐 서비스 (Kafka, RabbitMQ) 등에서 데이터를 수집
  • Filter Plugin
    • 데이터 형식을 변환 / 특정 조건에 따라 데이터를 가공
    • ex) JSON 형식으로으로 파싱 / IP 주소의 Geo 정보 추가 등
  • Output Plugin:
    • 데이터를 Elasticsearch, S3, 메일 등으로 전송

Kibana

  • Elasticsearch에 저장된 데이터를 시각화 및 대시보드 형태로 시각화 하여 제공 : Visualize & Manage
    • 다양한 시각화를 모아 실시간으로 데이터를 모니터링.
  • 데이터 검색
    • 쿼리를 작성하여 원하는 데이터를 탐색 가능
  • 시각화 도구:(그래프, 차트, 맵 등) 을 통해 데이터를 쉽게 분석 가능
  • Alerting
    • 조건에 따라 알림을 설정해 이벤트 발생 시 조치

분산 서버에서의 파이프라인에서의 로깅 FLOW

[애플리케이션 서버 1] → [RabbitMQ/Kafka] → [Consumer 1] → [Elasticsearch Node 1]
[애플리케이션 서버 2] → [RabbitMQ/Kafka] → [Consumer 2] → [Elasticsearch Node 2]
[애플리케이션 서버 3] → [RabbitMQ/Kafka] → [Consumer 2] → [Elasticsearch Node 3]
	                                                                                                                                                        → [Kibana 대시보드]

1. 애플리케이션 서버별 로그 생성

  • 각 분산 서버(Spring Boot 애플리케이션 기준)에서 독립적으로 로그 생성
    • Slf4j, Logback, Log4j를 사용하여 JSON 형식으로 로그를 통일적으로 생성

Spring에서 로그 파일 생성

  • Spring Boot는 기본적으로 Logback을 로깅 구현체로 사용
  • JSON 형식으로 로그를 생성하고 파일로 저장하고 그 파일을 보내는 활용하는 방식

1. Logback 설정 파일 (logback-spring.xml) 작성

<configuration>
    <!-- 로그를 JSON 형식으로 출력 -->
    <appender name="JSON_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/application-log.json</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/application-log-%d{yyyy-MM-dd}.json</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder" />
    </appender>

    <!-- 콘솔 출력도 추가 가능 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="JSON_FILE" />
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>
  • JSON_FILE: 로그를 JSON 형식으로 저장
  • fileNamePattern: 날짜별로 로그를 분리해서 저장
  • RollingPolicy: 오래된 로그 파일은 일정 기간 이후 삭제 정책
    • 위에서는 30일 보관을 예시
{
  "@timestamp": "2024-11-08T12:00:00.123Z",
  "level": "INFO",
  "thread": "main",
  "logger_name": "com.example.MyClass",
  "message": "INFO 로그 메시지",
  "context": "default"
}
  • 위의 형태의 로그가 logs/application-log.json 파일에 계속 append 되면서 찍히게 됨
  • 로그롤링정책에 의해서 매일 정각 logs/application-log-YYYY-MM-DD.json 형태로 파일이 저장

2. 로그 수집 및 중앙화 전송

  • 각 서버의 로그를 메시지 큐로 비동기적으로 수집 및 전송
    • 각 애플리케이션 서버에서 Filebeat( 또는 **Logstash Forwarder, 많이 사용 X)**를 설치해 로그를 메시지 큐(RabbitMQ/Kafka)로 전송

Filebeat 구성

docker pull docker.elastic.co/beats/filebeat:latest
  • (EC2 인스턴스에 Spring Application 컨테이너가 실행되고 있다고 가정했을 때,) 인스턴스 안에 Filebeat 컨테이너를 이미지로 구성
mkdir spring-app-logs && cd spring-app-logs
nano docker-compose.yml
version: '3.8'
services:
  spring-app:
    image: your-spring-app-image:latest
    container_name: spring-app
    volumes:
      - logs:/app/logs
    ports:
      - "8080:8080"

  filebeat:
    image: docker.elastic.co/beats/filebeat:latest
    container_name: filebeat
    user: root
    volumes:
      - logs:/app/logs
      - ./filebeat.yml:/usr/share/filebeat/filebeat.yml
    depends_on:
      - spring-app

volumes:
  logs:

  • docker-compose.yml 파일을 인스턴스 루트 디렉토리에 생성
mkdir ~/filebeat && cd ~/filebeat
nano filebeat.yml
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /app/logs/application-log-*.json

output.kafka:
  hosts: ["<kafka-broker>:9092"]
  topic: "spring-app-logs"

  • 설정파일 filebeat.yml 작성 (RabbitMQ를 사용하는 경우 output.rabbitmq 로 변경)
docker-compose up -d
  • 해당 컴포즈 파일로 컨테이너를 실행한다면, 각각 Spring Application, Filebeat 가 실행되면서 서로 로그 파일을 공유 → 메시지 큐로 전달 가능

3. 메시지 큐를 통한 로그 분산 처리

  • 메시지 큐(RabbitMQ/Kafka)는 수집한 로그를 여러 Consumer로 분산 전송
    • 순서 보장을 위해 Kafka의 파티셔닝 등 메시자 큐 단의 처리

4. Consumer를 통한 로그 처리 및 Elasticsearch로 전송

  • 각 Consumer가 메시지 큐로부터 로그를 읽고 가공(Logstash 역할)
  • 로그 데이터를 Elasticsearch 클러스터로 저장

5. Elasticsearch에서 데이터 분산 저장

  • 서버 분산 환경에서 Elasticsearch 클러스터가 각 노드에 데이터를 샤딩 및 복제하여 저장
    • 각 노드가 병렬로 데이터를 처리 → 대규모 로그 데이터 처리 가능

6. Kibana에서 로그 시각화 및 분석

  • Kibana가 Elasticsearch 클러스터와 연결되어 전체 분산 서버의 로그 데이터를 하나의 대시보드에서 확인
  • 필터, 검색 쿼리를 사용해 특정 서버나 요청별 데이터를 분리해 분석.

Elastic Stack

  • ELK Stack + Beats 차세대 로깅 엔진
  • Logstash의 데이터 수집/변환의 역할의 과도한 분배로 Overhead 발생을 방지, 이를 분배해주는 Beats 모듈을 도입

Beats

  • 경량 데이터 수집기
  • 특정 데이터 소스를 모니터링하고 이를 Logstash나 Elasticsearch로 전송
  • 구성
    • Filebeat: 로그 파일 수집
    • Metricbeat: 시스템 및 서비스 성능 데이터 수집
    • Packetbeat: 네트워크 트래픽 분석

실제로는 코드가 많아보이지만, 방법만 안다면 이미 구성되어있는 ELK 스택에 관련해서 충분히 이해하고

구성할 수 있는 기본적인 코드들이다

 

이후의 포스트에서는 ELK에 어떻게 사용자가 접근해서 분산되어서 작동되는 Application  서버와 비동기로 관리되고 있는로그들에 대해서 좀 정리할 계획이다.