모니터링은 애플리케이션의 성능과 안정성을 유지하기 위해 필수적인 요소입니다. 서버의 상태를 실시간으로 파악하고, 성능 이슈를 사전에 감지하여 대응할 수 있게 해 줍니다. 이를 통해 서비스의 가용성을 높이고, 안정적인 서비스를 운영할 수 있습니다. 이번 글에서는 Spring Boot 애플리케이션에 Spring Actuator를 추가하고, Prometheus와 Grafana를 사용하여 모니터링을 설정하는 방법을 알아보겠습니다.
모니터링 정보
모니터링을 하면서 수집하는 주요 정보는 시스템이나 애플리케이션의 상태, 성능 및 동작을 평가하는 데 사용되는 모든 종류의 데이터를 포함한다. 여기에는 metric, log, trace, event 등의 다양한 데이터가 포함될 수 있다.
모니터링 정보의 구성 요소
- metric: 시스템 또는 애플리케이션의 성능, 상태 및 동작을 수량화한 데이터 포인트로, CPU 사용량, 메모리 사용량, HTTP 요청 수, 응답 시간, GC(Garbage Collection) 횟수가 포함될 수 있다.
- log: 애플리케이션이나 시스템에서 발생한 이벤트에 대한 기록. 예를 들어, 오류 로그, 트랜잭션 로그 등이 포함된다.
- trace: 분산 시스템에서 요청이 어떻게 흐르는지를 추적하는 정보가 포함된다. 예를 들어, 마이크로서비스 아키텍처에서 요청이 여러 서비스 간에 어떻게 전달되는지 추적하는 것
- event: 시스템이나 애플리케이션에서 발생한 특정 이벤트. 예를 들어, 사용자 로그인 이벤트, 데이터베이스 커넥션 이벤트 등이 포함된다.
Spring Actuator
Spring Actuator는 Spring Boot 애플리케이션의 다양한 운영 정보를 제공하는 툴이다. 주로 애플리케이션의 상태를 모니터링하고, 운영 시에 유용한 metric과 진단 정보를 제공한다. 이러한 정보는 엔드포인트마다 노출되는 것이 다르다.
Actuator를 통해 노출되는 엔드포인트는 일반적으로 다음과 같은 정보를 포함할 수 있다.
헬스 체크(Health Check): /actuator/health
- 애플리케이션의 전반적인 건강 상태를 확인할 수 있습니다. 기본적으로 "UP" 또는 "DOWN" 상태를 반환하며, 데이터베이스 연결 상태나 디스크 공간 등 추가적인 health indicator를 구성할 수 있다.
메트릭(Metrics): /actuator/metrics
- CPU 사용량, 메모리 사용량, HTTP 요청 수 등 다양한 성능 지표를 제공한다. 특정 메트릭의 상세 정보를 확인하려면 /actuator/metrics/{metric.name} 엔드포인트를 사용할 수 있다.
정보(Info): /actuator/info
- 애플리케이션의 빌드 정보, 버전, 커스텀 데이터 등을 제공하며, 주로 application.properties 또는 application.yml 파일을 통해 설정된다.
환경(Environment): /actuator/env
- 애플리케이션의 환경 설정 및 프로필 정보를 제공한다. 특정 환경 변수를 확인하려면 /actuator/env/{name} 엔드포인트를 사용할 수 있다.
로거(Logger): /actuator/loggers
- 애플리케이션 내에서 사용되는 로거의 설정과 로그 레벨 정보를 제공한다. 특정 로거의 로그 레벨을 확인하거나 변경할 수 있다.
주의할 점은, 서버에 대한 민감한 정보를 노출할 수 있는 엔드포인트가 포함되어 있기 때문에, 보안적으로 심각한 문제를 야기 할 수 있다. 따라서 민감한 정보를 노출할 수 있는 엔드포인트를 비활성화하거나, Spring security에서 /actuator 엔드포인트에 대한 authentication, authorization을 추가하는 등의 조치가 필요하다.
아래 코드는 application.yml 에서 env, loggers, threaddump, heapdump 노출을 포함하지 않는 설정이다.
management:
endpoints:
web:
exposure:
exclude: env,loggers,threaddump,heapdump
Gradle 추가
build.gradle
implementation 'org.springframework.boot:spring-boot-starter-actuator'
Gradle 설정
application.yml
management:
endpoints:
web:
exposure:
include: health,info,metrics,env,loggers
endpoint:
health:
show-details: always
이 설정은 특정 Actuator 엔드포인트만 웹에서 접근할 수 있도록 노출한다. 여기서는 health, info, metrics, env, loggers 엔드포인트가 포함되어 있다.
또한 /actuator/health가 항상 상세 정보를 포함하도록 한다. 기본적으로는 health chacke 엔드포인트가 간단한 "UP" 또는 "DOWN" 상태를 반환하지만, 이 설정을 통해 추가적인 상세 정보를 확인할 수 있다.
Spring Actuator 예제
기본적인 엔드포인트 형식은 http://{server}:{port}/actuator
이다.
예를 들어, http://localhost:8080/actuator
접속 시 사용 가능한 엔드포인트 목록들이 나온다.
{
"_links": {
"self": {
"href": "http://localhost:8080/v1/actuator",
"templated": false
},
"health-path": {
"href": "http://localhost:8080/v1/actuator/health/{*path}",
"templated": true
},
"health": {
"href": "http://localhost:8080/v1/actuator/health",
"templated": false
},
"info": {
"href": "http://localhost:8080/v1/actuator/info",
"templated": false
},
"env": {
"href": "http://localhost:8080/v1/actuator/env",
"templated": false
},
"env-toMatch": {
"href": "http://localhost:8080/v1/actuator/env/{toMatch}",
"templated": true
},
"loggers": {
"href": "http://localhost:8080/v1/actuator/loggers",
"templated": false
},
"loggers-name": {
"href": "http://localhost:8080/v1/actuator/loggers/{name}",
"templated": true
},
"metrics-requiredMetricName": {
"href": "http://localhost:8080/v1/actuator/metrics/{requiredMetricName}",
"templated": true
},
"metrics": {
"href": "http://localhost:8080/v1/actuator/metrics",
"templated": false
}
}
http://localhost:8080/actuator/metrics
를 접속하면 아래와 같은 정보가 출력된다.
{
"names": [
"application.ready.time",
"application.started.time",
"disk.free",
"disk.total",
"executor.active",
"executor.completed",
"executor.pool.core",
"executor.pool.max",
"executor.pool.size",
"executor.queue.remaining",
"executor.queued",
"hikaricp.connections",
"hikaricp.connections.acquire",
"hikaricp.connections.active",
...
}
Prometheus
Prometheus는 시계열 데이터베이스(TSDB)로, 모니터링과 경고(alerting)를 목적으로 데이터를 수집하고 쿼리 할 수 있는 시스템이다. Prometheus는 주로 애플리케이션, 서버, 데이터베이스 등 다양한 시스템의 성능 메트릭을 수집하고 모니터링하는 데 사용된다.
Prometheus의 주요 특징은 다음과 같다.
- 멀티차원 데이터 모델: 메트릭을 라벨(label)로 구분하여 저장
- 쿼리 언어: PromQL을 사용하여 데이터를 쿼리하고 분석
- 자체 수집(pulling): HTTP를 통해 대상의 메트릭을 주기적으로 가져옴
- 알림 기능: 조건에 맞는 경고를 설정하고 알림을 보낼 수 있음
Prometheus의 주요 구성 요소
- Prometheus 서버:
- 메트릭 데이터를 수집하고 저장하는 핵심 컴포넌트이다. 각 타겟으로부터 데이터를 주기적으로 스크랩(scrape)하여 시계열 데이터베이스에 저장한다.
- 시계열 데이터베이스(Time Series Database, TSDB)는 시간에 따라 변화하는 데이터를 효율적으로 저장하고 조회할 수 있도록 최적화된 데이터베이스이다.
- Exporters:
- Prometheus는 기본적으로 애플리케이션에서 메트릭 데이터를 수집한다.
- Exporter는 특정 애플리케이션이나 시스템의 메트릭 데이터를 Prometheus가 이해할 수 있는 형식으로 변환해주는 도구이다.
- 예시: Node Exporter (서버의 시스템 메트릭 수집), PostgreSQL Exporter (PostgreSQL 메트릭 수집), Spring boot의 micrometer-registry-prometheus dependency
- Pushgateway:
- 짧은 수명의 작업(job)에서 메트릭을 수집하여 Prometheus 서버에 푸시(push)할 수 있다.
- 일반적으로 지속적으로 실행되지 않는 작업에서 사용됩니다. 예를 들어 배치 작업, 스크립트 실행, 크론 작업 등이 있다.
- Alertmanager:
- Prometheus 서버에서 발생하는 경고(alert)를 처리하고, 이메일, PagerDuty, Slack 등 다양한 방법으로 알림을 보낼 수 있다.
- Grafana:
- Prometheus 데이터를 시각화하기 위해 자주 사용되는 대시보드 도구이다.
- Grafana를 사용하면 Prometheus에서 수집한 메트릭 데이터를 대시보드 형태로 시각화할 수 있다.
Prometheus 설정
Prometheus를 사용하려면 gradle에는 아래와 같이 추가한다.
implementation 'io.micrometer:micrometer-registry-prometheus'
Micrometer는 JVM 기반 애플리케이션의 성능 metric을 수집하는 라이브러리로, Spring Boot 2.x 이상에서 기본적으로 지원된다. Micrometer는 다양한 모니터링 시스템과의 통합을 지원하며, Prometheus도 그중 하나이다.
Spring Actuator와 혼동될 수 있는데, Spring Actuator는 애플리케이션의 상태와 정보를 엔드포인트로 제공하는데 중점을, Micrometer는 metric을 수집하고 다양한 모니터링 시스템과 통합하는데 중점을 둔다.
Prometheus는 애플리케이션의 성능 데이터를 수집하여 저장하고 분석한다. 이를 위해서는 Spring Boot 애플리케이션이 Prometheus와 통신할 수 있는 metric 엔드포인트를 노출해야 한다.
따라서 Spring에 application.yml에 prometheus에 노출할 엔드포인트를 추가해주어야 한다.
management:
endpoints:
web:
exposure:
include: health,info,metrics,env,loggers,prometheus # prometheus 추가
endpoint:
health:
show-details: always
Prometheus를 설정하기 위해 yml을 생성하여 Prometheus 서버의 동작을 정의할 수 있다. 다음은 설정 파일의 예시이다.
global:
scrape_interval: 15s
external_labels:
monitor: 'the-survey-monitor'
scrape_configs:
- job_name: 'prometheus'
metrics_path: 'v1/actuator/prometheus'
static_configs:
- targets: ['host.docker.internal:8080']
global:
- scrape_interval: Prometheus가 메트릭을 수집하는 주기를 15초로 설정한다.
- external_labels: 모든 메트릭에 추가될 레이블을 설정한다. 여기서는 monitor 레이블을 the-survey-monitor 값으로 설정한다.
scrape_configs:
- job_name: 수집 작업의 이름을 prometheus로 설정한다.
- metrics_path: 메트릭을 수집할 경로를 v1/actuator/prometheus로 설정한다. 이는 Spring Actuator의 Prometheus 엔드포인트이다.
- static_configs: targets: metric을 수집할 대상의 주소를 설정한다. 여기서는 host.docker.internal:8080으로, Docker 컨테이너 내부에서 Local 머신의 Spring Boot 애플리케이션에 접근하기 위한 주소이다.
이 설정을 통해 Prometheus는 Spring Boot 애플리케이션에서 노출된 Actuator metric을 15초 간격으로 수집하게 된다.
Prometheus Docker 설정
Prometheus를 설정하기 위해 Docker와 Docker Compose를 사용할 수 있습니다. 다음은 Docker Compose 파일의 일부 예시이다.
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./config/prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
여기서 local에 ./config/prometheus.yml 설정 파일을 컨테이너의 /etc/prometheus/prometheus.yml 위치에 매핑한다.
Prometheus에서 Spring Actuator 메트릭 쿼리 예제
Docker에서 Prometheushttp://localhost:9090/
에 접속하면 아래와 같은 페이지에 접속된다.
Status -> Targets를 클릭하면 Spring Actuator와의 연결 상태를 확인할 수 있다.
다시 main 화면으로 돌아와서, expression에서 쿼리문을 입력하면 그 데이터의 대한 정보를 얻을 수 있다.
아래는 쿼리 예제들이다.
- JVM 메모리 사용량 조회
JVM 메모리 사용량을 조회하는 쿼리이다. Spring Boot Actuator는 기본적으로 JVM 관련 메트릭을 노출한다.
- 총 JVM 메모리 사용량: jvm_memory_used_bytes
- Heap 메모리 사용량: jvm_memory_used_bytes{area="heap"}Non-Heap 메모리 사용량: jvm_memory_used_bytes{area="nonheap"}
- GC(Garbage Collection) 활동 조회
GC 활동을 모니터링하는 쿼리이다.
- GC 횟수: jvm_gc_collection_seconds_count
- GC 시간: jvm_gc_collection_seconds_sum
- HTTP 요청 관련 메트릭 조회
Spring Boot Actuator는 기본적으로 HTTP 요청 관련 메트릭을 제공한다.
- HTTP 요청 수: http_server_requests_seconds_count
- HTTP 요청 처리 시간: http_server_requests_seconds_sum
- HTTP 상태 코드별 요청 수: http_server_requests_seconds_count{status="200"}
- 스레드 관련 메트릭 조회
애플리케이션의 스레드 상태를 모니터링하는 쿼리이다.
- 활성 스레드 수: jvm_threads_live_threads
- 데몬 스레드 수: jvm_threads_daemon_threads
- CPU 사용량 조회
- CPU 사용량: system_cpu_usage
Grafana
Grafana는 오픈 소스 시각화 도구로, 데이터 소스에서 데이터를 가져와 대시보드를 생성하고 시각화할 수 있다.
Grafana의 주요 특징은 다음과 같다.
- 다양한 데이터 소스 지원: Prometheus, InfluxDB, Graphite, Elasticsearch 등
- 풍부한 시각화 옵션: 그래프, 차트, 히트맵 등 다양한 시각화 도구 제공
- 대시보드 공유 및 관리: 대시보드를 쉽게 공유하고, 관리할 수 있는 기능 제공
- 경고(alerting): 특정 조건에 따라 알림을 설정하고, 다양한 채널로 알림을 보낼 수 있음
Grafana는 Prometheus와 함께 사용하여 수집된 metric을 시각화하고, 직관적인 대시보드를 통해 시스템의 상태를 모니터링할 수 있다.
Grafana 설정
Grafana를 Docker에서 사용하기 위해 다음과 같은 Docker Compose를 작성했다.
grafana:
image: grafana/grafana:latest
container_name: grafana
user: "${UID}:${GID}"
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- ./grafana:/var/lib/grafana
depends_on:
- prometheus
user: "${UID}:${GID}"의 경우 Grafana 컨테이너가 특정 사용자 및 그룹 ID로 실행되도록 지정하는 설정이다. 기본적으로 컨테이너는 root 사용자로 실행되며, 이는 보안 위험을 초래할 수 있다. 따라서 컨테이너가 필요 이상으로 많은 권한을 가지지 않도록 한다.
${UID}와 ${GID}는 쉘이나 환경 파일에 정의되어야 하는 환경 변수인데, 이는 호스트 머신의 사용자의 사용자 ID와 그룹 ID를 나타낸다.
이 기능을 사용하려면 UID와 GID 환경 변수를 쉘이나. env 파일에 설정한 후 docker-compose를 실행해야 한다.
예를 들어,
export UID=$(id -u)
export GID=$(id -g)
docker-compose up -d
또는 다음과 같은 내용을 가진 .env 파일을 만들어서 사용할 수 있다.
UID=1000
GID=1000
그런 다음 docker-compose를 실행하면 ${UID}와 ${GID}가 실제로 정의된 사용자 및 그룹 ID로 대체된다.
Grafana 모니터링 데이터가 사라지지 않도록 Volume을 local 경로와 매핑하였다.
Grafana 사용 예시
1. Grafana에 로그인
브라우저에서 http://localhost:3000로 접속하여 Grafana에 로그인한다. 기본 사용자 이름과 비밀번호는 admin/admin이다.
2. 데이터 소스 추가
사이드바에서 "Connections" -> "Data Sources"를 클릭하고, "Add data source"를 클릭한다. "Prometheus"를 선택한 후,
URL에 http://host.docker.internal:9090 입력하고 (prometheus의 docker container url) 아래에 "Save & Test"를 클릭한다.
참고로 http://host.docker.internal는 Docker 컨테이너에서 호스트 머신에 접근할 수 있도록 하기 위해 사용되는 특별한 DNS이다. 이 주소를 사용하면 컨테이너가 실행되고 있는 호스트 머신에 쉽게 접근할 수 있다.
컨테이너에서 호스트 머신에서 실행 중인 데이터베이스, 웹 서버 또는 기타 서비스에 접근해야 할 때나, 로컬 개발 환경에서 컨테이너가 호스트의 자원에 접근해야 하는 경우 사용된다.
3. Dashboard 생성
Grafana Labs에 접속하여 spring boot를 검색한다. Spring boot와 관련된 Dashboard들이 나온다.
Spring boot 2.1 System Monitor를 선택하고 우측에 Copy Id를 클릭한다.
참고로 회원가입은 필요 없다.
다시 Grafana 페이지로 돌아와서, Dashboard Import를 클릭한 후 복사한 Id를 입력하면 Dashboard를 Import 할 수 있다.
적용된 모습은 위와 같다.
마치며
요약하자면 Spring Actuator는 엔드포인트로 애플리케이션의 모니터링 데이터를 노출한다.
Spring Actuator가 노출한 데이터를 Prometheus가 일정 주기로 엔드포인트에서 메트릭 데이터를 수집한다.
Prometheus에서 수집한 데이터를 Grafana가 받아서 시스템 상태와 성능을 시각적으로 표현해 준다.
이러한 Spring 모니터링 시스템을 구축한 이후, 부하 테스트를 통해 서버의 성능을 평가하고 최적화 방안을 마련하는 것이 중요하다. 부하 테스트를 통해 시스템의 병목 현상을 식별하고, 필요에 따라 서버 자원을 확장하거나 설정을 조정하여 안정적인 서비스 운영을 보장할 수 있도록 해야 한다. 지속적인 모니터링과 테스트를 통해 시스템의 가용성을 높이고, 예상치 못한 트래픽 증가에도 유연하게 대응할 수 있도록 서버 관리 방안을 고민해야겠다.
참고
'Development > Spring' 카테고리의 다른 글
[Spring] MSA와 Spring Cloud (1) | 2024.07.31 |
---|---|
[Spring] MVC 패턴과 Spring MVC (0) | 2024.07.22 |
[Spring] Redisson을 활용한 캐시 사용하기 (0) | 2024.07.11 |
[Spring] Gatling 으로 서버 부하 테스트하기 (0) | 2024.07.09 |
[Spring] ThreadLocal에 대해 알아보자 + SecurityContextHolder, RequestContextHolder (0) | 2024.05.28 |