BackEnd/Spring Boot

Spring Boot + Prometheus + Grafana 모니터링 시스템 구축

연향동큰손 2025. 9. 24. 23:29

 

 

Prometheus와 Grafana를 사용하여 Spring Boot와 연동하는 방법으로 모니터링 시스템을 구축하고자 한다.

 

 모니터링 시스템이 필요한 이유

CPU, 메모리, GC, 스레드, DB 커넥션 같은 주요 지표에 대한 적절한 알림 경고를 통해 버그, 장애가 발생한 상황을 인지할 수 있다.

이를 통해 장애에 대한 빠른 대처가 가능하고, 안정적인 운영을 통해 비즈니스 신뢰성을 확보할 수 있다.

 

 


사용된 기술

1. Spring Boot Actuator

Spring Boot Actuator는 Spring Boot 애플리케이션의 모니터링 및 관리를 용이하게 해주는 여러 기능을 제공하는 라이브러리이다. Actuator는 다음과 같은 기능을 제공한다.

  • 애플리케이션 건강 상태 확인
  • 메트릭 수집 및 시각화
  • 애플레케이션 환경 정보 제공
  • 애플리케이션 상태 및 메트릭을 엔드포인트로 노출하고, 이를 외부 모니터링 시스템이 활용할 수 있도록 해주는 도구

Actuator는 Prometheus, Grafana 같은 모니터링 시스템과 쉽게 연동할 수 있다는 장점이 있다.

 

2. Prometheus

Prometheus는 메트릭 수집, 시각화, 알림, 서비스 디스커버리 기능을 모두 제공하는 오픈 소스 모니터링 시스템이다.

Prometheus의 대표적인 기능은 다음과 같다.

  • Pull 방식의 메트릭 수집
  • 시계열 데이터 수집 ( CPU 사용률, 메모리 사용량, 응답 속도를 시간 축을 기준으로 연속적으로 기록 )
  • 데이터 시각화
  • 특정 메트릭이 임계치가 넘어가거나 경계에 잡혔을 때 이메일, 슬랙 등을 통해 알림 전송

Prometheus를 Spring Boot Actuator와 함께 사용하게 되면 Actuator에서 노출한 /actuator/prometheus 엔드포인트를 주기적으로 Pull 방식으로 스크래핑하여 데이터를 시각화하게 된다.

 

3. Grafana

Grafana는 시계열 메트릭 데이터를 시각화 하는 대시보드를 제공해주는 오픈소스이다.

다양한 데이터를 가져와 시각화할 수 있으며 각 지표에 대한 그래프를 그리는 것도 간단하게 가능하다.

또한 사용자들이 만들어 놓은 대시보드를 import해서 사용할 수 있고 그 대시보드를 커스터마이징할 수 있다.

Prometheus도 자체적인 UI를 제공하지만 그 기능이 비교적 빈약하여 Grafana와 함께 연동해서 사용하는 것이 일반적이다.


모니터링 시스템 구축

 

1. 의존성 추가

//Monitoring
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:microm

Spring Boot에서 JVM 메모리, GC, 스레드, HTTP 요청, DB 커넥션 등 운영 환경에서 필요한 정보 자동 수집하고 노출하기 위해 Spring Boot Actuator 라이브러리를 추가하고,

Actuator가 수집한 메트릭을 Prometheus 포맷으로 변환하기 위해 micrometer-registry-prometheus 라이브러리를 추가해줬다

 

 

2. Spring Boot Actuator, Micrometer 적용

application.yml

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus   # 모니터링용 엔드포인트 오픈
  endpoint:
    health:
      show-details: when_authorized
      probes:
        enabled: true   
  metrics:
    tags:
      application: youthjob-be
      version: "3.8"

 

Actuator 엔드 포인트는 기본적으로 보안상 외부에 노출하지 않고 닫혀있는데, include에 지정된 것만 HTTP API로 접근 가능하도록 설정할 수 있다.

내가 노출한 엔드포인트는 다음과 같다.

  • health : /actuator/health (애플리케이션 생존 여부, DB 연결 상태)
  • info : /actuator/info (애플리케이션 정보, 버전, 빌드 정보)
  • metrics : /actuator/metrics (JVM 메모리, 스레드, HTTP 요청 수 등 메트릭 조회)
  • prometheus : /actuator/prometheus (Prometheus가 스크래핑할 수 있는 포맷으로 변환된 메트릭)

show-details에서 when_authorized로 설정하여 인증된 사용자일 때만 상세 정보를 제공하도록 하였다.

 

3. prometheus.yml

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: "youthjob"
    metrics_path: "/actuator/prometheus"
    static_configs:
      - targets: ["spring-app:8080"]

 

Prometheus에서 Spring Boot 컨테이너를 모니터링 대상으로 지정하고, scrape_interval을 15초로 설정하여 /actuator/prometheus 엔드포인트에서 15초 주기로 메트릭을 수집하도록 구성하였다.

 

4. docker-compose.yml

Spring Boot 애플리케이션, Prometheus, Grafana를 Docker 컨테이너 단위로 묶어서 실행하였다.

version: "3.8"

services:
  app:
    build:
      context: ..                
      dockerfile: Dockerfile
    image: youthjob:latest       
    container_name: youthjob
    ports:
      - "8080:8080"
    networks: [monnet]

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
    ports:
      - "9090:9090"
    networks: [monnet]
    depends_on: [app]

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin
    ports:
      - "3000:3000"
    networks: [monnet]
    depends_on: [prometheus]

networks:
  monnet:
    driver: bridge 

 

Spring Boot 애플리케이션 컨테이너, Prometheus 컨테이너, Grafana 컨테이너를 모두 동일한 네트워크 안에 배치하여 컨테이너간 상호 통신이 가능하도록 하였고, 이를 통해 Prometheus는 Spring Boot 애플리케이션의 /actuator/prometheus 엔드포인트에서 주기적으로 메트릭을 수집하고, Grafana는 Prometheus를 데이터 소스로 연결하여 수집된 데이터를 시각화 할 수 있다.

 

5. Grafana, Prometheus 연결

이제 <퍼블릭 IP주소>:3000를 통해 Grafana UI에 접속할 수 있다.

Prometheus와 Grafana를 연결하여 시각화 하기 위해 Prometheus를 데이터 소스로 등록해줘야 한다.

 

 

여기서 Prometheus server URL은 같은 Docker 네트워크 안에 있다면 "http://<Prometheus 컨테이너 이름> : Prometheus가 실행되고 있는 포트"로 입력 해주면 된다.

 

6. Dashboard 추가

Grafana는 다양한 대시보드를 제공하는데 https://grafana.com/grafana/dashboards/ 여기서 자신에게 필요한 대시보드의 ID를 복사하여 Import dashboard 페이지에 넣어주면 된다.

 

 

대시보드를 확인해보면 가동시간, 힙 메모리 사용량, CPU 사용량, 부하 평균등의 애플리케이션 상태 정보가 나타나는 것을 확인할 수 있다.

 

 

7. 알림기능 활성화

Grafana에서 각 상황에 맞는 알림 기능을 설정하여 에러 상황을 빠르게 인지할 수 있도록 도와준다.

나는 CPU 사용률이 80%가 넘으면 나의 이메일로 알림이 오도록 설정해 봤다.

 

Altering -> Alter rules -> New alert rule

 

Query 조건은 Prometheus쿼리(PromQL)을 사용하여 System CPU 사용률이 80%가 넘을때를 조건으로 정했다.

 

이메일로 알림을 수신하기 위해서는 Grafana 컨테이너가 Gmail SMTP 서버를 이용해서 메일을 보낼 수 있게 설정해줘야 한다.

 

나는 Grafana 컨테이너가 실행되는 시점에서 이메일 전송에 필요한 값들을 환경 변수로 넣어줬다.

# Grafana
docker run -d \
  --name grafana \
  --restart unless-stopped \
  --network monnet \
  -e GF_SECURITY_ADMIN_USER=admin \
  -e GF_SECURITY_ADMIN_PASSWORD='Grafana 비밀번호' \
  -e GF_SMTP_ENABLED=true \
  -e GF_SMTP_HOST='smtp.gmail.com:587' \
  -e GF_SMTP_USER='나의 이메일' \
  -e GF_SMTP_PASSWORD='앱 비밀번호' \
  -e GF_SMTP_FROM_ADDRESS='나의 이메일' \
  -e GF_SMTP_FROM_NAME='Grafana' \
  -e GF_SMTP_SKIP_VERIFY=true \
  -v grafana-data:/var/lib/grafana \
  -p 3000:3000 \
  grafana/grafana:latest

 

여기서 GF_SMTP_PASSWORD는 gmail 비밀번호가 아닌 앱 비밀번호를 넣어줘야 한다.

Grafana의 SMTP설정이 완료되면 contact point에서 이메일을 입력하고 테스트 이메일을 수신해볼 수 있다.

 

설정을 끝내고 직접 시트템 CPU 점유율을 80%이상으로 끌어올려 정말 이메일이 오는지 확인해봤다.

# CPU 90% 정도 2코어에 2분간
sudo stress-ng --cpu 2 --cpu-load 90 --timeout 120s

 

수신한 이메일을 확인해보니, 내가 설정한 High CPU Usage 알림 규칙에 의해 메일이 발송되었고, 현재는 시스템 CPU 점유율이 임계치 아래로 떨어져 Resolved 상태로 표시되었다.