[Spring Boot] 시스템 모니터링 : Micrometer + Prometheus + Grafana
서비스가 안정적으로 운영되기 위해서는 애플리케이션의 상태를 수치로 관찰하고, 이상 징후를 빠르게 감지할 수 있어야 한다.
특히 MSA나 클라우드 환경처럼 복잡성이 높아질수록 시스템의 가시성(Observability), 즉 관찰 가능한 지표(Metric), 로그(Log), 트레이싱(Trace)를 수집하고 시각화하는 과정이 필요하다.
Spring Boot 기반 애플리케이션에서는 주로 Actuator와 Micrometer를 활용해 메트릭을 수집하고, Prometheus를 통해 데이터를 저장, Grafana로 대시보드를 구성하고 시각화하여 실시간 모니터링 체계를 구축할 수 있다.
이번 포스팅에서는 Micrometer와 Prometheus를 활용을 중심으로, Spring 애플리케이션에 모니터링 기능 적용을 위한 메트릭 수집 방법에 대해서 살펴보려고 한다.
- 구성 요소와 데이터 흐름 : Micrometer & Spring Boot Actuator & Prometheus & Grafana
- Spring Application 설정
1. 의존성 설정
2. 환경 변수 설정
3. Micrometer 지표 수집과 커스텀 지표
4. Actuator Endpoint 확인
- Prometheus와 Grafana 인프라 구성
1. Docker 컨테이너 기반 인프라 구성
2. Prometheus 확인
3. Grafana 확인 및 Prometheus 연결 : 대시보드 생성 및 데이터 소스 연결
- Grafana 활용
1. Grafana 대시보드 구성 : 대시보드의 구성 요소 & Query Builder
2. Grafana 템플릿 활용
구성 요소와 데이터 흐름
- Micrometer : 애플리케이션 내부에서 CPU 사용량, HTTP 요청 수, JVM 상태 등 다양한 메트릭을 수집한다.
- MeterRegistry : 수집된 메트릭은 Micrometer 내부의 MeterRegistry에 저장된다.
- Spring Boot Actuator : MeterRegistry에 저장된 메트릭을 외부에서 접근할 수 있도록 HTTP 엔드포인트(/actuator/prometheus)로 노출한다.
- Prometheus : Spring Actuator 엔드포인트를 주기적으로 호출(Polling)하여 메트릭을 가져온다.
- 수집한 메트릭을 시계열 데이터베이스에 저장한다.
- Grafana : Prometheus를 데이터 소스로 연결하여 메트릭을 쿼리하고 시각화하여 사용자에게 제공한다.
Micrometer
- Java 진영, 정확히 JVM 기반 애플리케이션의 모니터링을 위한 Metrics 계측 라이브러리이다.
- 다양한 모니터링 시스템에 데이터를 연동할 수 있도록 추상화 계층을 제공하며 Prometheus, Datadog, CloudWatch 등 다양한 구현체를 사용할 수 있다.
- Micrometer가 수집한 지표들은 내부적으로 MeterRegistry에 저장된다.
- Custom Metric : Annotation을 활용해 개발자가 직접 측정하고 싶은 메서드 지표를 수집할 수 있다.
- @Timed : 메서드의 실행 시간 & 호출 횟수
- @Counted : 단순 이벤트 횟수
- @Gauge : 현재 상태 값(메모리 크기 등)을 측정, 주로 변수 상태를 추적할 때 사용
Spring Boot Actuator
- Spring Boot 애플리케이션의 상태와 정보를 외부에 엔드포인트를 통해 노출하는 기능을 제공한다.
- 메트릭과 상태 확인 : /actuator/health, /actuator/metrics, /actuator/prometheus 등 다양한 엔드포인트를 통해 확인할 수 있다.
- 모니터링 기능 이외에도 환경 설정 정보, 빈 구성 정보 등 운영 및 진단에 필요한 내부 정보를 확인할 수 있는 엔드포인트를 제공 및 연동할 수 있다.
Prometheus
- 메트릭 데이터를 수집하고 저장하며, 모니터링과 알람에 활용되는 오픈소스 애플리케이션이다.
- 대상 시스템에 직접 접속하여 데이터를 가져오는 Pull 방식 구조를 사용한다.
- 즉 Spring Application의 경우 Spring Actuator의 엔드포인트에 접근하여 메트릭을 가져온다.
- 시계열 데이터베이스(TSDB)에 저장된 메트릭을 쿼리 언어(PromQL)로 조회할 수 있다.
Grafana
- 다양한 데이터 소스를 기반으로 시각화, 대시보드 구성, 모니터링 등을 제공하는 오픈소스 분석 도구이다.
- Prometheus를 포함한 시계열 데이터 소스를 연결해 메트릭을 시각화할 수 있다.
- Dashboard를 통해 시각화 및 실시간 지표 모니터링이 가능하다.
Spring Application 설정 : Micrometer 지표 수집 및 Actuator를 통한 엔드포인트 개방
1. 의존성 설정
▶ build.gradle
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'
▶ pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
먼저 필요한 의존성들을 추가해주자.
- spring-boot-starter-actuator : 애플리케이션의 상태 및 메트릭을 외부로 노출하는 Actuator 기능을 활성화한다.
- micrometer-registry-prometheus : Micrometer의 Prometheus용 MeterRegistry의 구현체이다. 즉 수집한 메트릭을 Prometheus에서 수집할 수 있는 포멧으로 변환하여 저장하고 노출할 수 있도록 한다.
2. 환경 변수 설정
▶ application.yml
management:
endpoints:
web:
exposure:
include: health, beans, httptrace, info, metrics, prometheus
- Actuator Endpoint를 노출하기 위한 환경 변수를 구성한다. 해당 Endpoint를 기반으로 Prometheus가 메트릭을 수집한다.
- Prometheus 엔드포인트가 명시적으로 활성화되도록 설정하였다.
- Micrometer가 Prometheus용 MeterRegistry를 활성화하도록 지정하였다.
3. 지표 수집과 커스텀 지표
기본적으로 Micrometer은 시스템 모니터링에 필요한 다양한 지표들을 수집한다. HTTP 요청 수, 응답 시간, JVM 메모리 사용량, GC 시간, CPU 사용률 등이 있다.
그리고 앞에서 언급했듯 사용자 정의 지표를 수집하기 위해서 Micrometer의 Annotation 기반으로 메서드 단위의 성능을 측정할 수 있다.
@GetMapping("/welcome")
@Timed(value="users.welcome", description = "Welcome 메서드의 실행 시간과 호출 횟수 측정")
public String welcome(){
return this.message;
}
4. Actuator Endpoint 확인
이제 Application을 실행하면 Actuator Endpoint를 통해서 애플리케이션 내부에서 Micrometer를 통해 수집한 지표를 확인 가능하다.
왼쪽은 Spring Boot의 내부 Metric 목록을 보여주는 엔드포인트이며, 오른쪽은 Prometheus가 읽을 수 있는 텍스트 기반으로 메트릭을 노출하는 엔드포인트이다.
Prometheus와 Grafana 인프라 구성
1. Docker 컨테이너 기반의 인프라 구성
Prometheus와 Grafana는 수동으로 설치하거나 직접 인프라를 구성해 운영할 수도 있지만, 설정과 배포가 복잡해질 수 있다.
이번 예제에서는 인프라 구성을 하나의 docker-compose.yml로 통합해 손쉽게 관리할 수 있도록 구성하였다.
▶ docker-compose.yaml
version: "3.7"
networks:
my-network:
driver: bridge
my-prometheus:
image: prom/prometheus:latest
container_name: my-prometheus-container
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9091:9090"
networks:
- my-network
my-grafana:
image: grafana/grafana:latest
container_name: my-grafana-container
ports:
- "3001:3000"
volumes:
- ./volumes/grafana:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=1111
depends_on:
- my-prometheus
networks:
- my-network
- Prometheus와 Grafana를 Docker 컨테이너로 실행하기 위한 Compose 설정이다.
- Prometheus는 로컬 설정 파일(prometheus.yml)을 마운트하고, 9091 포트를 통해 외부에 노출된다.
- Grafana는 Prometheus보다 늦게 실행되며, 3001 포트로 대시보드 UI를 제공한다. 설정은 볼륨으로 유지되며, 기본 관리자 비밀번호는 1111로 설정되어 있다.
▶ prometheus/prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'my-app-job'
metrics_path: '/actuator/prometheus'
static_configs:
# - targets: ['192.168.0.100:8080'] #컨테이너 외부의 Spring App :IP 및 Port 지정
- targets: ['didacto-app:8080'] #같은 네트워크 컨테이너 상의 Spring App : "컨테이너명:Port"로 지정
이 설정 파일은 Prometheus의 메트릭 수집 구성을 정의하며 docker-compose에서 해당 설정 파일을 컨테이너에 마운트하여 사용한다.
- scrape_configs : 메트릭 수집 대상을 정의하는 블록이며, 여기서는 my-app-job이라는 이름의 작업을 지정했다.
- metrics_path : Spring Boot Actuator가 Prometheus 메트릭을 노출하는 경로인 /actuator/prometheu를 지정하여 해당 엔포인트에 주기적으로 Polling하여 메트릭을 가져오도록 설정한다.
- targets : Prometheus가 메트릭을 요청할 IP와 포트(Spring 서버의 Address)를 설정한다.
- global 섹션에서는 모든 타겟에 대해 15초마다 메트릭을 수집하도록 설정하였다.
▶ 여러개의 Service Application의 메트릭을 수집하는 경우
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'service-a'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['192.168.0.101:8080'] # 서비스 A의 IP:Port
- job_name: 'service-b'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['192.168.0.102:8080'] # 서비스 B의 IP:Port
docker-compose up -d
docker-compose 파일에 정의된 여러 컨테이너를 동시에 이미지를 빌드하고 실행시켜주었다.
2. Prometheus 확인
- Prometheus 웹 UI (컨테이너에서 설정한 9091 Port. 기본값은 9090 Port)에 접속하면 수집한 Metric에 대한 내용을 시각화해서 확인할 수 있다.
- http_server_requests_seconds_count 메트릭을 조회한 결과, 상단 테이블은 엔드포인트별 요청 횟수를 보여주고, 하단 그림에서는 시간에 따른 변화량을 그래프 형태로 확인할 수 있다.
- 애플리케이션의 다양한 API 엔드포인트로의 요청 횟수가 정상적으로 수집되고 있는 것을 확인할 수 있다.
3. Grafana 확인 및 Prometheus 연결
Prometheus는 기본적인 메트릭 조회와 간단한 그래프 시각화를 지원하지만, 대시보드 구성, 사용자 권한 관리, 알림 설정 등은 제한적이다.
Grafana는 Prometheus를 포함한 다양한 데이터 소스와 연동 가능하며, 직관적인 시각화 대시보드를 제공한다. 즉 여러 지표를 한 화면에서 모니터링하거나, 조건부 알림을 설정하고 팀 단위로 공유하는 데 유리하다.
따라서 운영 환경에서는 Prometheus가 메트릭을 수집하고, Grafana가 이를 모니터링 및 분석 도구로 시각화하는 구조가 일반적이다.
대시보드 초기 화면
- Grafana에서 새로운 대시보드를 만들었지만, 아직 시각화 패널이나 데이터 소스가 설정되지 않은 상태이다. 따라서 "Add visualization" 버튼을 눌러 시각화 패널을 추가하고, 데이터 소스를 연결하여 어떤 메트릭을 그릴지 설정해야 한다.
데이터 소스 연결
- 시각화할 대상 데이터 소스 설정을 위해서 Prometheus 서버의 주소(http://didacto-prometheus:9090)를 입력하여 Grafana가 해당 메트릭 서버에 접근할 수 있도록 설정하였다.
- 하단에 "Data source is working" 메시지가 표시되면 연결 성공이다.
- Docker 기반으로 컨테이너 내부의 Prometheus에 연결할 경우 도커 네트워크 이름으로 접근해야 한다.
대시보드 생성
- 시각화 패널에서 사용할 데이터 소스를 선택하는 단계이다. 이 때 Prometheus를 포함하여 다양한 유형의 데이터 소스 인스턴스를 지정할 수 있다.
- 등록된 Prometheus 데이터 소스들이 나열되어 있다. 우리는 방금 생성한 prometheus-wisefee를 연동해주자.
Grafana 활용
1. Grafana 대시보드
대시보드의 구성 요소
- Dashboard: 여러 지표를 한눈에 볼 수 있도록 구성된 시각화 보드. 즉 화면 전체가 하나의 Dashboard이다.
- Panel: 각 데이터 시각화 블록의 단위. 즉 지표 혹은 데이터 쿼리를 시각화 한 단위. (메모리/CPU, 로그 수, 서버 요청량 등)
- Query Builder : Panel에 시각화할 데이터 소스와 Metric을 선택하고 함수와 Filter 등을 통해 가공하는 기능 제공.
- Visualization 유형: 그래프(Line, Bar), 숫자(Value) 등 다양한 시각화 단위가 사용된다.
- Legend: 각 패널 하단에 표시된 색상 라벨. 서버나 계측 지표를 구분한다.
- Time Range 및 Refresh: 우측 상단에서 조회 시간 범위와 자동 갱신 주기를 설정할 수 있다.
Query Builder
초기 대시보드를 생성한 이후 Grafana에서 Prometheus 데이터를 Panel 단위로 시각화하기 위한 쿼리 빌더(Query Builder) 화면을 확인할 수 있다.
- Metric 선택 : 다양한 메트릭 중에서 원하는 항목을 선택하여 조회 쿼리를 구성할 수 있다.
- http_server_requests_seconds_count는 HTTP 요청 처리 시간(초)의 카운트를 나타낸다.
- 집계 및 필터링 함수 적용 : 메트릭을 집계하거나 필터링하는 등 연산을 수행한다. 예를 들어 rate, sum, avg, max 등의 함수와 label filter를 조합하여 유의미한 지표를 생성할 수 있다.
- rate(http_server_requests_seconds_count[1m])는 1분 동안의 HTTP 요청 처리의 평균 증가율을 구하는 함수이다.
- 위에서 설정한 rate(http_server_requests_seconds_count[1m]) 쿼리를 적용시킨 대시보드의 모습이다.
- 최근 1분간 어떤 HTTP 요청들이 얼마나 자주 발생했는지에 대한 정보를 시각화해서 모니터링 할 수 있는 것을 확인할 수 있다.
2. Grafana 템플릿 활용
Grafana는 Prometheus, Graphite, InfluxDB등 다양한 데이터 소스 및 Spring(JVM), MySQL, Kubernetes 등 다양한 시스템에 맞춘 대시보드 템플릿을 커뮤니티에서 공유하고 있다.
템플릿을 사용하면 사전 구성된 쿼리, 패널, 시계열 설정을 포함하고 있어 설정 없이도 빠르게 모니터링 환경을 구축할 수 있다.
위 사진은 대시보드 템플릿 중 하나인 Micrometer 기반의 JVM의 모니터링에 필요한 GC 동작, 메모리 사용량, 오류율, 처리 시간 등의 지표를 실시간으로 모니터링할 수 있는 설정을 완료한 대시보드 템플릿이다.
https://grafana.com/grafana/dashboards/
Grafana dashboards | Grafana Labs
No results found. Please clear one or more filters.
grafana.com
Grafana 웹 UI에서 “Import dashboard” 기능을 사용해 템플릿에 등록된 ID를 입력 및 Data Source를 연결하여 바로 대시보드를 구성할 수 있다.
References
https://docs.spring.io/spring-cloud-dataflow-samples/docs/current/reference/html/_micrometer.html
9. Micrometer
9.1 SCDF metrics with InfluxDB and Grafana In this demonstration, you will learn how Micrometer can help to monitor your Spring Cloud Data Flow (SCDF) streams using InfluxDB and Grafana. InfluxDB is a real-time storage for time-series data, such as SCDF m
docs.spring.io
Grafana | Query, visualize, alerting observability platform
“When you become a big business with all this data, you need to pull it together. And I think Grafana is the gel that pulls everything together from across the business to give us a real-time snapshot of how Utilita’s doing at any given moment. It’s
grafana.com
'Backend > Spring' 카테고리의 다른 글
[Spring Boot] 트랜잭션 범위와 전파 속성(Propagation) (4) | 2024.08.26 |
---|---|
[Spring Boot] 테스트 코드 : 계층별 테스트 코드 작성 전략 (Controller, Service, Repository) (0) | 2024.08.05 |
[Spring Boot] 레이어드(Layerd) 아키텍쳐 : 계층별 주요 책임 및 고려할 점 (0) | 2024.08.04 |
[Spring Boot] 좋은 테스트 코드 : 필요성 및 실천 방법론 개요 (1) | 2024.07.22 |
[Spring Boot] 테스트 : Test Double : 모듈 의존성 격리(Mocking) (0) | 2024.05.16 |