Skip to content

TIL -2025-05-27 [Spring Boot 모니터링 통합 실습: Prometheus, AlertManager, Grafana, Slack 연동, On-Premise] #76

@soheeGit

Description

@soheeGit

📌 Spring Boot 모니터링 통합 실습: Prometheus, AlertManager, Grafana, Slack 연동

0. 사전 설정: Micrometer 기반 사용자 정의 메트릭 노출

package org.example.bootfromcompose;

import io.micrometer.core.annotation.Counted;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CountedController {

    @Counted(
            value = "give_me_money",
            description = "부자가 되고 싶어요")
    @GetMapping("/counted")
    public String getCounted() {
        return "Counted OK";
    }

    @GetMapping("/error")
    public ResponseEntity<Void> getError() {
        return ResponseEntity.status(500).build();
    }
}
  • /counted: 호출 시 give_me_money_total이라는 메트릭을 1씩 증가

1. application.yml 설정

spring:
  application:
    name: boot-from-compose
management:
  endpoints:
    web:
      exposure:
        include: "health,prometheus"
  prometheus:
    metrics:
      export:
        enabled: true
Image

2. Prometheus 설정 (prometheus.yml)

global:
  scrape_interval: 5s

scrape_configs:
  - job_name: 'spring-boot-app'
    static_configs:
      - targets: ['host.docker.internal:8080']
    metrics_path: '/actuator/prometheus'

# Alert Rule 등록
rule_files:
  - "alert.rules.yml"

# AlertManager 연결
alerting:
  alertmanagers:
    - static_configs:
        - targets: ['host.docker.internal:9093']
  • host.docker.internal 은 Docker 컨테이너가 호스트의 8080 포트로 접근하도록 설정함
  • prometheus.yml, alert.rules.yml은 ./prometheus/ 폴더에 위치시킨다.

3. AlertManager 설정 (alertmanager.yml)

route:
  receiver: slack

receivers:
  - name: slack
    slack_configs:
      - api_url: "<SLACK_WEBHOOK_URL>"
        channel: 'alert'
        send_resolved: true
        text: "{{ .CommonAnnotations.summary }} - {{ .CommonAnnotations.description }}"
  • Slack Webhook 연동을 통해 알림 전송 설정

4. 알림 조건 설정 (alert.rules.yml)

groups:
  - name: give_me_money
    rules:
      - alert: give_me_money
        expr: rate(give_me_money_total[10s]) > 10
        for: 10s
        labels:
          severity: warning
        annotations:
          summary: "give_me_money"
          description: "돈 주세요"
  • give_me_money_total이 초당 10 이상이면 경고 발송

5. 테스트 스크립트 (test.sh)

#!/bin/bash

success_count=0
fail_count=0

for i in {1..10000}; do
  if (( RANDOM % 2 )); then
    curl -s http://localhost:8080/counted > /dev/null
    ((success_count++))
    echo "[${i}/10000] Success: counted endpoint (Total: ${success_count})"
  else
    curl -s http://localhost:8080/error > /dev/null
    ((fail_count++))
    echo "[${i}/10000] Failure: error endpoint (Total: ${fail_count})"
  fi
  sleep 1
done

echo "Test complete: ${success_count} successes, ${fail_count} failures."
echo "Checking Prometheus metrics..."
curl -s http://localhost:8080/actuator/prometheus | grep give_me_money_total

6. Docker 컨테이너 실행

# 기존 컨테이너 제거 (필요 시)
docker rm -f prometheus alertmanager

# Prometheus 실행
docker run -d -p 9090:9090 \
  -v ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml \
  -v ./prometheus/alert.rules.yml:/etc/prometheus/alert.rules.yml \
  --name prometheus \
  prom/prometheus:latest

# AlertManager 실행
docker run -d -p 9093:9093 \
  -v ./prometheus/alertmanager.yml:/etc/alertmanager/config.yml \
  --name alertmanager \
  prom/alertmanager:latest

sh test.sh
  • 만약 권한 오류가 난다면 ${pwd] 대신 절대 경로를 사용해야 권한 오류가 발생하지 않는다.

7. 확인 포인트

항목 주소 또는 명령어
Prometheus UI http://localhost:9090
AlertManager UI http://localhost:9093
Spring Boot Actuator http://localhost:8080/actuator/prometheus
테스트 실행 sh test.sh
Image Image Image

8. Grafana 설정

docker run -d -p 3000:3000 --name grafana grafana/grafana:latest
# localhost:3000
Image
  1. 데이터 소스 연결
Image
  1. 대시보드 생성
  • Dashboards → Create → Add Visualization
  • Prometheus 선택
Image
  • 원하는 메트릭 (give_me_money_total 등) 입력해 시각화

9. docker-compose

# Stage 1: Build
FROM azul/zulu-openjdk:17-latest AS build
WORKDIR /app

# 그래들 파일 복사 및 의존성 캐싱
COPY gradlew .
COPY gradle gradle
COPY build.gradle settings.gradle ./
RUN chmod +x ./gradlew

# 소스 코드 복사 및 빌드
COPY src src
RUN ./gradlew build -x test

# Stage 2: Runtime
FROM azul/zulu-openjdk:17-latest
WORKDIR /app

# 빌드 스테이지에서 JAR 파일만 복사
COPY --from=build /app/build/libs/*.jar app.jar

EXPOSE 8080

# Spring 프로필을 'prod'로 설정
ENV SPRING_PROFILES_ACTIVE=prod

ENTRYPOINT ["java", "-jar", "app.jar"]
  • docker-compose.yml
services:
  app:
    build: . # Dockerfile
    ports:
      - "8080:8080" # 외부로 Open
    networks:
      - prom

  prometheus:
    image: prom/prometheus:latest
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - ./prometheus/alert.rules.yml:/etc/prometheus/alert.rules.yml
    ports:
      - "9090:9090"
    networks:
      - prom

  alertmanager:
    image: prom/alertmanager:latest
    volumes:
      - ./prometheus/alertmanager.yml:/etc/alertmanager/alertmanager.yml
    ports:
      - "9093:9093"
    networks:
      - prom

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    networks:
      - prom

networks:
  prom:
  • prometheus.yml 변경
global:
  scrape_interval: 5s

scrape_configs:
  - job_name: 'spring-boot-app'
    static_configs:
#      - targets: ['host.docker.internal:8080'] # intellj로 실행 중이거나 별도 네트워크 없이 직접 연결하겠다
      - targets: ['app:8080'] # 네트워크에서 컨테이너 이름으로 연결하겠다
    metrics_path: '/actuator/prometheus'

# alert manager

rule_files:
  - "alert.rules.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['alertmanager:9093']
  • bash
docker compose up -d
sh test.sh

📌 On-Premise

기업이나 조직이 자체 데이터 센터 또는 서버에 직접 설치하여 운영하는 방식
클라우드(AWS, Azure 등)의 반대 개념

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions