Prometheus & Grafana를 통한 메트릭 모니터링 시스템 구축하기 - 모니터링 시스템 구축기 (1)

개요
회사에 합류하여 곧장 어드민 페이지와 모니터링 시스템 구축 업무를 맡게 되었다. 서비스가 이제 막 출시된 상태에서 운영을 위해서는 두 시스템 모두 중요하며, 특별히 모니터링 시스템을 통해 서버가 여러가지 방면으로 이상은 없는지 확인할 수 있고, 큰 일이 발생하기 전 예방할 수 있다.
이번 글에서는 서버 메트릭 모니터링 시스템을 구축하는 과정을 공유해보려 한다.
메트릭이란?
메트릭이란 무언가를 측정하기 위한 기준이나 지표를 말한다. 그렇다면 소프트웨어에서 메트릭은 상태를 나타내는 수치를 말하며, 예로 CPU 사용률이나 서버 응답 평균 시간, 에러 발생 횟수 등이 있을 것이다.
메트릭을 실시간으로 수집함으로써, 서버의 상태를 체크하고 장애 시 대응 혹은 예방할 수 있을 것이다.
목표
현재 서버는 이중화되어있다. 2개의 운영 서버에 대해서 각각의 메트릭을 수집하고, 대시보드를 구축하려 한다.
시스템 구축을 위한 기술로는 Prometheus & Grafana를 선정하였다. 이전에 가볍게 학습하며 그나마 익숙한 스택이기도 하였고, 무엇보다 레퍼런스가 많아 구축 과정에서 참고할 자료들이 많다는 것도 한 몫 하였다.
액츄에이터(Actuator)
서버에 문제가 없는지에 대해 감시하고 데이터화 하여 메트릭으로 만들어 줄 주체가 필요하다. Spring은 액츄에이터를 통해 이러한 기능을 편리하고 다양하게 제공한다.
implementation 'org.springframework.boot:spring-boot-starter-actuator'
먼저 build.gradle 파일에 다음과 같은 의존성을 추가하자.
management:
# 액츄에이터 포트 분리
server:
port: 9292
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
# 더 많은 기능을 웹 환경에서 보이고 싶을 경우
# include: "*"
application.yaml 파일에 다음과 같은 설정을 추가하자. include 항목에 필요한 메트릭에 대해서 찾아보고 커스텀하게 설정하면 될 것 같다. 액츄에이터 포트를 분리하여, 내부망에서만 접근하도록 설정할 수도 있다.
/actuator 경로로 이동하면 아래와 같이 제공되는 기능을 확인할 수 있다.

특별히 /actuator/metrics 기능을 통해서 spring 서버의 CPU, JVM, 톰캣 등 중요한 메트릭들을 제공한다.
마이크로미터(micrometer)
액츄에이터를 통해 서버 어플리케이션을 감시하여 메트릭으로 조회할 수 있었다. 이제 메트릭을 조회할 수 있는 모니터링 툴로 전달한다면, 사용자는 메트릭을 조회할 수 있을 것이다. 그러기 위해서는 모니터링 툴에 형식에 맞춰 메트릭을 변환하여야 한다.

마이크로미터는 어플리케이션의 메트릭 수집을 추상화한 라이브러리이다.
어플리케이션이 제공하는 메트릭은 여러 모니터링 툴에서 사용될 수 있으며, 모니터링 툴마다 전달해야하는 형식이 다를 수 있다. 마이크로미터를 통해 개발자는 정해진 표준 방법으로 메트릭을 전달하면 된다.
implementation 'io.micrometer:micrometer-registry-prometheus'
마이크로미터에서 제공하는 프로메테우스 의존성을 추가하여, 메트릭을 프로메테우스 표준 형식으로 출력할 수 있다.
다음 의존성을 추가하면, /actuator/prometheus api를 제공한다. 해당 api를 통해서 /actuator/metrics의 정보를 프로메테우스 표준에 맞게 출력해준다.
프로메테우스(Prometheus)
지금까지 어플리케이션에서 메트릭을 수집하고, 프로메테우스 표준 형식으로 출력하도록 하였다. 그렇다면 이제 프로메테우스에서 해당 메트릭을 수집하도록 해보자!
프로메테우스는 서버의 메트릭을 스크래핑(Scraping)한다.
스크래핑이란 polling 방식과 비슷하게 주기적으로 서버에 HTTP 요청을 보내는 방식이다. 요청 URL은 마이크로미터 의존성을 추가할 때 제공된 /actuator/prometheus api로 보내서 메트릭을 수집한다. 제공된 메트릭은 프로메테우스가 시계열 DB에 저장하게 된다.
docker run -d --name prometheus-container -p 9090:9090 prom/prometheus
프로메테우스는 docker를 이용하여 실행하였다.
services:
prometheus-container:
image: prom/prometheus:latest
container_name: prometheus-container
ports:
- "9090:9090"
volumes:
## 프로메테우스 설정 파일
- /home/ubuntu/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
## 수집한 시계열 데이터
- /home/ubuntu/prometheus/data:/prometheus
restart: unless-stopped
docker compose로도 당연히 가능하다. 설정파일과 시계열 데이터를 저장하는 디렉토리와 설정파일은 볼륨을 설정하여 휘발되지 않게 하자.
global:
scrape_interval: 15s #스크래핑 주기
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
rule_files:
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
# 스크래핑 job 설정
- job_name: "spring-actuator"
metrics_path: '/actuator/prometheus' # 메트릭 제공 주소
scrape_interval: 30s #스크래핑 주기 개별 설정
static_configs:
# 스크래핑 대상 서버
- targets: ['[ip]:8080'] # 스크래핑 대상 주소
labels:
application: "prod"
instance: "server-1"
- targets: ['[ip]:8080'] # 스크래핑 대상 주소
labels:
application: "prod"
instance: "server-2"
- targets: ['172.31.37.24:8080'] # 스크래핑 대상 주소
labels:
application: "dev"
instance: "server"
프로메테우스 관련 설정파일이다. 경로는 컨테이너 내의 /etc/prometheus/prometheus.yml 이다.
스크래핑 주기를 15초로 설정하였고, 하나의 job에서 2개의 서버 메트릭을 수집하도록 설정하였다.
또한 우리는 앞서 액츄에이터와 마이크로미터를 통해 프로메테우스에서 메트릭을 수집할 수 있으며, 설정 파일의 metrics_path를 통해 메트릭을 제공하는 주소를 설정해준다. 필자는 운영 서버 2대, 개발 서버 1대의 메트릭을 수집하도록 설정하였다.
application, label 필드를 통하여 서버를 구분하여 메트릭을 조회할 수 있다.
변경된 수정파일을 적용하기 위해, 프로메테우스를 재시작하자.
프로메테우스가 실행된 ip와 port로 /config url을 접속한다면, 아래와 같이 prometheus 관련 설정을 조회할 수 있다.

/targets url을 접속한다면, 스크래핑 대상 서버들을 조회할 수 있다.

보안에 문제가 될 수 있기에 보안 그룹을 통해서 특정 ip에서만 접속할 수 있도록 보안을 철저히 하도록 하자.
그라파나(Grafana)
지금까지 서버의 메트릭을 측정하고, 프로메테우스에서 출력 형식에 맞춰 지속적으로 수집하도록 하였다.
그라파나(Grafana)는 프로메테우스가 수집한 데이터에 대한 출력하는 대시보드 툴이다.

docker run -d --name grafana -p 3000:3000 grafana/grafana
그라파나 docker 실행 명령어이다.
services:
grafana-container:
image: grafana/grafana:latest
container_name: grafana-container
ports:
- "3000:3000"
volumes:
## 그라파나 설정
- /home/ubuntu/grafana/data:/var/lib/grafana
- /home/ubuntu/grafana/grafana.ini:/etc/grafana/grafana.ini
restart: unless-stopped
필자는 docker compose를 통해 실행하였다. UI 관련 설정한 데이터 및 설정 파일을 볼륨으로 설정하자.

그라파나를 실행한 port로 접속하게 되면, 로그인 창이 나온다. 초기에는 아이디와 패스워드 모두 admin으로 하고 로그인을 시도하자
그 후, 비밀번호 변경은 skip 한다.

프로메테우스를 연결하여 메트릭을 조회해보자.
좌측 사이드바에서 Connections -> Add new connection에서 Prometheus를 선택한다.

그 후, data source를 추가해준다.

프로메테우스 엔드포인트만 잘 설정해주자.
대시보드 툴은 우리가 직접 구성할 수도 있지만, Grafana Labs에 다양한 라이브러리를 이용하는 것이 더 편리하다.
내가 이용한 대시보드 툴의 라이브러리 번호는 11378이다.

대시보드 페이지에서 Import 버튼을 통해 대시보드 생성 페이지로 이동한다.
그 후, 라이브러리 번호를 입력하고, 우리가 설정한 prometheus datasource로 선택한다.
결과
서버에 대한 메트릭을 시각화하여 조회할 수 있게 되었다.
좌측 상단의 뿐만 아니라 필터링을 통해 여러 서버들에 대해 하나를 선택하여 메트릭을 조회할 수도 있다.

현재까지 아키텍처는 다음과 같다. 프로메테우스에서 각 서버의 메트릭을 수집하고 개발자는 그라파나를 통해 각 서버의 메트릭을 실시간으로 조회할 수 있다.
추후보완 사항
지금까지 Prometheus & Grafana를 통해서 서버의 메트릭을 수집하고 대시보드로 조회할 수 있도록 시스템을 구축하였다.
이 후 글에서는 서버 이외에 컴포넌트인 DB와 프록시 서버에 대한 메트릭을 수집하여 연결해보자.