본문 바로가기
개발

[Infra] Prometheus & Grafana & K6를 이용한 모니터링 한방 정리

by 주주병 2025. 1. 31.
728x90
반응형

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 형태로 데이터를 노출할 뿐,
      이를 장기적으로 저장하거나 분석할 수 있는 기능이 없습니다.
  • 알람(Alert) 기능이 없음
    • 서버에서 장애가 발생하더라도 자동으로 알람을 보내는 기능이 없습니다.
    • 운영자가 직접 /actuator/health 같은 엔드포인트를 수동으로 확인해야 합니다.
  • 시각화 기능 부족
    • Actuator는 JSON 형식으로 데이터를 반환하기 때문에,
      데이터를 직관적으로 분석하기 어렵습니다.
    • 차트나 그래프 형태로 시각화하려면 별도의 툴이 필요합니다.

💡해결책

Actuator는 애플리케이션 내부 정보를 제공하는 역할을 하지만,

이를 효과적으로 활용하려면 Prometheus 및 Grafana와 함께 사용하는 것이 필수적입니다.

 

Prometheus란?

Prometheus시계열 데이터를 수집하고 저장하는 모니터링 도구입니다.

 

Prometheus의 주요 특징

  1. 실시간 메트릭 수집 (Pull 방식)
    • 애플리케이션에서 직접 데이터를 푸시하는 것이 아니라,
      Prometheus가 주기적으로 /actuator/prometheus 엔드포인트에서 데이터를 가져오는 방식입니다.
  2. 강력한 시계열 데이터 저장 기능
    • Actuator는 현재 상태만 제공하지만,
      Prometheus는 데이터를 저장하여 과거 기록을 분석할 수 있습니다.
  3. PromQL을 활용한 데이터 분석 가능
    • Prometheus는 PromQL이라는 자체 쿼리 언어를 제공하여 데이터를 분석할 수 있습니다.
  4.  자동화된 알람(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

 

 

 

K6HTTP 부하 테스트를 수행하는 도구로, 애플리케이션의 성능을 평가할 수 있습니다.

  • command: run -o experimental-prometheus-rw /scripts/output_test.js
    K6가 부하 테스트를 실행하고 결과를 Prometheus로 보낸다는 코드입니다.
  • volumes 설정을 통해 부하 테스트 스크립트(output_test.js)를 컨테이너 내부로 마운트하여 실행할 수 있도록 합니다.

environment 설정을 통해서 k6Prometheus의 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에서 시각화하는 대시보드 설정입니다.

K6.json
0.05MB

 

 

결과

여기까지 오셨다면 도커를 실행해주면 됩니다.

// 터미널에서 입력
docker-compose up -d

 

localhost:3000으로 들어오시면 그라파나를 보실 수 있습니다.

여기서 반드시 하셔야 하는게 데이터 소스를 넣어줘야 합니다.

 

도커로 프로메테우스를 실행하는 경우에는 아래처럼 prometheus:9090으로 하시고,

로컬로 실행하시면 localhost:9090으로 해주셔야 에러가 안 납니다.

 

대시보드 항목을 선택하시면 아래와 같이 우리가 설정한 대시보드가 나와있는 것을 볼 수 있습니다.

 

아래와 같이 잘 나오는 것을 확인할 수 있습니다.

 

728x90
반응형