Spring 서비스의 운영 모니터링 환경 구축기1: Prometheus, Grafana, Loki, Kafka/Redis Exporter
목차
1.도입: 왜 도입을 했는가?
2.아키텍처 개요
3.Prometheus로 메트릭 수집
4.Loki + Promtail로그 수집
5. Grafana로 통합 대시보드 구성
6.느낀점
1.도입: 왜 도입을 했는가?
일정관리 프로젝트 개발 초기에는 Spring Boot의 MDC(Mapped Diagnostic Context)를 활용해서 requestId, username 등의 식별자를 로그에 포함시키고, 콘솔(logback)을 통해 디버깅을 진행했다.
MDC.put("requestId", UUID.randomUUID().toString());
MDC.put("username", authentication.getName());
<!-- logback-spring.xml -->
<pattern>
{
"timestamp": "%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ}",
"level": "%level",
"logger": "%logger",
"message": "%message",
"requestId": "%X{requestId}",
"email": "%X{email}"
}
</pattern>
이 방식은 로컬 개발 환경에서는 효과적이었다. IDE 콘솔에서 실시간으로 로그를 확인을 할 수 있었고, requestId 기반으로 로직의 흐름을 추적할 수 있었기 때문이다.
하지만 이 방식은 배포 이후, 아래와 같은 문제에 직면을 하게 되었다.
- 로그 접근 불편
- 서버에서는 콘솔이 아닌 로그 파일(/var/log/...)로 남기 때문에, 일일이 ssh에 접속을 해서 tail,grep를 해야된다는 점
- 실시간 추적 불가
- 여러 요청이 동시에 처리가 되면 어떤 요청이 어떤 로그인지가 혼동이 되기 시작함
- 분산 로그 수집 어려움
- Kafka,Redis 등의 로그는 백엔드 로그와 분리되어 있어서 전체 흐름 파악이 어려움
- 시각화가 없음
- 배포를 하게 되면 서버의 메모리 및 JVM Memory, API 응답속도, GC 동작 등을 숫자나 그래프로 볼 수가 없음.
이러한 이유로 인해서 실시간 모니터링 시스템을 도입을 하기로 했습니다.
운영 환경에서는 로그를 단순히 보는 것만으로는 부족하다는 판단하에, 다음 요소들을 고려하여 관측성(observability) 시스템을 도입하게 됐다.
- Loki + Promtail: 구조화된 JSON 로그를 수집하여 요청 단위 추적 가능
- Prometheus: 메트릭(JVM, Redis, Kafka 상태) 수집
- Grafana: 대시보드로 시각화 및 빠른 문제 진단
2.아키텍처 개요
이번에 구축을 할 모니터링 아키텍처는 아래의 사진과 같습니다.
위의 아키텍처를 설명을 하면 다음과 같습니다.
- 로그 기반 모니터링 시스템
- Spring Boot, Redis, Kafka 로그를 각각 Promtail이 수집
- Loki에 전송된 로그를 Grafana에서 시각화
- MDC 기반 JSON 로그 포맷으로 requestId, email 등 필터링 가능
- 메트릭 기반 모니터링 시스템
- Spring Boot는 /actuator/prometheus 메트릭을 노출
- Redis/Kafka는 Exporter를 통해 상태 정보 전달
- Prometheus가 메트릭을 주기적으로 수집하고 Grafana에서 시각화
3.Prometheus로 메트릭 수집
Prometheus는 시계열 DB 기반 매트릭 수집 시스템이다. 이번 프로젝트에서는 다음과 같이 지표들을 수집을 했다.
수집대상
- Spring Boot : JVM Memory, Heap 사용량, GC시간, HTTP 요청수/속도 등
- Redis: Key수, 메모리 사용량, 연결 수, latency 등
- Kafka: Borker 상태, Topic lag,파티션 수, consumer offset등
구성 방식
- docker-compose.dev.yml 파일 내에 Promethus 서비스 정의
- 각 서비스에 exporter를 설치를 하고 targets 설정을 통해서 Prometheus가 주기적으로 메트릭을 수집
- 메트릭은 기본적으로 15초 간격(scrape_interval)으로 수집
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'spring-boot'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['api.schedulemanagement.site:8082']
- job_name: 'kafka'
static_configs:
- targets: ['api.schedulemanagement.site:9308']
- job_name: 'redis'
static_configs:
- targets: ['api.schedulemanagement.site:9121']
- job_name: 'node-exporter'
static_configs:
- targets: ['api.schedulemanagement.site:9100']
4.Loki + Promtail로그 수집
로그 수집에는 Grafana의 Loki와 Promtail을 사용했습니다. Promtail은 각 컨테이너의 로그 디렉토리를 tail하여 Loki로 전송을 하고, Loki는 수신된 로그를 Grafana를 통해서 시각화 가능하게 해줍니다.
구성 방식
- 로그 파일은 컨테이너에서 /var/log/schedule-backend/app.log 로 출력이 되도록 logback을 설정
- Promtail은 해당 경로의 로그를 감시(tailing)하여 Loki로 전송
- JSON 포맷 로그를 사용해 필터링 및 검색 용이
# log-back예시
<pattern>
<pattern>
{
"level": "%level",
"thread": "%thread",
"logger": "%logger",
"message": "%message",
"requestId": "%X{requestId}"
}
</pattern>
</pattern>
장점
- requestId 기준으로 백엔드 로그를 추적 가능( MDC 활용)
- Kafka,Redis,Spring 로그를 한 화면에서 통합 조회 가능
- 에러, WARN 로그를 수준별로 필터링하거나 특정 사용자 기반 검색 가능
5. Grafana로 통합 대시보드 구성
Grafana는 Loki와 Prometheus 데이터를 시각화해주는 대시보드 툴입니다.
구성
- 매트릭 대시보드: CPU사용률, JVM Heap, Kafka Broker 상태, Redis Memory Api 요청 속도 등
6.느낀점
단순한 콘솔 로그 기반 디버깅에서 벗어나, 실시간 메트릭과 로그를 통합적으로 모니터링함으로써 다음과 같은 이점을 느낄 수 있었습니다.
- 운영 장애 대응 속도 향상
- 이전에는 오류 원인 파악에 grep,tail 등 수작업이 필요했겠지만, 지금은 Grafana 대시보드에서 즉시 확인 가능해졌다.
- 서비스 병목 지점 파악
- Prometheus 기반 메트릭 덕분에 API 응답속도와 GC 시간이 튀는 구간을 빠르게 확인할 수 있었다.
- Kafak/Redis와의 연결성 확보
- 단순한 backend 관찰을 넘어서, 이벤트 흐름 전체(Kafka->consumer->DLQ재처리)를 추적 가능해졌다.
- 결론
- 실시간 모니터링 시스템을 직접 구축하면서 운영 환경에서의 관측성의 중요성을 체감했습니다.
- 단순한 개발자 수준을 넘어, 서비스를 운영하는 개발자로서의 경험을 쌓을 수 있었고, 추후 무중단 배포,슬로우 쿼리 분석까지 확장 가능한 기반을 마련했다.