모니터링 환경 구축(Spring actuator, Prometheus, Grafana)

Micrometer

스프링부트 어플리케이션을 구동하면 기본적으로 JAVA 환경에서 돌아가기 때문에 jvm에 관한 정보도 있고 HTTP 통신에 대한 정보, 시스템 환경에 대한 정보 등 다양한 metric 정보들이 생산된다. 우리가 이런 metric 정보를 모니터링 하기 위해서는 모니터링 툴에 맞는 형식으로 정보를 맞춰줘야 하고 또 모니터링 툴에 맞는 API로 전송해야 한다. 이런 것들을 개발자가 모두 제어하기는 어려운 일이다.

 

이런 작업을 추상화한 것이 Micrometer이다. Micrometer를 이용하면 표준 수집형식에 맞게 자동적으로 metric 정보가 수집되고 모니터링 툴에 맞게끔 세팅, 전송하는 역할은 Micrometer의 구현체를 이용할 수 있다.

스프링부트 엑추에이터

스프링부트 엑추에이터는 스프링부트에서 제공하는 metric 수집 라이브러리이다. 해당 기능을 통해 개발자는 metric 수집을 위한 별도의 로직을 짤 필요 없이 편하게 정보를 수집할 수 있다.

 

아래는 의존성 설치 시 필요한 코드이다.

// build.gradle

implementation 'org.springframework.boot:spring-boot-starter-actuator'

스프링 엑추에이터는 metric 정보를 조회하는데 있어 엔드포인트를 제공한다. 설정을 변경하지 않으면 기본 경로는 /actuator 이다. /actuator/health, /actuator/info등으로 접근할 수 있다. /actuator/metrics로 요청하면 스프링 엑추에이터가 제공하는 다양한 metric 정보들을 조회할 수 있다. 스프링 엑추에이터에 대한 설정을 변경하려면 yml 파일에서 변경하면 된다. 아래는 예시이다.

// application.yml

management:
  endpoints:
    enabled-by-default: false # actuator endpoint에 대해 기본적으로 비활성화
    jmx:
      exposure:
        exclude: "*" // jmx라는 micrometer 구현체에 대한 정보는 노출하지 않음.
    web:
      base-path: /monitor # actuator 기본 경로를 설정
      exposure:
        include: prometheus, health # actuator에서 노출할 것
  endpoint: // 엔드포인트 접근 설정
    prometheus:
      enabled: true
    health:
      enabled: true
  server:
    port: 8085 // 엑추에이터에 대한 접근은 다른 포트로 설정
server:
  tomcat:
    mbeanregistry:
      enabled: true // tomcat metric 정보에 대한 추가적인 정보를 조회하도록

프로메테우스(Prometheus)

모니터링 환경을 구축하려면 metric 정보가 데이터베이스에 저장이 되어야 한다. 그래야 그동안의 이력을 확인한다거나 모니터링 서버가 종료돼도 정보가 유지될 수 있다. 그런 역할을 하는 것이 프로메테우스이다.

 

프로메테우스를 사용하기 위해선 일단 모니터링을 할 서버에 설치를 해야 한다. 문서 기준은 회사 내부서버(linux)이고 docker 를 이용하면 편리하게 설치할 수 있다. 아래 명령어를 입력한다.

설치: docker pull prom/prometheus
가동: docker run -d -p 9090:9090 -v /etc/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus

 

가동 명령어를 조금 설명해보자면

  • docker run 이 docker image를 컨테이너로 띄우는 것이다.
  • -d는 백그라운드로 실행하겠다는 옵션
  • -p는 포트 설정이다. 9090:9090은 host의 9090포트로 접근하면 docker 내부의 9090포트로 연결하겠다는 의미이다.
  • -v 는 볼륨 마운트 옵션이고 host의 /etc/prometheus/prometheus.yml 파일을 컨테이너 내부의 /etc/prometheus/prometheus.yml 파일에 마운트 하겠다는 의미이다.
  • prom/prometheus는 docker image 이름이다.

이렇게 하고 서버IP:9090 으로 접속해서 아래 사진처럼 서버가 정상 구동 되는지 확인한다

그리고 프로메테우스가 metric 정보를 수집할 수 있도록 몇가지 작업을 해주어야 한다.

어플리케이션 설정

먼저 metric 정보를 생산하는 어플리케이션에 프로메테우스 형식으로 metric을 생산할 수 있도록 작업을 해주어야 한다. 아주 간단하게 의존성을 추가해주면 된다.

implementation 'io.micrometer:micrometer-registry-prometheus'

 

의존성 설치 후 /기본경로/prometheus 로 요청해보면 아래 사진과 같은 화면이 나타날 것이다.

프로메테우스 설정

그리고 프로메테우스의 설정 파일을 만들어주어야 한다. 임의의 경로에 prometheus.yml 파일을 만들고 해당 파일을 열어보자. 글에서는 /etc/prometheus 디렉토리 하위에 만들어주었다.

global:
  scrape_interval:     5s 
  evaluation_interval: 5s
  
  external_labels:
    monitor: 'label 이름'

rule_files:
  # - "first.rules"
  # - "second.rules"

scrape_configs:
  - job_name: 'spring-actuator'
    metrics_path: 'monitor/prometheus'
    static_configs:
      - targets: ['IP주소:포트']
    scrape_interval: 5s
    scrape_timeout: 5s
    
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

간단하게 설명하자면

  • scrape_interval: 수집 주기 . 기본적으로는 15초로 되어 있다.
  • job_name: 프로메테우스가 수행할 작업 이름
  • metrics_path: metric 정보를 조회할 수 있는 엔드포인트를 적는다.
  • static_configs
    • targets: metric 수집 요청을 보낼 ip 또는 DNS 주소와 포트를 적는다.

yml 파일을 작성할 때는 들여쓰기가 2칸 임을 유의해야 한다. 작성한 yml 파일을 저장하고 프로메테우스 docker 컨테이너를 재가동해주자. 그리고 상단 탭의 Status를 클릭하고 targets를 클릭한다.

그럼 아래 사진과 같이 정상적으로 프로메테우스가 metric을 수집해오고 있음을 확인할 수 있다. 만약 정보가 안 보이거나 State 값이 UP이 아니면 엔드포인트 주소, IP주소:포트 등을 잘 입력했는지 들여쓰기는 2칸씩 맞췄는지 확인해야 한다. 참고로 리눅스에서 tab으로 들여쓰기를 하면 제대로 작동하지 않는다.

 

yml에서 한 설정이 잘 적용된 건지 확인해 보려면 아래 사진과 같이 Status>Configuration을 클릭해 job이 잘 등록됐는지 확인하면 된다.

그라파나(Grafana)

metric 정보는 기본적으로 문자열 형태이다. 이를 개발자들이 눈으로 확인하기엔 가독성이 좋지 않고 모니터링에 용이하지 않다. 이를 그래프나 다이어그램으로 보기 좋게 만들면 더욱 편하게 모니터링 할 수 있다. 이 때 사용하는 것이 그라파나이다.

 

그라파나도 마찬가지로 docker를 통해 설치한다. 아래 명령어를 설치하면 자동으로 image를 docker hub에서 pull 받고 컨테이너를 실행시킨다. 참고로 --name은 컨테이너의 이름을 지정하는 것이다.

docker run -d -p 3000:3000 --name=grafana grafana/grafana-oss

 

그리고 서버 IP:3000 으로 접속해보면 처음에 로그인 화면이 나올 것이다.

초기 계정정보는 id: admin, password: admin 이다. 로그인하면 비밀번호를 수정하게 되어있는데 적절히 수정하면 된다. 수정을 마쳤다면 아래 사진과 같이 메인화면이 보일 것이다. 아마 사진과 다른 점이 있을텐데 아래 사진은 이미 data source와 dashboard를 구축한 이후에 캡처한 것이므로 해당 단계들이 Complete로 되어 있다.

Data Source 설정

Add your first data source 영역을 클릭해보자. 그럼 이렇게 그라파나에서 지원하는 형식들이 나온다. 우리는 프로메테우스를 이용하고 있으므로 Prometheus를 클릭하자.

 

그럼 아래 사진과 같이 설정화면이 나오는데, 이름은 적당히 지정해주고 Connection에 프로메테우스 서버가 있는 경로를 작성해준다. 예를들어 글에서는 회사서버에 있으므로 http://회사서버IP:9090이다. 화면 아래에 보면 설정 값들이 많이 있을텐데 추가적인 정보는 직접 찾아보면 된다. 맨 아래 쪽에 Seve & test 버튼이 있다. 버튼을 클릭해서 Successfully queried the Prometheus API. 이런 알림이 뜨면 정상적으로 설정이 된 것이다.

Dash board 설정

data source 설정을 마쳤다면 대시보드를 만들 차례이다. 메인화면에서 Create your first dashboard영역을 클릭하자. 그럼 아래와 같은 화면이 나온다. Add visualization을 누르면 data source를 선택하고 직접 PromQL(프로메테우스 전용 쿼리문)을 이용해 대시보드를 만들어야 한다. 너무 시간이 소요되므로 누군가가 만들어 놓은 대시보드를 이용하자. Import dashboard를 클릭한다.

 

그럼 아래처럼 대시보드 json파일을 업로드 하거나 url 또는 id를 입력하는 화면이 나온다. 대시보드는 아래 링크에서 확인할 수 있다. 어플리케이션 유형과 데이터소스에 맞는 대시보드를 선택해 ID를 복사하거나 json파일을 다운로드 받는다. 글에서는 https://grafana.com/grafana/dashboards/4701-jvm-micrometer/ 대시보드로 적용해보겠다.

대시보드 링크: https://grafana.com/grafana/dashboards/

 

ID를 입력하거나 json 파일을 업로드 하고 Load 버튼을 누르면 이렇게 보기 좋은 화면으로 프로메테우스가 수집한 metric 정보를 모니터링 할 수 있다. 각 지표들을 보면서 어플리케이션이 문제가 없는지 메모리 사용량은 괜찮은 지 등을 사전에 탐지해 적절한 조치를 취할 수 있다.

대시보드 화면

기본적인 모니터링 환경 구조

김영한님의 스프링부트 강의에서 등장한 그림

추가 조치 (만약 실제 운영에 도입한다면?)

Metric 정보는 보안 상 매우 민감한 정보를 가지고 있을 수 있다. 따라서 해당 정보에 접근할 수 있는 IP를 제안한다거나 권한이 있는 클라이언트만 접근하게 한다거나 그런 보안조치를 취해야 한다.

프로메테우스 인증 처리

서버에 있는 프로메테우스 URL로 접근 시에 로그인한 클라이언트만 접속할 수 있도록 할 수 있다.

  1. 먼저 문자열을 암호화할 수 있도록 해주는 라이브러리를 다운로드한다.

apt install python3-bcrypt

  1. 아래 코드와 같이 비밀번호를 입력받아 암호화 한 값을 반환하는 python 파일을 만든다. 파일 이름은 적당히 짓는다.
import bcrypt
import getpass

password = getpass.getpass("password: ")
hashed_password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
print(hashed_password.decode())
  1. 파일을 실행시키고 원하는 비밀번호를 입력하면 암호화 된 문자열이 출력될 것이다. 참고로 python 3.xx 이상에서 실행시켜야 한다.
  2. 프로메테우스 설정파일인 prometheus.yml 이 있는 위치에 web.yml 파일을 만들고 아래처럼 입력 후 저장한다.
basic_auth_users:
  아이디: 암호화 된 문자열
  1. 동일한 경로에 docker-compose.yml 파일을 만들고 아래와 같이 적어준다.
version: '3.7'

services:
  prometheus:
    image: prom/prometheus
    volumes:
    - /etc/prometheus/:/etc/prometheus/ # 볼륨 마운트
    command:
    - --config.file=/etc/prometheus/prometheus.yml # prometheus 설정 파일 
    - --web.config.file=/etc/prometheus/web.yml # web 관련 설정파일
    ports:
      - "9090:9090"
  1. 프로메테우스를 재가동한다. docker-compose -d up명령어를 이용하면 docker-compose.yml에 작성한 대로 컨테이너가 실행된다.
  2. 프로메테우스 URL로 접근해보면 ID와 Password를 입력하라는 alert 창이 뜬다. 위에서 설정한 ID와 지정한 Password를 입력하면 메인화면에 진입할 수 있다.

그라파나 Datasource 관련 변경사항

 

프로메테우스로 접근하는 것에 인증 절차를 도입했기 때문에 그라파나에서도 인증 관련 처리를 해주어야 한다. 그라파나 화면 왼쪽에 메뉴를 열고 Connections > Data sources 로 이동한다.

 

그럼 이전에 생성한 Prometheus의 데이터소스가 있을 것이다. 해당 항목을 클릭한다.

 

아래로 좀 내려보면 Authentication 영역이 있을 것이다. 사진은 설정이 되어 있는데 초기에는 select box 에 No Authentication으로 되어 있을 것이다. 이를 Basic authentication으로 변경해주고 프로메테우스의 로그인 정보를 입력하고 저장해준다. 그럼 대시보드에서 확인했을 때 정상적으로 지표들이 보일 것이다.

어플리케이션 서버 보안설정

해당 부분은 여러 방법이 있을 수 있다. 작성시점에 적용한 것은 어플리케이션 서버가 EC2 인스턴스이므로 보안그룹 인바운드에 특정 IP만 액추에이터 엔드포인트에 접근할 수 있도록 설정했다. 즉 프로메테우스가 설치된 서버의 IP만 특정 포트에 접근할 수 있도록 한 것이다. 외부 IP로 접근 시에는 차단되어 메트릭 정보를 볼 수 없다.

마치며

모니터링 환경은 실제 서비스를 운영할 때 필수적인 요소이다. 모니터링을 통해 서비스 장애 시 빠른 조치를 취할 수 있다. 추후 일정 지표가 임계치에 달했을 때 알림을 보내는 것까지 도입해보고자 한다.

참고자료

https://techblog.woowahan.com/9232/

https://toss.tech/article/how-to-work-health-check-in-spring-boot-actuator

https://velog.io/@zihs0822/Prometheus-Security

https://stackoverflow.com/questions/74128720/how-to-add-basic-authentication-for-prometheus-running-on-docker-container-ui

'Infra' 카테고리의 다른 글

springboot 배포 스크립트 이해  (1) 2023.12.22
HTTP란?  (0) 2023.12.14
Auto scaling 작동원리  (1) 2023.11.30