본문 바로가기

server/kafka

ELK 실습

1. ELK 

ELK 스택(Elasticsearch, Logstash, Kibana)은 로그 데이터를 모아 저장하고 분석하는 데 아주 유용한 도구다. 시스템 모니터링, 문제 진단, 성능 최적화까지 다양한 상황에서 로그를 효과적으로 다룰 수 있게 도와준다.

 

로그 분석이 중요한 이유

로그 분석은 시스템이 정상적으로 동작하고 있는지 확인하는 기본적인 방법이다. 예상치 못한 장애나 성능 저하가 생겼을 때 빠르게 원인을 찾고 대응할 수 있는 근거도 로그에서 나온다. ELK 스택을 사용하면 로그를 단순히 모으는 데서 끝나지 않고, 실시간으로 분석하고 다양한 시각화까지 할 수 있다.

 

ELK Stack 구성 요소

  • Elasticsearch: 데이터를 저장하고 검색하는 엔진이다. 빠른 검색 속도와 대용량 데이터 처리에 강하다.
  • Logstash: 다양한 소스에서 로그를 수집하고 가공해 Elasticsearch로 전달한다.
  • Kibana: Elasticsearch에 저장된 데이터를 시각화해서 사용자에게 보여준다.

이 세 가지가 조합되어 로그 수집부터 분석, 시각화까지 한 번에 처리할 수 있는 구조를 만든다.

 

Kibana란 무엇인가

Kibana는 Elasticsearch 데이터를 시각적으로 보여주는 인터페이스다. 처음에는 오픈소스로 시작했지만, 현재는 서버 사이드 퍼블릭 라이센스(SSPL)를 적용받아 완전한 오픈소스는 아니다.

Kibana에서는 라인 차트, 파이 차트, 테이블, 히트맵 같은 다양한 형태로 데이터를 표현할 수 있다. 덕분에 로그 데이터뿐만 아니라 웹사이트 트래픽, 애플리케이션 성능 지표 같은 데이터도 한눈에 파악할 수 있다.

Kibana의 주요 활용 사례

Kibana는 로그와 메트릭 분석에 특히 강하다. 그 외에도 다음과 같은 곳에서 자주 활용된다.

  • 마이크로서비스 모니터링 대시보드
  • 사용자 행동 분석
  • Jenkins 빌드 모니터링
  • 매출 실적 분석
  • 리소스 할당 보고서 작성
  • 웹사이트 가동 시간 모니터링
  • 자동화 테스트 결과 추적
  • 글로벌 데이터 모니터링
  • 보안 위협 감지 및 대응

조금 덜 알려진 사례로는 컴플라이언스 감사, IT 운영 모니터링, 애플리케이션 성능 모니터링에도 활용된다.

 

Kibana의 모니터링과 알림 기능

Kibana에서는 임계값 기반 알림을 설정할 수 있다. 예를 들어 특정 오류율이 일정 수치를 넘으면 Slack으로 경고 메시지를 보내거나, 이메일 알림을 받을 수 있다. Elastic Observability, Elastic Security 모듈과 통합하면 더욱 강력한 모니터링과 대응 체계를 구축할 수 있다.

 


2. ELK 간편 실습 

이번 실습에는 kafka에 들어오는 데이터를 ELK로 가져와서 대시보드에서 보는것을 목표로 한다.

 

전체 폴더 구조는 다음과 같다 

logstash.conf : 로그스태시 설정파일

docker-compose.yml : 전체 시스템 

send_message.py : kafka로 테스트 메시지 전송 파일

 

 

먼저 docker-compose.yml 이다. 

version: '3.8'

services:
  zookeeper:
    image: confluentinc/cp-zookeeper:7.3.0
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
    ports:
      - "2181:2181"

  kafka:
    image: confluentinc/cp-kafka:7.3.0
    depends_on:
      - zookeeper
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 1
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      # 여기 고쳐야 한다
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,PLAINTEXT_INTERNAL://0.0.0.0:9093
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092,PLAINTEXT_INTERNAL://kafka:9093
      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_INTERNAL:PLAINTEXT
      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT_INTERNAL
    extra_hosts:
      - "kafka:127.0.0.1"  # docker-compose 내부 DNS 보장용

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
    volumes:
      - esdata:/usr/share/elasticsearch/data

  kibana:
    image: docker.elastic.co/kibana/kibana:7.17.0
    depends_on:
      - elasticsearch
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    ports:
      - "5601:5601"

  logstash:
    image: docker.elastic.co/logstash/logstash:7.17.0
    depends_on:
      - kafka
      - elasticsearch
    environment:
      - xpack.monitoring.enabled=false
    volumes:
      - ./logstash/pipeline:/usr/share/logstash/pipeline
    ports:
      - "5044:5044"
      - "5000:5000"
      - "9600:9600"

volumes:
  esdata:

 

 

로그스태시의 파일은 다음 경로에 있다. (docker-compose.yml에 있듯이 다음 경로에 넣어줘야 한다.)

/logstash/pipeline/logstash.conf

 

위의 파일에 카프카의 데이터를 logstash가 가져오도록 설정해주면 된다. 

input에 설정을 주의해야하는데 

bootstrap_servers => "kafka:9093"  # 해당 카프카에 
topics => ["log_test"]                          # log_test 라는 토픽에 있는 데이터를 가져와라. 
group_id => "logstash-consumer-group" # 컨슈머는 logstast-consumer-group으로 생성해라 
codec => "json"
auto_offset_reset => "earliest"
input {
  kafka {
    bootstrap_servers => "kafka:9093"
    topics => ["log_test"]
    group_id => "logstash-consumer-group"
    codec => "json"
    auto_offset_reset => "earliest"
  }
}

output {
  elasticsearch {
    hosts => ["http://elasticsearch:9200"]
    index => "your_index_name-%{+YYYY.MM.dd}"
  }
  stdout { codec => rubydebug }  # 디버깅용
}

 

input 에서 kafka에만 속하는 설정들이 있는데,group_id와client_id이다. 

group_id:  Kafka Consumer Group의 ID

  • Logstash가 Kafka에서 메시지를 읽어갈 때, Kafka는 이 group_id를 기준으로 offset(읽은 위치) 를 관리한다.
  • 같은 group_id를 사용하는 Consumer들은 서로 데이터를 나눠 읽는다.
  • Kafka에 저장된 데이터 중 어디까지 읽었는지를 Kafka 브로커가 기억하는 단위
  • group_id는 "내가 어디까지 읽었는지 Kafka야 기억해줘" 하는 식별자다.
  • Logstash가 재시작해도 이전에 읽던 위치를 이어서 읽게 해준다.

client_id: Kafka 클러스터에 보이는 Consumer 클라이언트 이름

  • group_id랑은 다르게 offset 관리랑 아무 관련 없다.
  • 클러스터 내부에서 이 Consumer를 구별하는 고유 이름
  • 모니터링이나 트러블슈팅할 때 "어떤 Consumer가 붙어있는지" 볼 수 있게 해준다.
  • client_id는 "내 이름은 logstash-01이야" 하고 Kafka에 등록하는 이름표

 

이제 docker-compose up으로 실행해보자

docker-compose up

 

 

에러 없이 정상적으로 실행되었다면 테스트 메시지를 전송해보자. 

send_message.py에 다음의 코드를 추가한다. 

from kafka import KafkaProducer
import json
import time

bootstrap_servers = ['localhost:9092']
topic_name = 'log_test'

producer = KafkaProducer(
    bootstrap_servers=bootstrap_servers,
    value_serializer=lambda v: json.dumps(v).encode('utf-8')
)

message = {
    "user_id": 12345,
    "action": "click",
    "timestamp": int(time.time())
}

producer.send(topic_name, value=message)
print(f"Message sent: {message}")

producer.flush()
producer.close()

 

이제 파이썬코드를 실행해보면 카프카에 메시지가 전송된다. 

$ python3 ./send_message.py
Message sent: {'user_id': 12345, 'action': 'click', 'timestamp': 1745804018}

 

logstash가 데이터를 잘 가져왔다면 엘라스틱서치에 index가 생성되었을 것이다. 

logstash.conf에 index이름을 "your_index_name-YYYYMMDD"로 생성했기 떄문에 다음과 같이 인덱스를 확인할수 있다. 

$ curl 'http://localhost:9200/_cat/indices?v'

health status index                           uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   your_index_name-2025.04.28      eb6RbuSCTsmQlz5uNa19SQ   1   1          7            0     25.3kb         25.3kb

 

 


 

마지막으로 IU에서 확인하기 위해  엘라스틱서치의 관리 화면으로 들어오자. 

브라우저에 다음으로 접속한다. http://localhost:5601

 

먼저 화면에 볼수 있도록 어떤 index를 볼지를 선택해줘야 한다. 

왼쪽 메뉴바에서 Management → Stack Management → Kibana → Index Patterns 를 클릭하자

해당 화면에서 create index patterns를 클릭해서 만들어주자.

(혹시 샘플 데이터를 만든다고 계속 뜬다면 그냥 만들어줘도 무방하다)

이름을 your_index_name-* 를 넣어주면 된다. your_index_name-로 시작하는 모든 인덱스를 참조하겠다는 뜻이다. 

정상적으로 만들어졌다면 메뉴바 -> Analytics -> Discover에서 실시간으로 들어오는 데이터를 확인할수 있다.

 

파이썬으로 메시지를 계속 전송해보면 아래와 같이 그래프에 들어온 메시지를 볼수 있다.

 

 

 

'server > kafka' 카테고리의 다른 글

kafka -> fluentd -> kafka 로 데이터 전송하기 (local)  (0) 2025.03.19