Prometheus와 Grafana를 활용한 모니터링
Spring Boot 애플리케이션을 운영하다 보면, 현재 서버의 상태나 성능을 모니터링해야 하는 경우가 많습니다.
특히 마이크로서비스 아키텍처(MSA) 환경에서는 서비스 간 연결이 많아지고, 각 서비스의 상태를 실시간으로 확인하는 것이 매우 중요해집니다.
이때 활용할 수 있는 대표적인 기능이 바로 Spring Boot Actuator입니다.
Actuator는 애플리케이션의 다양한 정보를 쉽게 조회할 수 있도록 API 엔드포인트를 제공하는 도구입니다.
하지만 Actuator만으로는 실시간 데이터 분석 및 장기적인 모니터링이 어려운 한계가 존재합니다.
이 글에서는 Spring Boot Actuator의 기능과 한계를 알아보고, 이 한계를 Prometheus와 Grafana를 활용해 해결하는 방법을 설명하겠습니다.
Spring Boot Actuator란?
Spring Boot Actuator는 애플리케이션의 상태를 모니터링하고,
다양한 운영 정보를 제공하는 관리 도구입니다.
Actuator의 주요 기능
Actuator는 기본적으로 다양한 엔드포인트(Endpoints)를 제공합니다. 이 엔드포인트를 통해 애플리케이션의 상태를 쉽게 조회할 수 있습니다.
엔드포인트 설명
/actuator/health | 애플리케이션 상태 확인 (UP/DOWN) |
/actuator/metrics | JVM, CPU, 메모리 사용량, HTTP 요청 수 등 확인 |
/actuator/loggers | 애플리케이션 로그 설정 변경 가능 |
/actuator/threaddump | 현재 실행 중인 스레드 덤프 정보 확인 |
/actuator/prometheus | Prometheus에서 수집할 수 있는 메트릭을 제공 |
이 중에서 /actuator/prometheus 엔드포인트는 Prometheus와 연동할 때 중요한 역할을 합니다.
Prometheus는 이 엔드포인트에서 데이터를 가져와(PULL 방식) 저장하고 분석할 수 있습니다.
실제로 이렇게 서버를 로컬로 키시고 actuator의 엔트포인트를 입력하시면 스프링이 다양한 기능을 제공하는 것을 볼 수 있습니다.
이것을 통해서 우리는 특정 URI의 요청 수, 힙 메모리 사용량, 스레드의 개수 등등을 확인할 수 있습니다.
그리고 아마 실제로 실행해 보시면 위와 같은 화면이 안 나올 수도 있습니다.
같은 결과가 나오기 위해서는 아래와 같이 설정을 해주세요.
// application.yml
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
info:
os:
enabled: true
java:
enabled: true
server:
port: 8080
tomcat:
mbeanregistry:
enabled: true
부가설명을 해드리겠습니다.
management:
endpoints:
web:
exposure:
include: "*"
- Actuator의 모든 엔드포인트를 웹에서 접근 가능하도록 설정합니다.
- 기본적으로 Actuator 엔드포인트는 일부만 노출되지만, include: "*"을 설정하면 모든 엔드포인트(/actuator/health, /actuator/info, /actuator/metrics 등)를 사용할 수 있습니다.
management:
endpoint:
health:
show-details: always
- /actuator/health 엔드포인트에서 시스템의 상태를 확인할 수 있습니다.
- 기본적으로는 "UP" 또는 "DOWN" 같은 간단한 정보만 제공하지만, show-details: always를 설정하면 상세 정보를 포함한 응답을 반환합니다.
management:
info:
os:
enabled: true
java:
enabled: true
- /actuator/info 엔드포인트에서 운영 체제(os) 및 Java의 버전 정보를 제공합니다.
server:
tomcat:
mbeanregistry:
enabled: true
이 설정을 하시면 Tomcat 내부의 실행 정보(스레드 수, 커넥션 상태 등)를 JMX에서 확인 가능합니다.
Actuator의 한계점
- 실시간 모니터링 부족
- Actuator는 현재 상태만 제공하며, 과거 데이터에 대한 분석이 어렵습니다.
- CPU 사용량이나 HTTP 요청 수가 일정 기간 동안 어떻게 변화했는지 확인하기 어렵습니다.
- 장기적인 데이터 저장 불가능
- Actuator는 단순한 API 형태로 데이터를 노출할 뿐,
이를 장기적으로 저장하거나 분석할 수 있는 기능이 없습니다.
- Actuator는 단순한 API 형태로 데이터를 노출할 뿐,
- 알람(Alert) 기능이 없음
- 서버에서 장애가 발생하더라도 자동으로 알람을 보내는 기능이 없습니다.
- 운영자가 직접 /actuator/health 같은 엔드포인트를 수동으로 확인해야 합니다.
- 시각화 기능 부족
- Actuator는 JSON 형식으로 데이터를 반환하기 때문에,
데이터를 직관적으로 분석하기 어렵습니다. - 차트나 그래프 형태로 시각화하려면 별도의 툴이 필요합니다.
- Actuator는 JSON 형식으로 데이터를 반환하기 때문에,
💡해결책
Actuator는 애플리케이션 내부 정보를 제공하는 역할을 하지만,
이를 효과적으로 활용하려면 Prometheus 및 Grafana와 함께 사용하는 것이 필수적입니다.
Prometheus란?
Prometheus는 시계열 데이터를 수집하고 저장하는 모니터링 도구입니다.
Prometheus의 주요 특징
- 실시간 메트릭 수집 (Pull 방식)
- 애플리케이션에서 직접 데이터를 푸시하는 것이 아니라,
Prometheus가 주기적으로 /actuator/prometheus 엔드포인트에서 데이터를 가져오는 방식입니다.
- 애플리케이션에서 직접 데이터를 푸시하는 것이 아니라,
- 강력한 시계열 데이터 저장 기능
- Actuator는 현재 상태만 제공하지만,
Prometheus는 데이터를 저장하여 과거 기록을 분석할 수 있습니다.
- Actuator는 현재 상태만 제공하지만,
- PromQL을 활용한 데이터 분석 가능
- Prometheus는 PromQL이라는 자체 쿼리 언어를 제공하여 데이터를 분석할 수 있습니다.
- 자동화된 알람(Alert) 기능
- CPU 사용량이 90% 이상이면 Slack이나 이메일로 경고 메시지를 보낼 수 있습니다.
Grafana란?
Prometheus가 데이터를 저장하고 분석하는 역할을 한다면,
Grafana는 이를 시각적으로 표현하는 역할을 합니다.
Grafana의 역할
- Prometheus에서 수집한 데이터를 차트와 그래프로 시각화할 수 있습니다.
- 실시간 모니터링 대시보드를 제공하여 애플리케이션의 상태를 직관적으로 파악할 수 있습니다.
- 사용자 정의 대시보드를 만들 수 있어 각 조직의 운영 환경에 맞춘 모니터링이 가능합니다.
Prometheus가 데이터를 수집하고, Grafana에서 이를 시각적으로 보여주는 방식으로 Actuator의 한계를 극복할 수 있습니다.
k6란?
k6는 성능 테스트및 부하 테스트를 위한 오픈 소스 도구입니다.
K6는 아래와 같은 기능을 제공합니다.
- API 부하 테스트
- 웹 애플리케이션 성능 테스트
- 마이크로서비스 간 통신 부하 테스트
- CI/CD에서 자동 성능 테스트
- Prometheus, Grafana와 연동하여 실시간 모니터링
Prometheus + Grafana 모니터링 구조
디렉토리 구조
docker-compose.yml 코드
# docker-compose.yml
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus.yml:/prometheus/prometheus.yml
ports:
- "9090:9090"
command:
- --web.enable-remote-write-receiver
- --enable-feature=native-histograms
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- ~/Desktop/spring_study/grafana-9.3.6/data:/var/lib/grafana
- ./grafana_provisioning:/etc/grafana/provisioning
- ./grafana_dashboard:/var/lib/grafana/dashboards
depends_on:
- prometheus
k6:
image: grafana/k6:latest
container_name: k6
command: run -o experimental-prometheus-rw /scripts/output_test.js
volumes:
- ./output_test.js:/scripts/output_test.js
environment:
- K6_PROMETHEUS_RW_SERVER_URL=http://prometheus:9090/api/v1/write
- K6_PROMETHEUS_RW_TREND_AS_NATIVE_HISTOGRAM=true
networks:
- default
depends_on:
- prometheus
Prometheus는 시계열 데이터를 수집하고 저장하는 역할을 합니다.
volumes 설정을 통해 prometheus.yml 설정 파일을 마운트하여 원하는 데이터를 수집할 수 있습니다.
💡바운드 마운트란?
바운드 마운트는 호스트 시스템의 특정 디렉토리를 컨테이너 내부 디렉토리와 연결하는 방식입니다.
즉, 컨테이너 내부에서 데이터가 변경되면, 로컬(호스트)에도 바로 반영되며, 반대로 로컬에서 파일을 변경하면 컨테이너 내부에서도 동일하게 변경됩니다.
--enable-feature=native-histograms 옵션은 응답 시간 데이터를 세밀하게 분석할 수 있도록 도와줍니다.
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus.yml:/prometheus/prometheus.yml
ports:
- "9090:9090"
command:
- --web.enable-remote-write-receiver
- --enable-feature=native-histograms
Grafana는 Prometheus 데이터를 대시보드로 시각화하는 역할을 합니다.
volumes 설정을 통해 Grafana 설정 및 대시보드 데이터를 저장할 수 있습니다.
기본적으로 도커로 그라파나를 실행하면 /var/lib/grafana 경로는 Grafana의 내부 컨테이너 파일 시스템에서 데이터(설정, 대시보드, 사용자 정보 등)를 저장하는 기본 경로입니다.
따라서 저는 기존에 저의 컴퓨터에 설치돼있던 그라파나의 데이터를 컨테이너로 가져오고싶어서 아래와 같이 사용했습니다.
- ~/Desktop/spring_study/grafana-9.3.6/data:/var/lib/grafana
또한 K6로 가져온 데이터를 이쁘게 보여주기 위해서 대시보드 양식을 설정을 하였습니다.
이 부분은 대시보드 양식 부분이라 이해 안 하셔도 괜찮습니다.
- ./grafana_provisioning:/etc/grafana/provisioning
- ./grafana_dashboard:/var/lib/grafana/dashboards
depends_on: prometheus 설정을 추가하여 Prometheus가 실행된 후에 Grafana가 실행되도록 설정했습니다.
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- ~/Desktop/spring_study/grafana-9.3.6/data:/var/lib/grafana
- ./grafana_provisioning:/etc/grafana/provisioning
- ./grafana_dashboard:/var/lib/grafana/dashboards
depends_on:
- prometheus
K6는 HTTP 부하 테스트를 수행하는 도구로, 애플리케이션의 성능을 평가할 수 있습니다.
- command: run -o experimental-prometheus-rw /scripts/output_test.js
→ K6가 부하 테스트를 실행하고 결과를 Prometheus로 보낸다는 코드입니다. - volumes 설정을 통해 부하 테스트 스크립트(output_test.js)를 컨테이너 내부로 마운트하여 실행할 수 있도록 합니다.
environment 설정을 통해서 k6가 Prometheus의 remote_write API로 데이터를 직접 Push하도록 설정하였습니다.
✅ http://prometheus:9090/api/v1/write
→ prometheus 컨테이너의 포트 9090에서 데이터를 받을 수 있도록 설정.
✅ K6_PROMETHEUS_RW_TREND_AS_NATIVE_HISTOGRAM=true
-> 트렌드 데이터를 Prometheus Native Histogram으로 저장
데이터를 네이티브 히스토그램으로 저장한다는 것이 무슨 소리인 지 모를 수도 있습니다.
자세히 설명 드리겠습니다.
💡 네이티브 히스토그램란?
Prometheus에서 Histogram을 사용하는 이유는 응답 시간(latency), 처리량(throughput) 등의 성능 데이터를 분석하기 위해서입니다.
각각의 HTTP의 요청들의 latency와 throughput은 제각각일 것입니다.
그래서 일반적인 히스토그램은 고정된 버킷값을 사용합니다.
💡여기서 버킷값이란?
버킷은 히스토그램에서 데이터를 그룹화하는 범위(구간)를 의미합니다.
✅ 일반적인 히스토그램이런식으로 미리 버킷값을 고정해두고 요청을 제각기 분류합니다.
응답 시간 0.5초 이하 0.5초 이하 1초 이하 5초 이하 10초 이하 요청 개수 50 200 400 80 1000
✅ 네이티브 히스토그램
버킷을 미리 정의하지 않고, 데이터가 들어오면서 자동으로 적응하는 방식. 즉, 응답 시간이 다양하게 분포될 경우, 적절한 구간을 자동으로 설정합니다.
기존 방식과의 차이점:
- 0.5초~1초 구간에 요청이 많다면, 이 구간을 더 세밀하게 나누어 저장.
- 5초~10초 구간에는 요청이 적다면, 더 큰 범위로 묶어서 저장.
- 결과적으로 데이터를 더 효율적으로 저장하면서도 정확도를 높일 수 있습니다.
k6:
image: grafana/k6:latest
container_name: k6
command: run -o experimental-prometheus-rw /scripts/output_test.js
volumes:
- ./output_test.js:/scripts/output_test.js
environment:
- K6_PROMETHEUS_RW_SERVER_URL=http://prometheus:9090/api/v1/write
- K6_PROMETHEUS_RW_TREND_AS_NATIVE_HISTOGRAM=true
depends_on:
- prometheus
prometheus.yml 코드
✅ scrape_configs: 어떤 데이터를 가져올지 정의
Prometheus가 수집할 대상(타겟)을 정의하는 부분입니다.
scrape_configs 아래에 여러 개의 job을 정의할 수 있습니다.
✅ static_configs: 데이터를 가져올 서버를 정의
Prometheus가 데이터를 가져올 서버를 정의하는 부분입니다.
- targets: Prometheus가 데이터를 가져올 서버의 주소를 지정
- ['host.docker.internal:8080']:
Spring Boot 애플리케이션이 8080 포트에서 실행되고 있는 중이고,
Prometheus는 Docker 컨테이너에서 실행되고 있고, Spring Boot는 호스트에서 실행되었다는 의미.
Docker 컨테이너에서 호스트 OS에 접근하려면 host.docker.internal을 사용해야 합니다. (localhost는 사용할 수 없음)
여기서 localhost라는 의미는 컨테이너 자체를 말합니다.
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: "spring-actuator"
metrics_path: '/actuator/prometheus'
scrape_interval: 15s
static_configs:
- targets: ['host.docker.internal:8080'] # 호스트 머신의 Spring Boot
Dashboards.yml 코드
우리가 가져온 K6 데이터를 그라파나에 대시보드 양식으로 보여줌으로써 가시성을 높일 수 있습니다.
apiVersion: 1
providers:
- name: "k6 Stress Test"
orgId: 1
folder: ""
type: file
disableDeletion: false
updateIntervalSeconds: 10
options:
path: /var/lib/grafana/dashboards
Output_test.js 코드
K6의 설정 파일입니다.
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
vus: 10, // 동시 사용자 수
duration: '30s', // 테스트 지속 시간
};
export default function () {
http.get('https://test-api.k6.io/public/crocodiles/1/');
sleep(1); // 1초 대기
}
K6.json
아래의 첨부파일을 다운 받으시고 제 폴더 구조랑 똑같이 만드시면 됩니다.
이 파일은 k6 성능 테스트 결과를 Prometheus에서 가져와 Grafana에서 시각화하는 대시보드 설정입니다.
결과
여기까지 오셨다면 도커를 실행해주면 됩니다.
// 터미널에서 입력
docker-compose up -d
localhost:3000으로 들어오시면 그라파나를 보실 수 있습니다.
여기서 반드시 하셔야 하는게 데이터 소스를 넣어줘야 합니다.
도커로 프로메테우스를 실행하는 경우에는 아래처럼 prometheus:9090으로 하시고,
로컬로 실행하시면 localhost:9090으로 해주셔야 에러가 안 납니다.
대시보드 항목을 선택하시면 아래와 같이 우리가 설정한 대시보드가 나와있는 것을 볼 수 있습니다.
아래와 같이 잘 나오는 것을 확인할 수 있습니다.
'개발' 카테고리의 다른 글
소프트웨어 마에스트로 16기 합격 후기 (0) | 2025.03.31 |
---|---|
[MySQL] SQL 기본 문법 정리 (0) | 2025.01.04 |
[Spring] Redis 써서 JWT 토큰 캐시에 저장하기 (0) | 2024.11.24 |
[Spring] Spring Security, OAuth 2.0, JWT로 카카오 로그인 구현하기 (0) | 2024.11.22 |
[배포] Docker, spring을 통한 무중단 배포 구현 (2) | 2024.10.16 |